From 62997cf0ecd4ea940a5393ed6c9a4f4d20c5d7a4 Mon Sep 17 00:00:00 2001 From: Christopher Dawes Date: Mon, 1 Feb 2021 11:15:30 +0000 Subject: [PATCH] python2 -> python3 --- filehunt.py | 48 +++++++++++++++++++++++++++-------------------- msmsg.py | 45 ++++++++++++++++++++++---------------------- panhunt.py | 50 ++++++++++++++++++++++++------------------------- pst.py | 54 ++++++++++++++++++++++++++--------------------------- 4 files changed, 102 insertions(+), 95 deletions(-) diff --git a/filehunt.py b/filehunt.py index 529525a..56a568a 100644 --- a/filehunt.py +++ b/filehunt.py @@ -6,7 +6,7 @@ # filehunt: general file searching library for use by PANhunt and PassHunt # By BB -import os, sys, zipfile, re, datetime, cStringIO, argparse, time, hashlib, unicodedata, codecs +import os, sys, zipfile, re, datetime, io, argparse, time, hashlib, unicodedata, codecs import colorama import progressbar import pst # MS-PST files @@ -37,10 +37,8 @@ def __init__(self, filename, file_dir): self.type = None self.matches = [] - def __cmp__(self, other): - - return cmp(self.path.lower(), other.path.lower()) - + def __lt__(self, other): + return self.path.lower() < other.path.lower() def set_file_stats(self): @@ -74,7 +72,7 @@ def size_friendly(self): def set_error(self, error_msg): self.errors.append(error_msg) - print colorama.Fore.RED + unicode2ascii(u'ERROR %s on %s' % (error_msg, self.path)) + colorama.Fore.WHITE + sys.stdout.buffer.write(colorama.Fore.RED.encode('ascii','ignore') + unicode2ascii('ERROR %s on %s\n' % (error_msg, self.path)) + colorama.Fore.WHITE.encode('ascii','ignore')) def check_regexs(self, regexs, search_extensions): @@ -94,7 +92,7 @@ def check_regexs(self, regexs, search_extensions): elif self.type == 'TEXT': try: - file_text = read_file(self.path, 'rb') + file_text = read_file(self.path, 'r') self.check_text_regexs(file_text, regexs, '') #except WindowsError: # self.set_error(sys.exc_info()[1]) @@ -145,7 +143,7 @@ def check_pst_regexs(self, regexs, search_extensions, hunt_type, gauge_update_fu if message.Subject: message_path = os.path.join(folder.path, message.Subject) else: - message_path = os.path.join(folder.path, u'[NoSubject]') + message_path = os.path.join(folder.path, '[NoSubject]') if message.Body: self.check_text_regexs(message.Body, regexs, message_path) if message.HasAttachments: @@ -185,7 +183,7 @@ def check_attachment_regexs(self, attachment, regexs, search_extensions, sub_pat if attachment_ext in search_extensions['ZIP']: if attachment.data: try: - memory_zip = cStringIO.StringIO() + memory_zip = io.StringIO() memory_zip.write(attachment.data) zf = zipfile.ZipFile(memory_zip) self.check_zip_regexs(zf, regexs, search_extensions, os.path.join(sub_path, attachment.Filename)) @@ -212,7 +210,7 @@ def check_zip_regexs(self, zf, regexs, search_extensions, sub_path): for file_in_zip in files_in_zip: if get_ext(file_in_zip) in search_extensions['ZIP']: # nested zip file try: - memory_zip = cStringIO.StringIO() + memory_zip = io.StringIO() memory_zip.write(zf.open(file_in_zip).read()) nested_zf = zipfile.ZipFile(memory_zip) self.check_zip_regexs(nested_zf, regexs, search_extensions, os.path.join(sub_path, decode_zip_filename(file_in_zip))) @@ -222,13 +220,13 @@ def check_zip_regexs(self, zf, regexs, search_extensions, sub_path): elif get_ext(file_in_zip) in search_extensions['TEXT']: #normal doc try: file_text = zf.open(file_in_zip).read() - self.check_text_regexs(file_text, regexs, os.path.join(sub_path, decode_zip_filename(file_in_zip))) + self.check_text_regexs(decode_zip_text(file_text), regexs, os.path.join(sub_path, decode_zip_filename(file_in_zip))) except: # RuntimeError: # e.g. zip needs password self.set_error(sys.exc_info()[1]) else: # SPECIAL try: if get_ext(file_in_zip) == '.msg': - memory_msg = cStringIO.StringIO() + memory_msg = io.StringIO() memory_msg.write(zf.open(file_in_zip).read()) msg = msmsg.MSMSG(memory_msg) if msg.validMSG: @@ -253,10 +251,10 @@ def find_all_files_in_directory(AFileClass, root_dir, excluded_directories, sear global TEXT_FILE_SIZE_LIMIT - all_extensions = [ext for ext_list in search_extensions.values() for ext in ext_list] + all_extensions = [ext for ext_list in list(search_extensions.values()) for ext in ext_list] extension_types = {} - for ext_type, ext_list in search_extensions.iteritems(): + for ext_type, ext_list in search_extensions.items(): for ext in ext_list: extension_types[ext] = ext_type @@ -379,9 +377,13 @@ def load_object(fn): def read_file(fn, open_mode="r"): - f = open(fn, open_mode) + try: + with open(fn, open_mode) as f: s = f.read() - f.close() + except: + with open(fn, "rb") as f: + b = f.read() + s = b.decode("utf-8", "ignore") return s @@ -421,13 +423,19 @@ def unicode2ascii(unicode_str): return unicodedata.normalize('NFKD', unicode_str).encode('ascii','ignore') -def decode_zip_filename(str): +def decode_zip_filename(instr): - if type(str) is unicode: - return str + if type(instr) is str: + return instr else: - return str.decode('cp437') + return instr.decode('cp437') +def decode_zip_text(instr): + + if type(instr) is str: + return instr + else: + return instr.decode('utf-8') def get_ext(file_name): diff --git a/msmsg.py b/msmsg.py index 07e5ecb..2c364f3 100644 --- a/msmsg.py +++ b/msmsg.py @@ -61,7 +61,7 @@ def get_stream(self, sector, size): def __repr__(self): - return ', '.join(['%s:%s' % (hex(sector), hex(entry)) for sector, entry in zip(range(len(self.entries)), self.entries)]) + return ', '.join(['%s:%s' % (hex(sector), hex(entry)) for sector, entry in zip(list(range(len(self.entries))), self.entries)]) @@ -102,7 +102,7 @@ def get_stream(self, sector, size): def __repr__(self): - return ', '.join(['%s:%s' % (hex(sector), hex(entry)) for sector, entry in zip(range(len(self.entries)), self.entries)]) + return ', '.join(['%s:%s' % (hex(sector), hex(entry)) for sector, entry in zip(list(range(len(self.entries))), self.entries)]) @@ -133,7 +133,7 @@ def set_entry_children(self, dir_entry): child_ids_queue.append(dir_entry.ChildID) while child_ids_queue: child_entry = self.entries[child_ids_queue.pop()] - if child_entry.Name in dir_entry.childs.keys(): + if child_entry.Name in list(dir_entry.childs.keys()): raise MSGException('Directory Entry Name already in children dictionary') dir_entry.childs[child_entry.Name] = child_entry if child_entry.SiblingID != DirectoryEntry.NOSTREAM: @@ -156,7 +156,7 @@ def get_directory_sector(self, sector): def __repr__(self): - return u', '.join([entry.__repr__() for entry in self.entries]) + return ', '.join([entry.__repr__() for entry in self.entries]) @@ -199,9 +199,8 @@ def __init__(self, mscfb, bytes): self.childs = {} - def __cmp__(self, other): - - return cmp(self.Name, other.Name) + def __lt__(self, other): + return self.Name < other.Name def get_data(self): @@ -222,7 +221,7 @@ def list_children(self, level=0, expand=False): for child_entry in sorted(self.childs.values()): line_sfx = '' if child_entry.ObjectType == DirectoryEntry.OBJECT_STORAGE: - line_sfx = '(%s)' % len(child_entry.childs.keys()) + line_sfx = '(%s)' % len(list(child_entry.childs.keys())) s += '%s %s %s\n' % (line_pfx, child_entry.Name, line_sfx) if expand: s += child_entry.list_children(level+1, expand) @@ -231,7 +230,7 @@ def list_children(self, level=0, expand=False): def __repr__(self): - return u'%s (%s, %s, %s, %s, %s, %s)' % (self.Name, self.ObjectType, hex(self.SiblingID), hex(self.RightSiblingID), hex(self.ChildID), hex(self.StartingSectorLocation), hex(self.StreamSize)) + return '%s (%s, %s, %s, %s, %s, %s)' % (self.Name, self.ObjectType, hex(self.SiblingID), hex(self.RightSiblingID), hex(self.ChildID), hex(self.StartingSectorLocation), hex(self.StreamSize)) @@ -240,7 +239,7 @@ class MSCFB: def __init__(self, cfb_file): """cfb_file is unicode or string filename or a file object""" - if isinstance(cfb_file, str) or isinstance(cfb_file, unicode): + if isinstance(cfb_file, str) or isinstance(cfb_file, str): self.fd = open(cfb_file,'rb') else: self.fd = cfb_file @@ -330,14 +329,14 @@ def __init__(self, msmsg, parent_dir_entry, header_size): property_entries_count = (len(bytes) - header_size) / 16 for i in range(property_entries_count): prop_entry = PropertyEntry(self.msmsg, parent_dir_entry, bytes[header_size + i*16: header_size + i*16 + 16]) - if prop_entry in self.properties.keys(): + if prop_entry in list(self.properties.keys()): raise MSGException('PropertyID already in properties dictionary') self.properties[prop_entry.PropertyID] = prop_entry def getval(self, prop_id): - if prop_id in self.properties.keys(): + if prop_id in list(self.properties.keys()): return self.properties[prop_id].value else: return None @@ -345,7 +344,7 @@ def getval(self, prop_id): def __repr__(self): - return u'\n'.join([prop.__repr__() for prop in self.properties.values()]) + return '\n'.join([prop.__repr__() for prop in list(self.properties.values())]) @@ -389,7 +388,7 @@ def __init__(self, msmsg, parent_dir_entry, bytes): def __repr__(self): - return u'%s=%s' % (hex(self.PropertyTag), self.value.__repr__()) + return '%s=%s' % (hex(self.PropertyTag), self.value.__repr__()) @@ -723,7 +722,7 @@ def set_recipients(self): recipient_dir_index = 0 while True: recipient_dir_name = '__recip_version1.0_#%s' % zeropadhex(recipient_dir_index, 8) - if recipient_dir_name in self.root_dir_entry.childs.keys(): + if recipient_dir_name in list(self.root_dir_entry.childs.keys()): recipient_dir_entry = self.root_dir_entry.childs[recipient_dir_name] rps = PropertyStream(self, recipient_dir_entry, PropertyStream.RECIP_OR_ATTACH_HEADER_SIZE) recipient = Recipient(rps) @@ -739,7 +738,7 @@ def set_attachments(self): attachment_dir_index = 0 while True: attachment_dir_name = '__attach_version1.0_#%s' % zeropadhex(attachment_dir_index, 8) - if attachment_dir_name in self.root_dir_entry.childs.keys(): + if attachment_dir_name in list(self.root_dir_entry.childs.keys()): attachment_dir_entry = self.root_dir_entry.childs[attachment_dir_name] aps = PropertyStream(self, attachment_dir_entry, PropertyStream.RECIP_OR_ATTACH_HEADER_SIZE) attachment = Attachment(aps) @@ -870,7 +869,7 @@ def size_friendly(size): def test_status_msg(msg_file): msg = MSMSG(msg_file) - print msg.cfb.directory + print(msg.cfb.directory) msg.close() @@ -878,19 +877,19 @@ def test_folder_msgs(test_folder): global error_log_list - s = u'' + s = '' for msg_filepath in [os.path.join(test_folder, filename) for filename in os.listdir(test_folder) if os.path.isfile(os.path.join(test_folder, filename)) and os.path.splitext(filename.lower())[1] == '.msg']: #try: - s += u'Opening %s\n' % msg_filepath + s += 'Opening %s\n' % msg_filepath error_log_list = [] msg = MSMSG(msg_filepath) #s += u'MajorVersion: %s, FATSectors: %s, MiniFATSectors: %s, DIFATSectors %s\n' % (msg.cfb.MajorVersion, msg.cfb.FATSectors, msg.cfb.MiniFATSectors, msg.cfb.DIFATSectors) #s += u'MiniStreamSectorLocation: %s, MiniStreamSize: %s\n' % (hex(msg.cfb.MiniStreamSectorLocation), msg.cfb.MiniStreamSize) #s += u'\n' + msg.cfb.directory.entries[0].list_children(level=0, expand=True) #s += u'\n' + msg.prop_stream.__repr__() - s += u'Recipients: %s\n' % u', '.join([recip.__repr__() for recip in msg.recipients]) - s += u'Attachments: %s\n' % u', '.join([attach.__repr__() for attach in msg.attachments]) - s += u'Subject: %s\nBody: %s\n' % (msg.Subject.__repr__(), msg.Body.__repr__()) + s += 'Recipients: %s\n' % ', '.join([recip.__repr__() for recip in msg.recipients]) + s += 'Attachments: %s\n' % ', '.join([attach.__repr__() for attach in msg.attachments]) + s += 'Subject: %s\nBody: %s\n' % (msg.Subject.__repr__(), msg.Body.__repr__()) s += '\n\n\n' # dump attachments: if False: @@ -917,6 +916,6 @@ def test_folder_msgs(test_folder): if __name__=="__main__": - test_folder = u'D:\\' + test_folder = 'D:\\' #test_status_msg(test_folder+'test.msg') #test_folder_msgs(test_folder) \ No newline at end of file diff --git a/panhunt.py b/panhunt.py index 251d5bd..31746a8 100644 --- a/panhunt.py +++ b/panhunt.py @@ -6,9 +6,9 @@ # PANhunt: search directories and sub directories for documents with PANs # By BB -import os, sys, zipfile, re, datetime, cStringIO, argparse, time, hashlib, unicodedata, platform +import os, sys, zipfile, re, datetime, io, argparse, time, hashlib, unicodedata, platform import colorama -import ConfigParser +import configparser import progressbar import filehunt @@ -16,16 +16,16 @@ # defaults defaults = { - 'search_dir': u'C:\\', - 'output_file': u'panhunt_%s.txt' % time.strftime("%Y-%m-%d-%H%M%S"), - 'excluded_directories_string': u'C:\\Windows,C:\\Program Files,C:\\Program Files (x86)', - 'text_extensions_string': u'.doc,.xls,.xml,.txt,.csv,.log', - 'zip_extensions_string': u'.docx,.xlsx,.zip', - 'special_extensions_string': u'.msg', - 'mail_extensions_string': u'.pst', - 'other_extensions_string': u'.ost,.accdb,.mdb', # checks for existence of files that can't be checked automatically + 'search_dir': 'C:\\', + 'output_file': 'panhunt_%s.txt' % time.strftime("%Y-%m-%d-%H%M%S"), + 'excluded_directories_string': 'C:\\Windows,C:\\Program Files,C:\\Program Files (x86)', + 'text_extensions_string': '.doc,.xls,.xml,.txt,.csv,.log', + 'zip_extensions_string': '.docx,.xlsx,.zip', + 'special_extensions_string': '.msg', + 'mail_extensions_string': '.pst', + 'other_extensions_string': '.ost,.accdb,.mdb', # checks for existence of files that can't be checked automatically 'excluded_pans_string': '', - 'config_file': u'panhunt.ini' + 'config_file': 'panhunt.ini' } search_dir = defaults['search_dir'] output_file = defaults['output_file'] @@ -69,7 +69,7 @@ def __init__(self, filename, file_dir): def check_text_regexs(self, text, regexs, sub_path): """Uses regular expressions to check for PANs in text""" - for brand, regex in regexs.items(): + for brand, regex in list(regexs.items()): pans = regex.findall(text) if pans: for pan in pans: @@ -140,11 +140,11 @@ def digits_of(n): def get_text_hash(text): - if type(text) is unicode: + if type(text) is str: encoded_text = text.encode('utf-8') else: encoded_text = text - return hashlib.sha512(encoded_text+'PAN').hexdigest() + return hashlib.sha512(encoded_text+'PAN'.encode('utf-8')).hexdigest() def add_hash_to_file(text_file): @@ -163,10 +163,10 @@ def check_file_hash(text_file): hash_in_file = text_output[hash_pos+len(os.linesep):] hash_check = get_text_hash(text_output[:hash_pos]) if hash_in_file == hash_check: - print colorama.Fore.GREEN + 'Hashes OK' + sys.stdout.buffer.write(colorama.Fore.GREEN.encode('ascii','ignore') + 'Hashes OK\n'.encode('ascii','ignore')) else: - print colorama.Fore.RED + 'Hashes Not OK' - print colorama.Fore.WHITE + hash_in_file +'\n' + hash_check + sys.stdout.buffer.write(colorama.Fore.RED.encode('ascii','ignore') + 'Hashes Not OK\n'.encode('ascii','ignore')) + sys.stdout.buffer.write(colorama.Fore.WHITE.encode('ascii','ignore') + hash_in_file +'\n' + hash_check) def output_report(search_dir, excluded_directories_string, all_files, total_files_searched, pans_found, output_file, mask_pans): @@ -179,21 +179,21 @@ def output_report(search_dir, excluded_directories_string, all_files, total_file pan_report += u'Searched %s files. Found %s possible PANs.\n%s\n\n' % (total_files_searched, pans_found, '='*100) for afile in sorted([afile for afile in all_files if afile.matches]): - pan_header = u'FOUND PANs: %s (%s %s)' % (afile.path, afile.size_friendly(), afile.modified.strftime('%d/%m/%Y')) - print colorama.Fore.RED + filehunt.unicode2ascii(pan_header) + pan_header = 'FOUND PANs: %s (%s %s)' % (afile.path, afile.size_friendly(), afile.modified.strftime('%d/%m/%Y')) + sys.stdout.buffer.write(colorama.Fore.RED.encode('ascii','ignore') + filehunt.unicode2ascii(pan_header) + '\n'.encode('ascii','ignore')) pan_report += pan_header + '\n' - pan_list = u'\t' + pan_sep.join([pan.__repr__(mask_pans) for pan in afile.matches]) - print colorama.Fore.YELLOW + filehunt.unicode2ascii(pan_list) + pan_list = '\t' + pan_sep.join([pan.__repr__(mask_pans) for pan in afile.matches]) + sys.stdout.buffer.write(colorama.Fore.YELLOW.encode('ascii','ignore') + filehunt.unicode2ascii(pan_list) + '\n'.encode('ascii','ignore')) pan_report += pan_list + '\n\n' if len([afile for afile in all_files if afile.type == 'OTHER']) <> 0: pan_report += u'Interesting Files to check separately:\n' for afile in sorted([afile for afile in all_files if afile.type == 'OTHER']): - pan_report += u'%s (%s %s)\n' % (afile.path, afile.size_friendly(), afile.modified.strftime('%d/%m/%Y')) + pan_report += '%s (%s %s)\n' % (afile.path, afile.size_friendly(), afile.modified.strftime('%d/%m/%Y')) pan_report = pan_report.replace('\n', os.linesep) - print colorama.Fore.WHITE + 'Report written to %s' % filehunt.unicode2ascii(output_file) + sys.stdout.buffer.write(colorama.Fore.WHITE.encode('ascii','ignore') + 'Report written to '.encode('ascii','ignore') + filehunt.unicode2ascii(output_file) + '\n'.encode('ascii','ignore')) filehunt.write_unicode_file(output_file, pan_report) add_hash_to_file(output_file) @@ -306,8 +306,8 @@ def hunt_pans(gauge_update_function=None): mail_extensions_string = unicode(args.mailfiles) other_extensions_string = unicode(args.otherfiles) mask_pans = not args.unmask - excluded_pans_string = unicode(args.excludepan) - config_file = unicode(args.config) + excluded_pans_string = str(args.excludepan) + config_file = str(args.config) load_config_file() set_global_parameters() diff --git a/pst.py b/pst.py index bad778b..b3be85a 100644 --- a/pst.py +++ b/pst.py @@ -26,7 +26,7 @@ def is_int(x): to_byte = ord def is_int(x): - return isinstance(x, (int, long)) + return isinstance(x, int) ############################################################################################################################## # _ _ _ ____ _ _ ___ _ ____ ______ _ @@ -284,9 +284,9 @@ class Block: 200, 161, 128, 166, 153, 152, 168, 47, 14, 129, 101, 115, 228, 194, 162, 138, 212, 225, 17, 208, 8, 139, 42, 242, 237, 154, 100, 63, 193, 108, 249, 236) if sys.hexversion >= 0x03000000: - decrypt_table = bytes.maketrans(bytearray(range(256)), bytearray(mpbbCryptFrom512)) + decrypt_table = bytes.maketrans(bytearray(list(range(256))), bytearray(mpbbCryptFrom512)) else: - decrypt_table = string.maketrans(b''.join(map(chr, range(256))), b''.join(map(chr, mpbbCryptFrom512))) + decrypt_table = string.maketrans(b''.join(map(chr, list(range(256)))), b''.join(map(chr, mpbbCryptFrom512))) btypeData = 0 btypeXBLOCK = 1 @@ -439,7 +439,7 @@ def fetch_subnodes(self, bid): block = self.fetch_block(bid) if block.block_type == Block.btypeSLBLOCK: for slentry in block.rgentries: - if slentry.nid in subnodes.keys(): + if slentry.nid in list(subnodes.keys()): raise PSTException('Duplicate subnode %s' % slentry.nid) subnodes[slentry.nid.nid] = slentry elif block.block_type == Block.btypeSIBLOCK: @@ -457,7 +457,7 @@ def get_page_leaf_entries(self, entry_type, page_offset): page = self.fetch_page(page_offset) for entry in page.rgEntries: if isinstance(entry, entry_type): - if entry.key in leaf_entries.keys(): + if entry.key in list(leaf_entries.keys()): raise PSTException('Invalid Leaf Key %s' % entry) leaf_entries[entry.key] = entry elif isinstance(entry, BTENTRY): @@ -633,7 +633,7 @@ def __init__(self, bth_data, hn): self.value = ptype.value(hn.get_hid_data(self.hid)) else: self.subnode_nid = NID(self.dwValueHnid) - if self.subnode_nid.nid in hn.subnodes.keys(): + if self.subnode_nid.nid in list(hn.subnodes.keys()): subnode_nid_bid = hn.subnodes[self.subnode_nid.nid].bidData else: raise PSTException('Invalid NID subnode reference %s' % self.subnode_nid) @@ -920,7 +920,7 @@ def __init__(self, hn): def getval(self, propid): - if propid in self.props.keys(): + if propid in list(self.props.keys()): return self.props[propid].value else: return None @@ -1016,7 +1016,7 @@ def setup_row_matrix(self): if self.hnidRows.is_hid: row_matrix_datas = [self.hn.get_hid_data(self.hnidRows)] # block data list else: - if self.hnidRows.nid in self.hn.subnodes.keys(): + if self.hnidRows.nid in list(self.hn.subnodes.keys()): subnode_nid_bid = self.hn.subnodes[self.hnidRows.nid].bidData else: raise PSTException('Row Matrix HNID not in Subnodes: %s' % self.hnidRows.nid) @@ -1037,7 +1037,7 @@ def setup_row_matrix(self): else: data_bytes = None #row_datas.append(self.get_row_cell_value(data_bytes, tcoldesc)) - if tcoldesc.wPropId in rowvals.keys(): + if tcoldesc.wPropId in list(rowvals.keys()): raise PSTException('Property ID %s already in row data' % hex(tcoldesc.wPropId)) rowvals[tcoldesc.wPropId] = self.get_row_cell_value(data_bytes, tcoldesc) self.RowMatrix[dwRowID] = rowvals #row_datas @@ -1062,7 +1062,7 @@ def get_row_cell_value(self, data_bytes, tcoldesc): return ptype.value(self.hn.get_hid_data(hid)) else: subnode_nid = NID(data_bytes) - if subnode_nid.nid in self.hn.subnodes.keys(): + if subnode_nid.nid in list(self.hn.subnodes.keys()): subnode_nid_bid = self.hn.subnodes[subnode_nid.nid].bidData else: raise PSTException('Row Matrix Value HNID Subnode invalid: %s' % subnode_nid) @@ -1079,7 +1079,7 @@ def getval(self, RowIndex, wPropId): dwRowID = self.get_row_ID(RowIndex) rowvals = self.RowMatrix[dwRowID] - if wPropId in rowvals.keys(): + if wPropId in list(rowvals.keys()): return rowvals[wPropId] else: return None @@ -1089,7 +1089,7 @@ def __repr__(self): s = 'TC Rows: %s, %s\n' % (len(self.RowIndex), self.hn) s += 'Columns: ' + ''.join([' %s' % tcoldesc for tcoldesc in self.rgTCOLDESC]) - s += '\nData:\n' + '\n'.join(['%s: %s' % (hex(dwRowID), rowvals) for dwRowID,rowvals in self.RowMatrix.items()]) + s += '\nData:\n' + '\n'.join(['%s: %s' % (hex(dwRowID), rowvals) for dwRowID,rowvals in list(self.RowMatrix.items())]) return s @@ -1269,7 +1269,7 @@ def __init__(self, nid, ltp, parent_path='', messaging=None): self.submessages = [SubMessage(self.tc_contents.RowIndex[RowIndex].nid, \ self.tc_contents.getval(RowIndex,PropIdEnum.PidTagSentRepresentingNameW), ltp.strip_SubjectPrefix(self.tc_contents.getval(RowIndex,PropIdEnum.PidTagSubjectW)), \ self.tc_contents.getval(RowIndex,PropIdEnum.PidTagClientSubmitTime)) \ - for RowIndex in range(len(self.tc_contents.RowIndex)) if RowIndex in self.tc_contents.RowIndex.keys()] + for RowIndex in range(len(self.tc_contents.RowIndex)) if RowIndex in list(self.tc_contents.RowIndex.keys())] except PSTException as e: log_error(e) @@ -1373,7 +1373,7 @@ def __init__(self, nid, ltp, nbd=None, parent_message=None, messaging=None): self.tc_attachments = None self.tc_recipients = None if self.pc.hn.subnodes: - for subnode in self.pc.hn.subnodes.values(): #SLENTRYs + for subnode in list(self.pc.hn.subnodes.values()): #SLENTRYs if subnode.nid.nidType == NID.NID_TYPE_ATTACHMENT_TABLE: self.tc_attachments = self.ltp.get_tc_by_slentry(subnode) elif subnode.nid.nidType == NID.NID_TYPE_RECIPIENT_TABLE: @@ -1476,7 +1476,7 @@ def set_message_store(self): self.message_store = self.ltp.get_pc_by_nid(NID(NID.NID_MESSAGE_STORE)) self.store_record_key = self.message_store.getval(PropIdEnum.PidTagRecordKey) - if PropIdEnum.PidTagPstPassword in self.message_store.props.keys(): + if PropIdEnum.PidTagPstPassword in list(self.message_store.props.keys()): self.PasswordCRC32Hash = struct.unpack('I', struct.pack('i', self.message_store.getval(PropIdEnum.PidTagPstPassword)))[0] else: self.PasswordCRC32Hash = None @@ -1994,15 +1994,15 @@ def export_all_messages(self, path='', progressbar = None, total_messages = 0): messages_completed = 0 for folder in self.folder_generator(): filepath = get_unused_filename(os.path.join(path, get_safe_filename(folder.path.replace('\\','_'))+'.txt')) - msg_txt = u'' + msg_txt = '' for message in self.message_generator(folder): - msg_txt += u'Subject: %s\nFrom: %s (%s)\n' % (message.Subject, message.SenderName, message.SenderSmtpAddress) - msg_txt += u'To: %s\n' % ('; '.join([u'%s (%s)' % (subrecipient.DisplayName, subrecipient.EmailAddress) for subrecipient in message.subrecipients])) - msg_txt += u'Sent: %s\nDelivered: %s\n' % (message.ClientSubmitTime, message.MessageDeliveryTime) - msg_txt += u'MessageClass: %s\n' % (message.MessageClass) + msg_txt += 'Subject: %s\nFrom: %s (%s)\n' % (message.Subject, message.SenderName, message.SenderSmtpAddress) + msg_txt += 'To: %s\n' % ('; '.join(['%s (%s)' % (subrecipient.DisplayName, subrecipient.EmailAddress) for subrecipient in message.subrecipients])) + msg_txt += 'Sent: %s\nDelivered: %s\n' % (message.ClientSubmitTime, message.MessageDeliveryTime) + msg_txt += 'MessageClass: %s\n' % (message.MessageClass) if message.HasAttachments: - msg_txt += u'Attachments: %s\n' % (u', '.join([subattachment.__repr__() for subattachment in message.subattachments])) - msg_txt += u'\n%s\n\n\n' % message.Body + msg_txt += 'Attachments: %s\n' % (', '.join([subattachment.__repr__() for subattachment in message.subattachments])) + msg_txt += '\n%s\n\n\n' % message.Body if msg_txt: write_file(filepath, unicode2ascii(msg_txt), 'w') messages_completed += 1 @@ -2030,7 +2030,7 @@ def get_total_attachment_count(self): def get_pst_status(self): - status = u'Valid PST: %s, Unicode: %s, CryptMethod: %s, Name: %s, Password: %s' % (self.header.validPST, self.header.is_unicode, self.header.bCryptMethod, self.messaging.message_store.getval(PropIdEnum.PidTagDisplayName), self.messaging.PasswordCRC32Hash) + status = 'Valid PST: %s, Unicode: %s, CryptMethod: %s, Name: %s, Password: %s' % (self.header.validPST, self.header.is_unicode, self.header.bCryptMethod, self.messaging.message_store.getval(PropIdEnum.PidTagDisplayName), self.messaging.PasswordCRC32Hash) return status @@ -2146,9 +2146,9 @@ def log_error(e): def test_status_pst(pst_filepath): pst = PST(pst_filepath) - print(unicode2ascii(pst.get_pst_status())) - print('Total Messages: %s' % pst.get_total_message_count()) - print('Total Attachments: %s' % pst.get_total_attachment_count()) + sys.stdout.buffer.write((unicode2ascii(pst.get_pst_status())) + '\n'.encode('ascii','ignore')) + print(('Total Messages: %s' % pst.get_total_message_count())) + print(('Total Attachments: %s' % pst.get_total_attachment_count())) pst.close() @@ -2163,7 +2163,7 @@ def test_dump_pst(pst_filepath, output_path): """ dump out all PST email attachments and emails (into text files) to output_path folder""" pst = PST(pst_filepath) - print(pst.get_pst_status()) + print((pst.get_pst_status())) pbar = get_simple_progressbar('Messages: ') total_messages = pst.get_total_message_count()