From 68229a5fd32470f26557ddfd635eb9f3c9d46ff0 Mon Sep 17 00:00:00 2001 From: j <@> Date: Fri, 11 Jan 2019 16:29:08 -0600 Subject: [PATCH 1/2] Switch from getopt to argparse to get more reasonable error messages for arguments. --- Eudora2Unix.py | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/Eudora2Unix.py b/Eudora2Unix.py index 922f3e5..0771961 100755 --- a/Eudora2Unix.py +++ b/Eudora2Unix.py @@ -15,7 +15,7 @@ from os.path import * import re import string -import getopt +import argparse if sys.hexversion < 33686000: sys.stderr.write( "Aborted: Python version must be at least 2.2.1" \ @@ -42,12 +42,6 @@ embedded_dir = None # --------------------- Comments & complaints ---------------------- -def usage_complaint( arg ): - return [ - 'Usage error; specify Eudora directory to be converted:', - ' ' + arg + ' [-a attachments directory] [-f mbox|maildir|mmdf|mh|babyl] [-d target directory] eudora_directory [kmail|pine]' - ] - def target_directory_already_exists_complaint( maildir ): return [ 'Directory ' + maildir + ' already exits. Rename it, e.g. to ', @@ -707,18 +701,15 @@ def fix_file_permissions( arg, dir, names ): elif isdir( f ): os.chmod( fpath, 0700 ) -# --------------------- START HERE -------------------------------- -# Note: in this rather stupid implementation of getopts, has to go -# program flags args, or else -try: - opts, args = getopt.getopt( sys.argv[1:], 'a:d:t:' ) -except getopt.GetoptError: - complain( usage_complaint( sys.argv[0] ) ) - sys.exit( 1 ) - -if len( args ) < 1 or len( args[0].strip() ) == 0: - complain( usage_complaint( sys.argv[0] ) ) - sys.exit( 1 ) -else: - eudoradir = args[0].strip() - convert_directory( eudoradir, opts ) +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('source_directory', help='Eudora directory to be converted') + parser.add_argument('-a', metavar='attach_dir', help='attachments directory') + parser.add_argument('-f', help='mailbox format', type=str, choices=('mbox','maildir','mmdf','mh','babyl')) + parser.add_argument('-d', metavar='target_dir', help='target directory') + parser.add_argument('-t', help='target client', type=str, choices=('kmail', 'pine')) + command_line_args = parser.parse_args() + eudoradir = command_line_args.source_directory + del command_line_args.source_directory + opts = [ ('-'+k, v) for k,v in vars(command_line_args).items() if v != None] # hack to convert to a getopts-style list + convert_directory( eudoradir, opts ) From 4c62b94cfed819d2592da5c8531aa912facfba4a Mon Sep 17 00:00:00 2001 From: j <@> Date: Mon, 9 Oct 2023 14:08:33 +0000 Subject: [PATCH 2/2] Fixes for Eudora 6.1.0.6. Enhance logging. --- Eudora2Unix.py | 4 +-- EudoraTOC.py | 84 +++++++++++++++++++------------------------------- 2 files changed, 34 insertions(+), 54 deletions(-) diff --git a/Eudora2Unix.py b/Eudora2Unix.py index 0771961..2f72c22 100755 --- a/Eudora2Unix.py +++ b/Eudora2Unix.py @@ -589,7 +589,7 @@ def convert_files( avoid_dirlist, dir, names ): # os.spawnlpe( os.P_WAIT, 'etoc', 'etoc', # f_toc, f_toc + '.txt', # os.environ ) - EudoraTOC.parse( f_toc, f_toc + '.txt' ) + EudoraTOC.parse( f_toc, isMac, f_toc + '.txt' ) except OSError, ( errno, str ): complain( toc_complaint( f_toc, str ) ) moveFile( fpath, f_nombx ) @@ -704,7 +704,7 @@ def fix_file_permissions( arg, dir, names ): if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('source_directory', help='Eudora directory to be converted') - parser.add_argument('-a', metavar='attach_dir', help='attachments directory') + parser.add_argument('-a', required=True, metavar='attach_dir', help='attachments directory') parser.add_argument('-f', help='mailbox format', type=str, choices=('mbox','maildir','mmdf','mh','babyl')) parser.add_argument('-d', metavar='target_dir', help='target directory') parser.add_argument('-t', help='target client', type=str, choices=('kmail', 'pine')) diff --git a/EudoraTOC.py b/EudoraTOC.py index 5ac0c6f..497f876 100755 --- a/EudoraTOC.py +++ b/EudoraTOC.py @@ -130,21 +130,6 @@ '26x', # (all 0) ), '' ) -# Eudora toc file versions I've seen: -# MAC_EUDORA_LITE_3 = 0x0001 -# MAC_EUDORA_LITE_131 = 0x0000 # (a Poor choice!) -# WIN_EUDORA_LITE_1 = 0x2a00 -# WIN_EUDORA_5 = 0x0300 - -# Just a guess: maybe Mac and Windows are distinguished thus (with 0 being Mac) -def isMac( version ): - MAC = 0x00FF - return version & MAC or version == 0 - -def isWin( version ): - WIN = 0xFF00 - return version & WIN - # Big-Endian integer conversions def toIntBig( c ): @@ -220,8 +205,7 @@ def printMacEntry( out, entry ): print >> out def printWinEntry( out, entry ): - ( offset, length, status, priority, date, to, subject ) \ - = unpack( win_entry, entry ) + ( offset, length, status, priority, date, to, subject ) = unpack( win_entry, entry ) print >> out, "offset: %d" % ( toIntLittle( offset ), ) print >> out, "length: %d" % ( toIntLittle( length ), ) @@ -258,17 +242,6 @@ def printWinEntry( out, entry ): print >> out, "priority: %d" % ( priority, ) print >> out -def readVersionAndRewind( file ): - verbuf = file.read( 2 ) - v = unpack( 'BB', verbuf ) - - file.seek( 0 ) - - if len( verbuf ) > 0: - return ( v[0] << 8 ) | v[1] - - return 0 - class TOCError(Exception): """ Problem occurred concerning a Eudora TOC file. """ def __init__(self, value): @@ -278,7 +251,7 @@ def __str__(self): def args(self): return self.args -def parse( infile, outfile = None ): +def parse( infile, isMac, outfile ): """ Parse a Eudora '.toc' file, and pull out important info into a text file '.toc.txt' @@ -291,10 +264,22 @@ def parse( infile, outfile = None ): Mac Eudora Lite 3.x has version 0001, Windows Eudora Pro 5.o has 0030 As a guess, if the upper byte is nonzero, it's Windows, otherwise, it's Mac. + + From prior list: + Eudora toc file versions I've seen: + MAC_EUDORA_LITE_3 = 0x0001 + MAC_EUDORA_LITE_131 = 0x0000 # (a Poor choice!) + WIN_EUDORA_LITE_1 = 0x2a00 + WIN_EUDORA_5 = 0x0300 + Windows 6.1.0.6 used 0x0000 also. It's possible that no file format identifier shows Mac vs Windows? + + Note that Windows Eudora 6.1.0.6 invalidates all this theory, so we rely on the passed-in isMac variable instead. + """ file = None returnVal = 0 out = sys.stdout + print >> out, ('Parsing %s ...' % infile) try: file = open( infile, "rb" ) @@ -308,54 +293,49 @@ def parse( infile, outfile = None ): except IOError, ( errno, strerror ): raise TOCError( "EudoraTOC: couldn't open file " + outfile ) - version = readVersionAndRewind( file ) - if isMac( version ): + if isMac: foldersize = calcsize( mac_folder ) entrysize = calcsize( mac_entry ) - elif isWin( version ): + else: foldersize = calcsize( win_folder ); entrysize = calcsize( win_entry ); - else: - raise TOCError( "EudoraTOC: unknown toc version: 0x%x" \ - % version ) - print >> out, "Expect folder and entry sizes %d %d" \ - % ( foldersize, entrysize ) + print >> out, "Expect sizes: folder %d %x, entry %d %x" % ( foldersize, foldersize, entrysize, entrysize ) + file.read(18) + ''' folder = file.read( foldersize ) if len( folder ) == 0: raise TOCError( "EudoraTOC: couldn't read header" ) - if isMac( version ): + if isMac: printMacFolder( out, folder ) - elif isWin( version ): + else: printWinFolder( out, folder ) - +''' while True: entry = file.read( entrysize ) if len( entry ) <= 0: break - if isMac( version ): - printMacEntry( out, entry ) - elif isWin( version ): - printWinEntry( out, entry ) + try: + if isMac: + printMacEntry( out, entry ) + else: + printWinEntry( out, entry ) + except: + sys.stderr.write('Error parsing %s - corrupt?\n' % infile) + if file: file.close() return returnVal -if sys.argv[0].find( 'EudoraTOC.py' ) > -1: # i.e. if script called directly - if len( sys.argv ) < 2: - raise TOCError( "EudoraTOC: insufficient arguments" ) - if len( sys.argv ) >= 3: - outfile = sys.argv[2] - else: - outfile = None +if __name__ == '__main__': # i.e. if script called directly try: - sys.exit( parse( sys.argv[1], outfile ) ) + sys.exit( parse( sys.argv[1], int(sys.argv[2]), sys.argv[3] ) ) except TOCError, errstr: print errstr sys.exit( 1 )