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))
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
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]))
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