parser.add_argument('-n', '--name', default='', help='Name of card holder')
parser.add_argument('-e', '--expires', default='9912', help='Date of expiration on card (Format: YYMM)')
parser.add_argument('-s', '--service', default='121', help='Service code of card (TODO: help for service code)')
- parser.add_argument('-p', '--pan', default='', help='Primary account number of card (CAUTION: COMMAND LINE SAVED IN SHELL HISTORIES)')
+ parser.add_argument('-p', '--pan', help='Primary account number of card (CAUTION: COMMAND LINE SAVED IN SHELL HISTORIES)')
parser.add_argument('-f', '--force', action=argparse.BooleanOptionalAction, default=False, help='Force file write even if exists')
parser.add_argument('-a', '--append', action=argparse.BooleanOptionalAction, default=False, help='Append to the file instead of overwriting it')
parser.add_argument('FILE')
args = parser.parse_args(args=argv[1:])
+ EXIT_FLAG_FILE = 2
+ EXIT_FLAG_NAME = 4
+ EXIT_FLAG_SVC = 8
+ EXIT_FLAG_EXP = 16
+ EXIT_FLAG_PAN = 32
exitcode = 0
- NAME = args.name
- if len(NAME) != 0 and not NAME.isalnum():
- print(f'Name ({NAME}) is not alphanumeric!')
- exitcode |= 2
+
+ FILE = args.FILE
+ if not args.force and not args.append and os.path.exists(args.FILE):
+ print(f'File ({FILE}) exists (use -a to append or -f to overwrite)')
+ exitcode |= EXIT_FLAG_FILE
+
+ NAME = args.name.upper()
+ if len(NAME) != 0 and not NAME.translate(str.maketrans(dict.fromkeys(" .'-,/\\", 'A'))).isalnum():
+ print(f'Name ({NAME}) is not a valid track 1 name!')
+ exitcode |= EXIT_FLAG_NAME
if len(NAME) > 26:
print(f'Name ({NAME}) is longer than 26 characters!')
- exitcode |= 2
+ exitcode |= EXIT_FLAG_NAME
+ NAME += (' ' * (26 - len(NAME)))
SVC = args.service
if len(SVC) != 0 and not SVC.isdigit():
- print(f'Service code ({SVC}) is not numeric, not 3 characters, or is not a known service code!')
- exitcode |= 4
+ print(f'Service code ({SVC}) is not numeric!')
+ exitcode |= EXIT_FLAG_SVC
if len(SVC) != 3:
- print(f'Service code ({SVC}) is not 3 characters, or is not a known service code!')
- exitcode |= 4
+ print(f'Service code ({SVC}) is not 3 characters!')
+ exitcode |= EXIT_FLAG_SVC
if SVC[0] not in '125679' or SVC[1] not in '024' or SVC[2] not in '01234567':
print(f'Service code ({SVC}) is not a known service code!')
- exitcode |= 4
+ exitcode |= EXIT_FLAG_SVC
EXP = args.expires
if len(EXP) != 0 and not EXP.isdigit():
- print(f'Expiration date ({EXP}) is not numeric, not 4 characters, not a valid date, or is already expired!')
- exitcode |= 8
+ print(f'Expiration date ({EXP}) is not numeric!')
+ exitcode |= EXIT_FLAG_EXP
if len(EXP) != 4:
print(f'Expiration date ({EXP}) is not 4 characters')
- exitcode |= 8
+ exitcode |= EXIT_FLAG_EXP
if not (1 <= int(EXP[2:4]) <= 12):
- print(f'Expiration date ({EXP}) is not a valid date, or is already expired!')
- exitcode |= 8
-
- TODAY = datetime.datetime.now()
- if datetime.datetime(2000 + int(EXP[0:2]), int(EXP[2:4]), 1) <= TODAY:
- print(f'Expiration date ({EXP}) is not a valid date, or is already expired!')
- exitcode |= 8
+ print(f'Expiration date ({EXP}) is not a valid date')
+ exitcode |= EXIT_FLAG_EXP
+ else:
+ TODAY = datetime.datetime.now()
+ if datetime.datetime(2000 + int(EXP[0:2]), int(EXP[2:4]), 1) <= TODAY:
+ print(f'Expiration date ({EXP}) is already expired!')
+ exitcode |= EXIT_FLAG_EXP
PAN = args.pan
- if not PAN and exitcode == 0:
- PAN = getpass.getpass("Enter PAN here: ")
- if not PAN.isdigit() or len(PAN) >= 20:
- print(f'Primary account number is not numeric or is longer than 19 characters!')
- exitcode |= 16
-
- FILE = args.FILE
- if not args.force and not args.append and os.path.exists(args.FILE):
- print(f'File ({FILE}) exists (use -a to append or -f to overwrite)')
- exitcode |= 32
+ if PAN is None:
+ PAN = ''
+ if exitcode == 0:
+ PAN = getpass.getpass("Enter PAN: ")
+ if len(PAN) == 0:
+ print('WARNING: Entered empty primary account number!')
+ if len(PAN) != 0 and not PAN.isdigit():
+ print(f'Primary account number is not numeric!')
+ exitcode |= EXIT_FLAG_PAN
+ if len(PAN) >= 20:
+ print(f'Primary account number is longer than 19 characters!')
+ exitcode |= EXIT_FLAG_PAN
if exitcode != 0:
return exitcode
# Write file and add a couple of newlines normally emitted by the
# MSR605X reader/writer program when reading magstripe cards
- T1 = f'%B{PAN}^{NAME}^{EXP}{SVC}^^^?'
- T2 = f';{PAN}={EXP}{SVC}===?'
+ T1 = f'%B{PAN}^{NAME}^{EXP}{SVC}?'
+ T2 = f';{PAN}={EXP}{SVC}?'
T3 = '+?'
with open(FILE, 'a' if args.append else 'w') as fp:
datestr = TODAY.strftime('%Y.%m.%d %H:%M:%S')