Example #1
0
 def _decodeGETSUBSMessage(self, message):
     """
     From a bencoded GET_SUBS messages, returns its decoded contents.
     
     Decodes and checks for validity a bencoded GET_SUBS messages.
     If the message is succesfully decoded returns the tuple
     (channel_id,infohash,languages).
     
     channel_id is the binary identifier of the chanel that published
     the requested subtitles.
     infohash is the binary identifier of the torrent wich the subtitle
     refers to
     languages is a list of 3 characters language codes, for the languages
     of the requested subtitles
     
     @return: (channel_id,infohash,languages) or None if something is wrong
     """
     assert message[0] == GET_SUBS, SUBS_LOG_PREFIX + \
         "Invalid GET_SUBS Message header: %s" % message[0]
     
     try:
         values = bdecode(message[1:])
     except:
         if DEBUG:
             print >> sys.stderr, SUBS_LOG_PREFIX + "Error bdecoding message"
         return None
     
     if len(values) != 3:
         if DEBUG:
             print >> sys.stderr, SUBS_LOG_PREFIX + "Invalid number of fields in GET_SUBS"
         return None
     channel_id, infohash, bitmask = values[0], values[1], values[2]
     if not validPermid(channel_id):
         if DEBUG:
             print >> sys.stderr, SUBS_LOG_PREFIX + "Invalid channel_id in GET_SUBS"
         return None
     elif not validInfohash(infohash):
         if DEBUG:
             print >> sys.stderr, SUBS_LOG_PREFIX + "Invalid infohash in GET_SUBS"
         return None
     elif not isinstance(bitmask, str) or not len(bitmask)==4:
         if DEBUG:
             print >> sys.stderr, SUBS_LOG_PREFIX + "Invalid bitmask in GET_SUBS"
         return None
     
     try:
         bitmask = binaryStringToUint(bitmask)
         languages = self._languagesUtility.maskToLangCodes(bitmask)
     except:
         if DEBUG:
             print >> sys.stderr, SUBS_LOG_PREFIX + "Invalid bitmask in GET_SUBS"
         return None
     
     return channel_id, infohash, languages
    def _splitChannelcastAndRichMetadataContents(self,enrichedChannelcastMessage):
        '''
        Takes a "enriched" channelcast message (protocol v.14 - the one with
        the 'rich_metadata' field inside), and extracts the rich metadata info
        from it
        
        @param enrichedChannelcastMessage: a channelcast message from protocol 
                                           version 14
                                           
        @return: a list tuples like (MetadataDTO, haveMask) instances extracted from the message. or
                 an empty list if nothing. Along with it there is a list
                 of the size of each entry in the message that is used to 
                 collect stats. if the announceStatsLog is disable this list
                 will always be empty
        '''
        if not isinstance(enrichedChannelcastMessage, dict):
            if DEBUG:
                print >> sys.stderr, "Invalid channelcast message received"
            return None
        
        rmdData = list()
        
        sizeList = list()
        for signature in iter(enrichedChannelcastMessage):
            msg = enrichedChannelcastMessage[signature]
            
            if 'rich_metadata' in msg.keys():
                metadataEntry = msg['rich_metadata']
                if metadataEntry is None \
                    or not validMetadataEntry(metadataEntry):
                    continue
                else:
                    channel_id = msg['publisher_id']
                    infohash = msg['infohash']

                    # rebuilding the serialized MetadataDTO structure
                    # that was broken in self.addRichMetadataContent
                    binary_havemask = metadataEntry.pop(-1)
                    havemask = binaryStringToUint(binary_havemask)
                    
                    metadataEntry.insert(0,infohash)
                    metadataEntry.insert(0,channel_id)
                    try:
                        curMetadataDTO = deserialize(metadataEntry)
                    except SerializationException,e:
                        if DEBUG:
                            print >> sys.stderr, "Invalid metadata message content: %s" % e
                        continue
                    
                    rmdData.append((curMetadataDTO,havemask))
Example #3
0
def deserialize(packed):
    assert packed is not None

    message = packed
    if len(message) != 7:
        raise SerializationException("Wrong number of fields in metadata")

    channel = message[0]
    infohash = message[1]
    description = message[2].decode("utf-8")
    timestamp = message[3]
    binarybitmask = message[4]
    bitmask = binaryStringToUint(binarybitmask)
    listOfChecksums = message[5]
    signature = message[6]
    subtitles = _createSubtitlesDict(bitmask, listOfChecksums)

    dto = MetadataDTO(channel, infohash, timestamp, description, subtitles, signature)
    if not dto.verifySignature():
        raise SerializationException("Invalid Signature!")
    return dto
