def decode_block(self, data, size): if size > len(data): size = len(data) done = 0 block = ContentBlock() while done < size: start = done if data[done] == 0xdd: cidlen, done = valuecodecs.parse_varuint(data, done+1) sumlen, done = valuecodecs.parse_varuint(data, done) cid = data[done:done+cidlen] cksum = data[done:done+sumlen] done += max(cidlen, sumlen) first = ( data[done] + data[done+1] * 0x100 + data[done+2] * 0x10000 + data[done+3] * 0x1000000) done += 4 last = ( data[done] + data[done+1] * 0x100 + data[done+2] * 0x10000 + data[done+3] * 0x1000000) done += 4 if last != first: self._logger.warn('deprecated', 'item.last') item = ItemContent(cid, cksum, first) if done > size: raise InvalidDataError( 'Content item overran block end at ' + str(done)) while data[done] in (0xa0, 0xa1): self._logger.warn('deprecated', 'item.update') done += 1 checksum = None if data[done-1] == 0xa1: checksum = data[done:done+sumlen] done += sumlen first = ( data[done] + data[done+1] * 0x100 + data[done+2] * 0x10000 + data[done+3] * 0x1000000) done += 4 last = ( data[done] + data[done+1] * 0x100 + data[done+2] * 0x10000 + data[done+3] * 0x1000000) done += 4 if done > size: raise InvalidDataError( 'Content item overran block end at ' + str(done)) block._items.append((data[start:done], item)) block._datasize += done - start elif data[done] == 0: if data[done:size].strip(b'\x00'): raise InvalidDataError('Trailing garbage') done = size else: raise InvalidDataError('Unknown data item: ' + str(data[done])) return block
def decode_block(self, data, size): if size > len(data): size = len(data) done = 0 block = BackupBlock() while done < size: item = None start = done if data[done] in (0x90, 0x92): itemtype = data[done] done += 1 dirid, done = valuecodecs.parse_varuint(data, done) parent, done = valuecodecs.parse_varuint(data, done) namelen, done = valuecodecs.parse_varuint(data, done) name = data[done:done+namelen] done += namelen item = ItemDirectory(dirid, parent, name) if itemtype == 0x92: extra_data, done = valuecodecs.parse_varuint(data, done) item.set_extra_data(extra_data) itemdata = data[start:done] elif data[done] in (0x91, 0x93, 0x94): itemtype = data[done] done += 1 parent, done = valuecodecs.parse_varuint(data, done) namelen, done = valuecodecs.parse_varuint(data, done) name = data[done:done+namelen] done += namelen cidlen, done = valuecodecs.parse_varuint(data, done) cid = data[done:done+cidlen] done += cidlen filesize, done = valuecodecs.parse_varuint(data, done) mtime_year = data[done] + data[done+1] * 256 mtime_second = ( data[done+2] + data[done+3] * 0x100 + data[done+4] * 0x10000) if data[done+5] >= 0x80: mtime_second += 0x1000000 mtime_ns = ( (data[done+5] & 0x3f) + data[done+6] * 0x40 + data[done+7] * 0x4000 + data[done+8] * 0x400000) done += 9 if itemtype in (0x91, 0x93): item = ItemFile( parent, name, cid, filesize, (mtime_year, mtime_second, mtime_ns)) elif itemtype == 0x94: ftype = self._filetypechars.get(data[done]) if ftype is None: raise AssertionError( 'Unknown filetype: ' + str(data[done])) done += 1 item = ItemSpecialFile( ftype, parent, name, cid, filesize, (mtime_year, mtime_second, mtime_ns)) else: raise AssertionError('unreachable') if itemtype in (0x93, 0x94): extra, done = valuecodecs.parse_varuint(data, done) item.set_extra_data(extra) itemdata = data[start:done] elif data[done] == 0x21: done += 1 length, done = valuecodecs.parse_varuint(data, done) end = done + length kvid, done = valuecodecs.parse_varuint(data, done) kv = data[done:end] done = end key, value = kv.split(b':', 1) item = ItemKeyValue(kvid, key, value) itemdata = data[start:done] elif data[done] == 0x22: done += 1 length, done = valuecodecs.parse_varuint(data, done) end = done + length xid, done = valuecodecs.parse_varuint(data, done) kvids = [] while done < end: kvid, done = valuecodecs.parse_varuint(data, done) kvids.append(kvid) assert done == end item = ItemExtraDef(xid, tuple(kvids)) itemdata = data[start:done] elif data[done] == 0: if data[done:size].strip(b'\x00'): raise InvalidDataError('Trailing garbage') done = size else: raise InvalidDataError('Unknown data item') if item is not None: block._items.append((itemdata, item)) block._datasize += len(itemdata) return block