# Written by bram cohen # see license.txt for license information # filename: btfield.py btformats.py
# btfield.py # Readword Diary: 2004-9-1 author: # author: zfive5 (Drunk Malaysia [Lonely Boat Weng, Single Fishing Hanjiang Snow]) # 注: This file is mainly byte Transformation between the bit
# Function: Mainly the list of implementations BITS bits to Byte transformation # parameters: 1 logical list, for example: [1, 1, 0, 1, 1, 1, 0, 1] # Return: BYTE stream, for example: 'a / x00 '# Effect: # >>> Booleans_to_bitfield ([0, 1, 1, 0, 0, 0, 1]) #' a '# >>> Booleans_to_bitfield ([0, 1, 1, 0, 0 , 0, 0, 1, 0]) # 'a / x00' # Def booleans_to_bitfield (booleans): r = [] for i in xrange (0, len (booleans), 8): v = 0 p = 0x80 for J In Booleans [I: I 8]: IF J: V | = P >> = 1 R.Append (chr (v)) Return '' .join (r)
# Function: The main completion of the transformation of the byte to BYTE stream to the Bits list: BYTE stream, byte, Byte,, for example: 'a / x00' # Return: Logic Bits list, for example: [false, true, true, false, False, False, False, True] # Effect: # >>> Bitfield_to_Booleans ('A', 8) # [false, true, true, false, false, false, false, true] # def bitfield_to_booleans (bitfield, l): Extra = len (bitfield) * 8 - l if extra <0 or extra> = 8: return none r = [] for c in bitfield: v = ord (c) for i in xrange (8): if v & 0x80! = 0: R.Append (true) Else: R.Append (false) V << = 1 if extra> 0: if r [-extra:]! = [0] * Extra: Return None del R [-extra: ] Return R
# Function: Test 1 Def Test_basic (): x = [1, 1, 1, 0, 0, 0, 1, 1, 1] y = [1, 1, 1, 0, 0, 0, 1, 1] For a in [x, y, []]: assert bitfield_to_booleans (booleans_to_bitfield (a), len (a)) == a # function: Test 2 Def Test_too_long (): assert bitfield_to_booleans ('ab', 8) == NONE # Function: Test 3 DEF TEST_TOO_SHORT (): Assert Bitfield_to_Booleans ('A', 9) == None # Function: Test 4 Def Test_nonzero_in_excess (): Assert Bitfield_to_Booleans (CHR (0xFF), 7) == NONE
# Written by bram cohen # see license.txt for license information
# btformats.py
From Types Import StringType, LongType, INTTYPE, LISTTYPE, DICTTYPE from RE IMPORT COMPER
REG = compile (r '^ [^ ////. ~] [^ ///] * $')
INTS = [longType, INTTYPE]
# Function: This is mainly to check if the seed file INFO information is legal, including its sub-information, # 不 不 不 异, from this file we can see the INFO of the seed file # info (dicttype) {# 'Piecelength': INTS (greater than zero), # 'PIECES': StringType (integer multiple of the length), # 'name': StringType (not a non-file name character like / *), # ' Length ': INTS (greater than zero, for a single file) #} # (dicttype) {#' Piecelength ': INTS (greater than zero), #' PIECES ': StringType (integer multiple of the length of 20 bytes), # 'Name': StringType (not a non-file name character like / *), # 'files': [# (dicttype) # {# 'Length': INTS (greater than zero) # 'Path' ( Listtype): [(for example: "1", "2", "4.txt" representative: "/ 1/2 / 4.txt" # StringType, # stringtype, # stringtype, # .... #] #} , # # (Dicttype) {# 'length': INTS (greater than zero) # 'Path' (Listtype) : [# StringType, # StringType, # StringType, # .... #] #} # .... #] #} # Here the order may be a seed file with a DEF CHECK_INFO (INFO): if Type (INFO) ! = Dices: Raise ValueError, 'Bad MetaInfo - Not a Dictionary' PIECES = INFO.GET ('PIECES') f Type (PIECES)! = StringType or Len (PIECES)% 20! = 0: Raise ValueError, 'Bad MetaInfo - BAD PIECES Key '
piecelength = info.get ( 'piece length') if type (piecelength) not in ints or piecelength <= 0: raise ValueError, 'bad metainfo - illegal piece length' name = info.get ( 'name') if type (name )! = StringType: Raise ValueError, 'Bad Metainfo - Bad Name' if NotregoMatch (Name): Raise ValueError, 'Name% S Disloaded for Security Reasons'% Name if info.has_key ('files') == Info .has_key ('Length'): Raise ValueError, 'Single / Multiple File Mix' IF Info.has_Key ('Length'): length = info.get ('length') if Type (Length) Not in Ints or Length <0 : Raise ValueError, 'Bad Metainfo - Bad Length' Else: Files = Info.get ('files') ife (files)! = ListType: Raise ValueError For F in Files: if Type (f)! = DictType: Raise ValueError , 'Bad MetaInfo - Bad file value' length = f.get ('length') if Type (Length) Not in INTS or Length <0: Raise ValueError, 'Bad Metainfo - Bad Length' Path = F.Get ('Path') if Type (Path)! = ListType or Path == []: Raise ValueError, 'Bad MetaInfo - Bad Path' for PCh: IF Type (P)! = StringType: Raise ValueError, 'Bad MetaInfo - Bad Path Dir' IF NOTEG.MATCH (P): Raise ValueError, 'Path% S Disallowed for Security Reasons'
% P for i in xrange (len (files)): for J in xrange (i): if files [i] ['Path'] == files [j] ['Path']: raise valueerror, 'Bad metainfo - Duplicate Path '# Function: This is mainly to check if the seed file Message information is legal, including its sub-information, # 不 不 不 异 异, from this file we can see the Message structure of the seed file # This is also seed Starting place # message (dices): {check_info (message.get ('Info')) 同} #} # Here the order may be a seed file to enter the DEF Check_message (message): if Type (Message)! = DicesPe: Raise ValueError Check_info (Message.Get ('INFO')) ife (message.get ('announce'))! = StringType: Raise ValueError
# Function: This is mainly legal, including its sub-information, about this structure, I haven't read the level you can understand, first play a question mark here? ? ? ? ? # Message (dices) {# 'Failure Reason': {CHECK_INFO (Message.Get ('Info')): # [# (DICTTYPE) # {# 'ip': stringType, # [# ": StringType 'Port': INTS (greater than zero), # 'peer id': StringType (id) == 20 Here I guess it is also SHA) #}, # (dicttype) # {# 'ip': StringType, # ' Port ': INTS (greater than zero), #' peer id ': StringType (id) == 20 Here I guess it is also SHA) #} # ... # #] #' interval ': INTS (greater than zero), # 'Min interval': INTS (greater than zero), # 'tracker id': stringtype, # 'num pess': INTS (greater than zero), #' DONE Peers': INTS (greater than zero), # 'la St ': INTS (greater than zero) #} # Here the order may be the actual order does not go out to def check_peers: if Type (Message)! = DictType: raise valueerror if message.has_key (' fiveure ": if Type Message ['Failure Reason'])! = StringType: Raise ValueError Return Peers = Message.Get ('Peers') if Type (Peers)! = LISTTYPE: RAISE VALUEERROR for P in Peers: if Type (P)! =
DictType: Raise ValueError if Type (P.Get ('ip'))! = StringType: Raise ValueError Port = P.Get ('Port') if Type (port) Not in INTS OR P <= 0: raise valueerror ID = P.GET ('peer id "f type (id)! = stringType or Len (ID)! = 20: raise.get (' Interval ', 1) if Type (Interval) Not in INTS ORTARTAL INTERVAL <= 0: raise.get ('min interval', 1) if Type (minint) Not in INTS OR minint <= 0: raise valueError if Type ('Tracker ID ") )! = StringType: raising valueerror npeers = message.get ('Num Peers', 0) IF Type (NPEERS) Not in INTS OR NPEERS <0: raise value ValueError DPEERS = Message.Get ('Done Peers', 0) IF Type (DPEERS) Not in INTS or DPEERS <0: raste valueerror last = message.get ('last', 0) if Type (Last) Not in INTS or Last <0: raise valueerror # Write here to understand the BT seed file Structure !! # (To be continued )