Example #4
0
 def test_packData(self):
     badInfohash = str2bin("GEh/o8rtTLB1wZJzFcSZSS4u9qo=")
     dto = MetadataDTO(test_perm_id, badInfohash)
     dto.description = u"Sample Description\u041f"
     
     bla = dto._packData()
     decoded = bdecode(bla)
     
     self.assertTrue(len(decoded) == 6)
     decodedChannelId = decoded[0]
     decodedInfohash = decoded[1]
     decodedDescription = decoded[2].decode("utf-8")
     decodedTimestamp = decoded[3]
     bin_decodedBitmask = decoded[4]
     decodedBitmask = binaryStringToUint(bin_decodedBitmask)
     self.assertEquals(dto.channel, decodedChannelId)
     self.assertEquals(dto.infohash, decodedInfohash)
     self.assertEquals(dto.description,decodedDescription)
     self.assertAlmostEquals(dto.timestamp,decodedTimestamp)
     self.assertEquals(0,decodedBitmask)
     self.assertEquals(0,len(decoded[5]))
Example #5
0
 def _decodeSUBSMessage(self, message):
     """
     From a bencoded SUBS message, returns its decoded contents.
     
     Decodes and checks for validity a bencoded SUBS message.
     If the message is succesfully decoded returns the tuple
     (channel_id, infohash, bitmask, contentsDictionary )
     
     channel_id is the binary identifier of the chanel that published
     the requested subtitles.
     infohash is the binary identifier of the torrent wich the subtitle
     refers to
     contentsDictionary is a dictionary having each entry like 
     {langCode : subtitleContents}.
     
     @return: the above described tuple, or None if something is wrong
     """
     assert message[0] == SUBS, SUBS_LOG_PREFIX + \
         "Invalid SUBS Message header: %s" % message[0]
         
     try:
         values = bdecode(message[1:])
     except:
         if DEBUG:
             print >> sys.stderr, SUBS_LOG_PREFIX + "Error bdecoding SUBS message"
         return None
     
     if len(values) != 4:
         if DEBUG:
             print >> sys.stderr, SUBS_LOG_PREFIX + "Invalid number of fields in SUBS"
         return None
     channel_id, infohash, bitmask, contents = values[0], values[1], \
         values[2], values[3]
     
     if not validPermid(channel_id):
         if DEBUG:
             print >> sys.stderr, SUBS_LOG_PREFIX + "Invalid channel_id in SUBS"
         return None
     elif not validInfohash(infohash):
         if DEBUG:
             print >> sys.stderr, SUBS_LOG_PREFIX + "Invalid infohash in SUBS"
         return None
     elif not isinstance(bitmask, str) or not len(bitmask) == 4:
         if DEBUG:
             print >> sys.stderr, SUBS_LOG_PREFIX + "Invalid bitmask in SUBS"
         return None
     
     try:
         bitmask = binaryStringToUint(bitmask)
         languages = self._languagesUtility.maskToLangCodes(bitmask)
     except:
         if DEBUG:
             print >> sys.stderr, SUBS_LOG_PREFIX + "Invalid bitmask in SUBS"
         return None
     
     if not isinstance(contents, list):
         if DEBUG:
             print >> sys.stderr, SUBS_LOG_PREFIX + "Invalid contents in SUBS"
         return None
     if len(languages) != len(contents):
         if DEBUG:
             print >> sys.stderr, SUBS_LOG_PREFIX + "Bitmask and contents do not match in"\
                   " SUBS"
         return None
     
     numOfContents = len(languages)
     if numOfContents == 0:
         if DEBUG:
             print >> sys.stderr, SUBS_LOG_PREFIX + "Empty message. Discarding."
         return None
     
     
     contentsDictionary = dict()
     for i in range(numOfContents):
         lang = languages[i]
         subtitle = contents[i]
         if not isinstance(subtitle,unicode):
             try:
                 subtitle = unicode(subtitle)
             except:
                 return None
         if len(subtitle) <= self._maxSubSize:
             contentsDictionary[lang] = subtitle
         else:
             #drop that subtitle
             continue
         
     bitmask = self._languagesUtility.langCodesToMask(contentsDictionary.keys())
         
     
     return channel_id, infohash, bitmask, contentsDictionary