def test_from_stream(self): ae = self.assertEqual ar = self.assertRaises data_le = b"\x00\x0E\x15\x91\xC4\x95\xC2\x01" data_be = data_le[::-1] data_bad = b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" stream = ByteIStream(data_le) filetime1 = FILETIMETodatetime.from_stream(stream, byte_order=LITTLE_ENDIAN) filetime2 = FILETIMETodatetime.from_stream(stream, 0, LITTLE_ENDIAN) stream = ByteIStream(data_be) filetime3 = FILETIMETodatetime.from_stream(stream, byte_order=BIG_ENDIAN) filetime4 = FILETIMETodatetime.from_stream(stream, 0, BIG_ENDIAN) ae(filetime1, datetime(2002, 11, 27, 3, 25, 0)) ae(filetime2, datetime(2002, 11, 27, 3, 25, 0)) ae(filetime3, datetime(2002, 11, 27, 3, 25, 0)) ae(filetime4, datetime(2002, 11, 27, 3, 25, 0)) stream = ByteIStream(data_bad) ar(ValueError, FILETIMETodatetime.from_stream, stream)
def test_from_stream(self): ae = self.assertEqual ar = self.assertRaises data_le = b"\x00\x0E\x15\x91\xC4\x95\xC2\x01" data_be = data_le[::-1] data_bad = b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" stream = ByteIStream(data_le) filetime1 = FILETIMETodatetime.from_stream( stream, byte_order=LITTLE_ENDIAN ) filetime2 = FILETIMETodatetime.from_stream(stream, 0, LITTLE_ENDIAN) stream = ByteIStream(data_be) filetime3 = FILETIMETodatetime.from_stream( stream, byte_order=BIG_ENDIAN ) filetime4 = FILETIMETodatetime.from_stream(stream, 0, BIG_ENDIAN) ae(filetime1, datetime(2002, 11, 27, 3, 25, 0)) ae(filetime2, datetime(2002, 11, 27, 3, 25, 0)) ae(filetime3, datetime(2002, 11, 27, 3, 25, 0)) ae(filetime4, datetime(2002, 11, 27, 3, 25, 0)) stream = ByteIStream(data_bad) ar(ValueError, FILETIMETodatetime.from_stream, stream)
def from_stream(cls, stream, offset=None): """Creates a :class:`DirEntry` object from a stream. :type stream: :class:`lf.dec.IStream` :param stream: A stream that contains the directory entry. :type offset: ``int`` :param offset: The start of the directory entry in :attr:`stream`. :rtype: :class:`DirEntry` :returns: The corresponding :class:`DirEntry` object. """ if offset is not None: stream.seek(offset, SEEK_SET) # end if values = dir_entry.from_buffer_copy(stream.read(128)) name = bytes(values.name) if values.name_size <= 64: name = name[:values.name_size] # end if new_name = name.decode("utf_16_le", "ignore") if new_name: name = new_name.split("\x00", 1)[0] # end if clsid = CLSIDToUUID.from_ctype(values.clsid) btime = values.btime try: btime = FILETIMETodatetime.from_ctype(btime) except (ValueError, TypeError): btime = (btime.hi << 32) | btime.lo # end try mtime = values.mtime try: mtime = FILETIMETodatetime.from_ctype(mtime) except (ValueError, TypeError): mtime = (mtime.hi << 32) | mtime.lo # end try return DirEntry(( name, values.name_size, values.type, values.color, values.left_sid, values.right_sid, values.child_sid, clsid, values.state, btime, mtime, values.stream_sect_offset, values.stream_size ))
def from_stream(cls, stream, offset=None): """Creates a :class:`DirEntry` object from a stream. :type stream: :class:`lf.dec.IStream` :param stream: A stream that contains the directory entry. :type offset: ``int`` :param offset: The start of the directory entry in :attr:`stream`. :rtype: :class:`DirEntry` :returns: The corresponding :class:`DirEntry` object. """ if offset is not None: stream.seek(offset, SEEK_SET) # end if values = dir_entry.from_buffer_copy(stream.read(128)) name = bytes(values.name) if values.name_size <= 64: name = name[:values.name_size] # end if new_name = name.decode("utf_16_le", "ignore") if new_name: name = new_name.split("\x00", 1)[0] # end if clsid = CLSIDToUUID.from_ctype(values.clsid) btime = values.btime try: btime = FILETIMETodatetime.from_ctype(btime) except (ValueError, TypeError): btime = (btime.hi << 32) | btime.lo # end try mtime = values.mtime try: mtime = FILETIMETodatetime.from_ctype(mtime) except (ValueError, TypeError): mtime = (mtime.hi << 32) | mtime.lo # end try return DirEntry((name, values.name_size, values.type, values.color, values.left_sid, values.right_sid, values.child_sid, clsid, values.state, btime, mtime, values.stream_sect_offset, values.stream_size))
def test_from_int(self): ae = self.assertEqual ar = self.assertRaises filetime = FILETIMETodatetime.from_int(0x01C295C491150E00) ae(filetime, datetime(2002, 11, 27, 3, 25, 0)) ar(ValueError, FILETIMETodatetime.from_int, 0xFFFFFFFFFFFFFFFF)
def test_from_ctype(self): ae = self.assertEqual ar = self.assertRaises data = b"\x00\x0E\x15\x91\xC4\x95\xC2\x01" data_bad = b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" filetime = filetime_le.from_buffer_copy(data) filetime = FILETIMETodatetime.from_ctype(filetime) ae(filetime, datetime(2002, 11, 27, 3, 25, 0)) filetime = filetime_le.from_buffer_copy(data_bad) ar(ValueError, FILETIMETodatetime.from_ctype, filetime)
def filetime_to_datetime(filetime): """Converts a Microsoft FILETIME timestamp to a Python datetime object. :parameters: The time in FILETIME format. :raises: ValueError If filetime is an invalid value. :rtype: datetime :returns: The timestamp as a datetime object. """ return FILETIMETodatetime.from_int(filetime)
def from_ctype(cls, ctype): """ Creates a :class:`INFO2Item` object from a ctype. :type ctype: :class:`~lf.win.shell.recyclebin.ctypes.info2_item` :param ctype: An info2_item object. :rtype: :class:`INFO2Item` :returns: The corresponding :class:`INFO2Item` object. """ if ctype.name_asc[0] == 0: exists = False start = 1 else: exists = True start = 0 # end if name_asc = bytes(ctype.name_asc) null_term = name_asc.find(b"\x00", start) if null_term != -1: name_asc = name_asc[:null_term] # end if name_uni = bytes(ctype.name_uni) new_name_uni = _utf16_le_decoder(name_uni, "ignore")[0] if new_name_uni: name_uni = new_name_uni.split("\x00", 1)[0] else: name_uni = name_uni.split(b"\x00", 1)[0] # end if try: dtime = FILETIMETodatetime.from_ctype(ctype.dtime) except ValueError: dtime = (ctype.dtime.hi << 32) | ctype.dtime.lo # end try return cls(( name_asc, ctype.id, ctype.drive_num, dtime, ctype.file_size, name_uni, exists ))
def from_stream(cls, stream, offset=None): """Creates a :class:`CatalogEntry` object from a stream. :type stream: :class:`~lf.dec.IStream` :param stream: A stream that contains the structure. :type offset: ``int`` :param offset: The start of the structure in :attr:`stream`. :rtype: :class:`CatalogEntry` :returns: The corresponding :class:`CatalogEntry` object. """ if offset is not None: stream.seek(offset, SEEK_SET) else: offset = stream.tell() # end if entry = catalog_entry_header.from_buffer_copy(stream.read(16)) if entry.size > 16: file_name = stream.read(entry.size - 16) new_file_name = _utf16_le_decoder(file_name, "ignore")[0] if new_file_name: file_name = new_file_name.split("\x00", 1)[0] # end if else: file_name = None # end if try: mtime = FILETIMETodatetime.from_ctype(entry.mtime) except (TypeError, ValueError): mtime = (entry.mtime.hi << 32) | entry.mtime.lo # end try stream_name = "{0}".format(entry.id) stream_name = stream_name[::-1] return cls((entry.size, entry.id, mtime, file_name, stream_name))
def from_ctype(cls, ctype): """ Creates a :class:`INFO2Item` object from a ctype. :type ctype: :class:`~lf.win.shell.recyclebin.ctypes.info2_item` :param ctype: An info2_item object. :rtype: :class:`INFO2Item` :returns: The corresponding :class:`INFO2Item` object. """ if ctype.name_asc[0] == 0: exists = False start = 1 else: exists = True start = 0 # end if name_asc = bytes(ctype.name_asc) null_term = name_asc.find(b"\x00", start) if null_term != -1: name_asc = name_asc[:null_term] # end if name_uni = bytes(ctype.name_uni) new_name_uni = _utf16_le_decoder(name_uni, "ignore")[0] if new_name_uni: name_uni = new_name_uni.split("\x00", 1)[0] else: name_uni = name_uni.split(b"\x00", 1)[0] # end if try: dtime = FILETIMETodatetime.from_ctype(ctype.dtime) except ValueError: dtime = (ctype.dtime.hi << 32) | ctype.dtime.lo # end try return cls((name_asc, ctype.id, ctype.drive_num, dtime, ctype.file_size, name_uni, exists))
def convert_timestamp(timestamp, timestamp_type): """Converts a timestamp from an integer into a datetime object.""" if timestamp_type == "posix": new_timestamp = POSIXTimeTodatetime.from_int(timestamp) elif timestamp_type == "dosdate": new_timestamp = DOSDateTimeTodatetime.from_ints(timestamp, None).date() elif timestamp_type == "dostime": new_timestamp = DOSDateTimeTodatetime.from_ints(None, timestamp).time() elif timestamp_type == "filetime": new_timestamp = FILETIMETodatetime.from_int(timestamp) elif timestamp_type == "variant": new_timestamp = VariantTimeTodatetime.from_float(timestamp) else: raise ValueError("Unknown timestamp type: {0}".format(timestamp_type)) # end if return new_timestamp
def test__init__(self): ae = self.assertEqual ar = self.assertRaises tdb = self.tdb catalog_entries = [ CatalogEntry(( 0x2E, 1, FILETIMETodatetime.from_int(0x01CAA3B750989500), "zoolemur1.jpg", "1" )), CatalogEntry(( 0x56, 2, FILETIMETodatetime.from_int(0x01CAA3B74F676800), "Copy (2) of danger-sign-shock.jpg", "2" )), CatalogEntry(( 0x5E, 3, FILETIMETodatetime.from_int(0x01CAA3B74E363B00), "Copy (2) of Kookaburra_at_Marwell.jpg", "3" )), CatalogEntry(( 0x54, 4, FILETIMETodatetime.from_int(0x01CAA3B74F676800), "Copy (2) of Makari_the_Tiger.jpg", "4" )), CatalogEntry(( 0x4A, 5, FILETIMETodatetime.from_int(0x01CAA3B750989500), "Copy (2) of prairiedogs.jpg", "5" )), CatalogEntry(( 0x46, 6, FILETIMETodatetime.from_int(0x01CAA3B750989500), "Copy (2) of zoolemur1.jpg", "6" )), CatalogEntry(( 0x4E, 7, FILETIMETodatetime.from_int(0x01CAA3B74F676800), "Copy of danger-sign-shock.jpg", "7" )), CatalogEntry(( 0x56, 8, FILETIMETodatetime.from_int(0x01CAA3B74E363B00), "Copy of Kookaburra_at_Marwell.jpg", "8" )), CatalogEntry(( 0x4C, 9, FILETIMETodatetime.from_int(0x01CAA3B74F676800), "Copy of Makari_the_Tiger.jpg", "9" )), CatalogEntry(( 0x42, 10, FILETIMETodatetime.from_int(0x01CAA3B750989500), "Copy of prairiedogs.jpg", "01" )), CatalogEntry(( 0x3E, 11, FILETIMETodatetime.from_int(0x01CAA3B750989500), "Copy of zoolemur1.jpg", "11" )), CatalogEntry(( 0x3E, 12, FILETIMETodatetime.from_int(0x01CAA3B74F676800), "danger-sign-shock.jpg", "21" )), CatalogEntry(( 0x46, 13, FILETIMETodatetime.from_int(0x01CAA3B74E363B00), "Kookaburra_at_Marwell.jpg", "31" )), CatalogEntry(( 0x3C, 14, FILETIMETodatetime.from_int(0x01CAA3B74F676800), "Makari_the_Tiger.jpg", "41" )), CatalogEntry(( 0x32, 15, FILETIMETodatetime.from_int(0x01CAA3B750989500), "prairiedogs.jpg", "51" )), ] catalog = Catalog((96, 96, 15, catalog_entries)) md5_hashes = { 8: "41783146a36b0df9c0e450715439fa55", 4: "8524c25aab60e2a76ecb3fd1215c52fa", 2: "ca70cbc23a7e39fbeba90f027fef6e5c", 1: "925405772966a6c3bbcedec92c2cb29a", 3: "41783146a36b0df9c0e450715439fa55", 6: "925405772966a6c3bbcedec92c2cb29a", 5: "6bbeb0387e4f44aac21d582a1f2a467d", 7: "ca70cbc23a7e39fbeba90f027fef6e5c", 12: "ca70cbc23a7e39fbeba90f027fef6e5c", 10: "6bbeb0387e4f44aac21d582a1f2a467d", 9: "8524c25aab60e2a76ecb3fd1215c52fa", 11: "925405772966a6c3bbcedec92c2cb29a", 14: "8524c25aab60e2a76ecb3fd1215c52fa", 13: "41783146a36b0df9c0e450715439fa55", 15: "6bbeb0387e4f44aac21d582a1f2a467d" } ae(tdb.catalog, catalog) ae(tdb.thumbnails.keys(), md5_hashes.keys()) for (key, hash) in md5_hashes.items(): ae(md5(tdb.thumbnails[key].data).hexdigest(), hash) # end for ar( KeyError, ThumbsDb, self.cfb,"thisisnotthecatalogyouarelookingfor" )
def test_from_properties(self): ae = self.assertEqual blair_si_stream = self.blair_si_stream sample_si_stream = self.sample_si_stream blair_props = list() sample_props = list() control_metadata = SummaryInfo(( 0x4E4, None, None, None, set([ "code_page", "title", "subject", "author", "keywords", "comments", "template", "last_author", "rev", "edit_time_tot", "print_time", "btime", "mtime", "page_count", "word_count", "char_count", "app_name", "security" ]), "Iraq- ITS INFRASTRUCTURE OF CONCEALMENT, DECEPTION AND " "INTIMIDATION", "", "default", "", "", "Normal.dot", "MKhan", "4", FILETIMETodatetime.from_int(0x6B49D200), FILETIMETodatetime.from_int(0x01C2C8A7296E8E00), FILETIMETodatetime.from_int(0x01C2CB66F65A2200), FILETIMETodatetime.from_int(0x01C2CB75E8F86400), 1, 0xF23, 0x564A, None, "Microsoft Word 8.0", 0, )) property_set_stream = Builder.build(blair_si_stream) blair_properties = property_set_stream.property_set_0.properties metadata = SummaryInfo.from_properties(blair_properties) ae(metadata, control_metadata) sample_si_stream.seek(0x1F8, SEEK_SET) cf_data = sample_si_stream.read(0x254A6) control_metadata = SummaryInfo(( 0x4E4, None, None, None, set([ "code_page", "title", "subject", "author", "keywords", "comments", "template", "last_author", "rev", "edit_time_tot", "btime", "mtime", "page_count", "word_count", "char_count", "thumbnail", "app_name", "security" ]), "title_value", "subject_value", "author_value", "keyword0 keyword1", "Comments in the comments box", "Normal", "lftest2", "24", FILETIMETodatetime.from_int(0x1176592E00), None, FILETIMETodatetime.from_int(0x01CAA3C0F0A6EC00), FILETIMETodatetime.from_int(0x01CAA3D361570400), 7, 0xAA, 0x0550, VtThumbnailValue((0x0254B4, cf_data, 0xFFFFFFFF, 3)), "Microsoft Office Word", 8, )) property_set_stream = Builder.build(sample_si_stream, 0) sample_properties = property_set_stream.property_set_0.properties metadata = SummaryInfo.from_properties(sample_properties) ae(metadata, control_metadata)
def test__init__(self): ae = self.assertEqual ar = self.assertRaises tdb = self.tdb catalog_entries = [ CatalogEntry( (0x2E, 1, FILETIMETodatetime.from_int(0x01CAA3B750989500), "zoolemur1.jpg", "1")), CatalogEntry( (0x56, 2, FILETIMETodatetime.from_int(0x01CAA3B74F676800), "Copy (2) of danger-sign-shock.jpg", "2")), CatalogEntry( (0x5E, 3, FILETIMETodatetime.from_int(0x01CAA3B74E363B00), "Copy (2) of Kookaburra_at_Marwell.jpg", "3")), CatalogEntry( (0x54, 4, FILETIMETodatetime.from_int(0x01CAA3B74F676800), "Copy (2) of Makari_the_Tiger.jpg", "4")), CatalogEntry( (0x4A, 5, FILETIMETodatetime.from_int(0x01CAA3B750989500), "Copy (2) of prairiedogs.jpg", "5")), CatalogEntry( (0x46, 6, FILETIMETodatetime.from_int(0x01CAA3B750989500), "Copy (2) of zoolemur1.jpg", "6")), CatalogEntry( (0x4E, 7, FILETIMETodatetime.from_int(0x01CAA3B74F676800), "Copy of danger-sign-shock.jpg", "7")), CatalogEntry( (0x56, 8, FILETIMETodatetime.from_int(0x01CAA3B74E363B00), "Copy of Kookaburra_at_Marwell.jpg", "8")), CatalogEntry( (0x4C, 9, FILETIMETodatetime.from_int(0x01CAA3B74F676800), "Copy of Makari_the_Tiger.jpg", "9")), CatalogEntry( (0x42, 10, FILETIMETodatetime.from_int(0x01CAA3B750989500), "Copy of prairiedogs.jpg", "01")), CatalogEntry( (0x3E, 11, FILETIMETodatetime.from_int(0x01CAA3B750989500), "Copy of zoolemur1.jpg", "11")), CatalogEntry( (0x3E, 12, FILETIMETodatetime.from_int(0x01CAA3B74F676800), "danger-sign-shock.jpg", "21")), CatalogEntry( (0x46, 13, FILETIMETodatetime.from_int(0x01CAA3B74E363B00), "Kookaburra_at_Marwell.jpg", "31")), CatalogEntry( (0x3C, 14, FILETIMETodatetime.from_int(0x01CAA3B74F676800), "Makari_the_Tiger.jpg", "41")), CatalogEntry( (0x32, 15, FILETIMETodatetime.from_int(0x01CAA3B750989500), "prairiedogs.jpg", "51")), ] catalog = Catalog((96, 96, 15, catalog_entries)) md5_hashes = { 8: "41783146a36b0df9c0e450715439fa55", 4: "8524c25aab60e2a76ecb3fd1215c52fa", 2: "ca70cbc23a7e39fbeba90f027fef6e5c", 1: "925405772966a6c3bbcedec92c2cb29a", 3: "41783146a36b0df9c0e450715439fa55", 6: "925405772966a6c3bbcedec92c2cb29a", 5: "6bbeb0387e4f44aac21d582a1f2a467d", 7: "ca70cbc23a7e39fbeba90f027fef6e5c", 12: "ca70cbc23a7e39fbeba90f027fef6e5c", 10: "6bbeb0387e4f44aac21d582a1f2a467d", 9: "8524c25aab60e2a76ecb3fd1215c52fa", 11: "925405772966a6c3bbcedec92c2cb29a", 14: "8524c25aab60e2a76ecb3fd1215c52fa", 13: "41783146a36b0df9c0e450715439fa55", 15: "6bbeb0387e4f44aac21d582a1f2a467d" } ae(tdb.catalog, catalog) ae(tdb.thumbnails.keys(), md5_hashes.keys()) for (key, hash) in md5_hashes.items(): ae(md5(tdb.thumbnails[key].data).hexdigest(), hash) # end for ar(KeyError, ThumbsDb, self.cfb, "thisisnotthecatalogyouarelookingfor")
def test_from_properties(self): ae = self.assertEqual blair_si_stream = self.blair_si_stream sample_si_stream = self.sample_si_stream blair_props = list() sample_props = list() control_metadata = SummaryInfo(( 0x4E4, None, None, None, set([ "code_page", "title", "subject", "author", "keywords", "comments", "template", "last_author", "rev", "edit_time_tot", "print_time", "btime", "mtime", "page_count", "word_count", "char_count", "app_name", "security" ]), "Iraq- ITS INFRASTRUCTURE OF CONCEALMENT, DECEPTION AND " "INTIMIDATION", "", "default", "", "", "Normal.dot", "MKhan", "4", FILETIMETodatetime.from_int(0x6B49D200), FILETIMETodatetime.from_int(0x01C2C8A7296E8E00), FILETIMETodatetime.from_int(0x01C2CB66F65A2200), FILETIMETodatetime.from_int(0x01C2CB75E8F86400), 1, 0xF23, 0x564A, None, "Microsoft Word 8.0", 0, )) property_set_stream = Builder.build(blair_si_stream) blair_properties = property_set_stream.property_set_0.properties metadata = SummaryInfo.from_properties(blair_properties) ae(metadata, control_metadata) sample_si_stream.seek(0x1F8, SEEK_SET) cf_data = sample_si_stream.read(0x254A6) control_metadata = SummaryInfo(( 0x4E4, None, None, None, set([ "code_page", "title", "subject", "author", "keywords", "comments", "template", "last_author", "rev", "edit_time_tot", "btime", "mtime", "page_count", "word_count", "char_count", "thumbnail", "app_name", "security" ]), "title_value", "subject_value", "author_value", "keyword0 keyword1", "Comments in the comments box", "Normal", "lftest2", "24", FILETIMETodatetime.from_int(0x1176592E00), None, FILETIMETodatetime.from_int(0x01CAA3C0F0A6EC00), FILETIMETodatetime.from_int(0x01CAA3D361570400), 7, 0xAA, 0x0550, VtThumbnailValue(( 0x0254B4, cf_data, 0xFFFFFFFF, 3 )), "Microsoft Office Word", 8, )) property_set_stream = Builder.build(sample_si_stream, 0) sample_properties = property_set_stream.property_set_0.properties metadata = SummaryInfo.from_properties(sample_properties) ae(metadata, control_metadata)