mirror of
https://github.com/scito/extract_otp_secret_keys.git
synced 2025-12-09 08:15:05 +01:00
fix linting
This commit is contained in:
parent
b89a338246
commit
f4389ca8a3
9 changed files with 53 additions and 39 deletions
8
.vscode/settings.json
vendored
8
.vscode/settings.json
vendored
|
|
@ -2,7 +2,7 @@
|
||||||
"python.testing.pytestArgs": [
|
"python.testing.pytestArgs": [
|
||||||
"."
|
"."
|
||||||
],
|
],
|
||||||
"python.testing.unittestEnabled": false,
|
"python.testing.unittestEnabled": true,
|
||||||
"python.testing.pytestEnabled": true,
|
"python.testing.pytestEnabled": true,
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"devbox",
|
"devbox",
|
||||||
|
|
@ -16,5 +16,9 @@
|
||||||
"qrcode",
|
"qrcode",
|
||||||
"TOTP",
|
"TOTP",
|
||||||
"venv"
|
"venv"
|
||||||
]
|
],
|
||||||
|
"search.exclude": {
|
||||||
|
"**/build": true,
|
||||||
|
"**/dist": true
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import pytest
|
||||||
|
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
parser.addoption( "--relaxed", action='store_true', help="run tests in relaxed mode")
|
parser.addoption("--relaxed", action='store_true', help="run tests in relaxed mode")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
||||||
|
|
@ -53,18 +53,18 @@ import urllib.parse as urlparse
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from operator import add
|
from operator import add
|
||||||
|
|
||||||
from qrcode import QRCode # type: ignore
|
from qrcode import QRCode # type: ignore
|
||||||
|
|
||||||
import protobuf_generated_python.google_auth_pb2 # type: ignore
|
import protobuf_generated_python.google_auth_pb2 # type: ignore
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import cv2 # type: ignore
|
import cv2 # type: ignore
|
||||||
import numpy
|
import numpy # type: ignore
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pyzbar.pyzbar as zbar # type: ignore
|
import pyzbar.pyzbar as zbar # type: ignore
|
||||||
from qreader import QReader # type: ignore
|
from qreader import QReader # type: ignore
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise SystemExit(f"""
|
raise SystemExit(f"""
|
||||||
ERROR: Cannot import QReader module. This problem is probably due to the missing zbar shared library.
|
ERROR: Cannot import QReader module. This problem is probably due to the missing zbar shared library.
|
||||||
|
|
@ -72,7 +72,7 @@ On Linux and macOS libzbar0 must be installed.
|
||||||
See in README.md for the installation of the libzbar0.
|
See in README.md for the installation of the libzbar0.
|
||||||
Exception: {e}""")
|
Exception: {e}""")
|
||||||
qreader_available = True
|
qreader_available = True
|
||||||
except ImportError as e:
|
except ImportError:
|
||||||
qreader_available = False
|
qreader_available = False
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -95,7 +95,6 @@ def main(sys_args):
|
||||||
|
|
||||||
def parse_args(sys_args):
|
def parse_args(sys_args):
|
||||||
global verbose, quiet
|
global verbose, quiet
|
||||||
formatter = lambda prog: argparse.RawTextHelpFormatter(prog, max_help_position=52)
|
|
||||||
description_text = "Extracts one time password (OTP) secret keys from QR codes, e.g. from Google Authenticator app."
|
description_text = "Extracts one time password (OTP) secret keys from QR codes, e.g. from Google Authenticator app."
|
||||||
if qreader_available:
|
if qreader_available:
|
||||||
description_text += "\nIf no infiles are provided, the QR codes are interactively captured from the camera."
|
description_text += "\nIf no infiles are provided, the QR codes are interactively captured from the camera."
|
||||||
|
|
@ -106,7 +105,7 @@ python extract_otp_secret_keys.py - < example_export.txt
|
||||||
python extract_otp_secret_keys.py --csv - example_*.png | tail -n+2
|
python extract_otp_secret_keys.py --csv - example_*.png | tail -n+2
|
||||||
python extract_otp_secret_keys.py = < example_export.png"""
|
python extract_otp_secret_keys.py = < example_export.png"""
|
||||||
|
|
||||||
arg_parser = argparse.ArgumentParser(formatter_class=formatter,
|
arg_parser = argparse.ArgumentParser(formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, max_help_position=52),
|
||||||
description=description_text,
|
description=description_text,
|
||||||
epilog=example_text)
|
epilog=example_text)
|
||||||
arg_parser.add_argument('infile', help="""a) file or - for stdin with 'otpauth-migration://...' URLs separated by newlines, lines starting with # are ignored;
|
arg_parser.add_argument('infile', help="""a) file or - for stdin with 'otpauth-migration://...' URLs separated by newlines, lines starting with # are ignored;
|
||||||
|
|
@ -143,7 +142,7 @@ def extract_otps_from_camera(args):
|
||||||
otp_urls = []
|
otp_urls = []
|
||||||
otps = []
|
otps = []
|
||||||
|
|
||||||
QRMode = Enum('QRMode', ['QREADER', 'DEEP_QREADER', 'CV2'], start = 0)
|
QRMode = Enum('QRMode', ['QREADER', 'DEEP_QREADER', 'CV2'], start=0)
|
||||||
qr_mode = QRMode.QREADER
|
qr_mode = QRMode.QREADER
|
||||||
if verbose: print(f"QR reading mode: {qr_mode}")
|
if verbose: print(f"QR reading mode: {qr_mode}")
|
||||||
|
|
||||||
|
|
@ -270,8 +269,8 @@ def read_lines_from_text_file(filename):
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
if filename == '-':
|
if filename == '-':
|
||||||
abort("\nERROR: Unable to open text file form stdin. "
|
abort("\nERROR: Unable to open text file form stdin. "
|
||||||
"In case you want read an image file from stdin, you must use '=' instead of '-'.")
|
"In case you want read an image file from stdin, you must use '=' instead of '-'.")
|
||||||
else: # The file is probably an image, process below
|
else: # The file is probably an image, process below
|
||||||
return None
|
return None
|
||||||
finally:
|
finally:
|
||||||
finput.close()
|
finput.close()
|
||||||
|
|
@ -285,7 +284,7 @@ def extract_otp_from_otp_url(otpauth_migration_url, otps, i, j, infile, args):
|
||||||
j += 1
|
j += 1
|
||||||
if verbose: print(f"\n{j}. Secret Key")
|
if verbose: print(f"\n{j}. Secret Key")
|
||||||
secret = convert_secret_from_bytes_to_base32_str(raw_otp.secret)
|
secret = convert_secret_from_bytes_to_base32_str(raw_otp.secret)
|
||||||
otp_type_enum = get_enum_name_by_number(raw_otp, 'type')
|
if verbose: print('OTP enum type:', get_enum_name_by_number(raw_otp, 'type'))
|
||||||
otp_type = get_otp_type_str_from_code(raw_otp.type)
|
otp_type = get_otp_type_str_from_code(raw_otp.type)
|
||||||
otp_url = build_otp_url(secret, raw_otp)
|
otp_url = build_otp_url(secret, raw_otp)
|
||||||
otp = {
|
otp = {
|
||||||
|
|
@ -349,7 +348,7 @@ def get_payload_from_otp_url(otpauth_migration_url, i, input_source):
|
||||||
if verbose > 2: print(f"\nDEBUG: parsed_url={parsed_url}")
|
if verbose > 2: print(f"\nDEBUG: parsed_url={parsed_url}")
|
||||||
try:
|
try:
|
||||||
params = urlparse.parse_qs(parsed_url.query, strict_parsing=True)
|
params = urlparse.parse_qs(parsed_url.query, strict_parsing=True)
|
||||||
except: # Not necessary for Python >= 3.11
|
except Exception: # Not necessary for Python >= 3.11
|
||||||
params = []
|
params = []
|
||||||
if verbose > 2: print(f"\nDEBUG: querystring params={params}")
|
if verbose > 2: print(f"\nDEBUG: querystring params={params}")
|
||||||
if 'data' not in params:
|
if 'data' not in params:
|
||||||
|
|
@ -362,9 +361,9 @@ def get_payload_from_otp_url(otpauth_migration_url, i, input_source):
|
||||||
payload = protobuf_generated_python.google_auth_pb2.MigrationPayload()
|
payload = protobuf_generated_python.google_auth_pb2.MigrationPayload()
|
||||||
try:
|
try:
|
||||||
payload.ParseFromString(data)
|
payload.ParseFromString(data)
|
||||||
except:
|
except Exception:
|
||||||
abort(f"\nERROR: Cannot decode otpauth-migration migration payload.\n"
|
abort(f"\nERROR: Cannot decode otpauth-migration migration payload.\n"
|
||||||
f"data={data_base64}")
|
f"data={data_base64}")
|
||||||
if verbose:
|
if verbose:
|
||||||
print(f"\n{i}. Payload Line", payload, sep='\n')
|
print(f"\n{i}. Payload Line", payload, sep='\n')
|
||||||
|
|
||||||
|
|
@ -515,7 +514,7 @@ def open_file_or_stdout_for_csv(filename):
|
||||||
def check_file_exists(filename):
|
def check_file_exists(filename):
|
||||||
if filename != '-' and not os.path.isfile(filename):
|
if filename != '-' and not os.path.isfile(filename):
|
||||||
abort(f"\nERROR: Input file provided is non-existent or not a file."
|
abort(f"\nERROR: Input file provided is non-existent or not a file."
|
||||||
f"\ninput file: {filename}")
|
f"\ninput file: {filename}")
|
||||||
|
|
||||||
|
|
||||||
def is_binary(line):
|
def is_binary(line):
|
||||||
|
|
|
||||||
2
setup.py
2
setup.py
|
|
@ -1,5 +1,5 @@
|
||||||
import pathlib
|
import pathlib
|
||||||
from setuptools import setup # type: ignore
|
from setuptools import setup # type: ignore
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='extract_otp_secret_keys',
|
name='extract_otp_secret_keys',
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ batch_id: -1320898453
|
||||||
|
|
||||||
|
|
||||||
1. Secret Key
|
1. Secret Key
|
||||||
|
OTP enum type: OTP_TOTP
|
||||||
Name: pi@raspberrypi
|
Name: pi@raspberrypi
|
||||||
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
Issuer: raspberrypi
|
Issuer: raspberrypi
|
||||||
|
|
@ -66,6 +67,7 @@ batch_id: -2094403140
|
||||||
|
|
||||||
|
|
||||||
2. Secret Key
|
2. Secret Key
|
||||||
|
OTP enum type: OTP_TOTP
|
||||||
Name: pi@raspberrypi
|
Name: pi@raspberrypi
|
||||||
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
Type: totp
|
Type: totp
|
||||||
|
|
@ -98,6 +100,7 @@ batch_id: -1822886384
|
||||||
|
|
||||||
|
|
||||||
3. Secret Key
|
3. Secret Key
|
||||||
|
OTP enum type: OTP_TOTP
|
||||||
Name: pi@raspberrypi
|
Name: pi@raspberrypi
|
||||||
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
Type: totp
|
Type: totp
|
||||||
|
|
@ -105,6 +108,7 @@ otpauth://totp/pi%40raspberrypi?secret=7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
|
|
||||||
|
|
||||||
4. Secret Key
|
4. Secret Key
|
||||||
|
OTP enum type: OTP_TOTP
|
||||||
Name: pi@raspberrypi
|
Name: pi@raspberrypi
|
||||||
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
Issuer: raspberrypi
|
Issuer: raspberrypi
|
||||||
|
|
@ -130,6 +134,7 @@ batch_id: -1558849573
|
||||||
|
|
||||||
|
|
||||||
5. Secret Key
|
5. Secret Key
|
||||||
|
OTP enum type: OTP_HOTP
|
||||||
Name: hotp demo
|
Name: hotp demo
|
||||||
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
Type: hotp
|
Type: hotp
|
||||||
|
|
@ -155,6 +160,7 @@ batch_id: -171198419
|
||||||
|
|
||||||
|
|
||||||
6. Secret Key
|
6. Secret Key
|
||||||
|
OTP enum type: OTP_TOTP
|
||||||
Name: encoding: ¿äÄéÉ? (demo)
|
Name: encoding: ¿äÄéÉ? (demo)
|
||||||
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
Type: totp
|
Type: totp
|
||||||
|
|
|
||||||
|
|
@ -20,13 +20,15 @@
|
||||||
|
|
||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import extract_otp_secret_keys
|
import extract_otp_secret_keys
|
||||||
from utils import *
|
from utils import (file_exits, quick_and_dirty_workaround_encoding_problem,
|
||||||
|
read_binary_file_as_stream, read_csv, read_csv_str,
|
||||||
|
read_file_to_str, read_json, read_json_str,
|
||||||
|
replace_escaped_octal_utf8_bytes_with_str)
|
||||||
|
|
||||||
qreader_available = extract_otp_secret_keys.qreader_available
|
qreader_available = extract_otp_secret_keys.qreader_available
|
||||||
|
|
||||||
|
|
@ -213,7 +215,6 @@ def test_keepass_csv_stdout(capsys):
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
expected_totp_csv = read_csv('example_keepass_output.totp.csv')
|
expected_totp_csv = read_csv('example_keepass_output.totp.csv')
|
||||||
expected_hotp_csv = read_csv('example_keepass_output.hotp.csv')
|
|
||||||
assert not file_exits('test_example_keepass_output.totp.csv')
|
assert not file_exits('test_example_keepass_output.totp.csv')
|
||||||
assert not file_exits('test_example_keepass_output.hotp.csv')
|
assert not file_exits('test_example_keepass_output.hotp.csv')
|
||||||
assert not file_exits('test_example_keepass_output.csv')
|
assert not file_exits('test_example_keepass_output.csv')
|
||||||
|
|
@ -340,7 +341,8 @@ def test_extract_saveqr(capsys, tmp_path):
|
||||||
|
|
||||||
|
|
||||||
def test_normalize_bytes():
|
def test_normalize_bytes():
|
||||||
assert replace_escaped_octal_utf8_bytes_with_str('Before\\\\302\\\\277\\\\303\nname: enc: \\302\\277\\303\\244\\303\\204\\303\\251\\303\\211?\nAfter') == 'Before\\\\302\\\\277\\\\303\nname: enc: ¿äÄéÉ?\nAfter'
|
assert replace_escaped_octal_utf8_bytes_with_str(
|
||||||
|
'Before\\\\302\\\\277\\\\303\nname: enc: \\302\\277\\303\\244\\303\\204\\303\\251\\303\\211?\nAfter') == 'Before\\\\302\\\\277\\\\303\nname: enc: ¿äÄéÉ?\nAfter'
|
||||||
|
|
||||||
|
|
||||||
def test_extract_verbose(capsys, relaxed):
|
def test_extract_verbose(capsys, relaxed):
|
||||||
|
|
@ -352,6 +354,9 @@ def test_extract_verbose(capsys, relaxed):
|
||||||
|
|
||||||
expected_stdout = read_file_to_str('test/print_verbose_output.txt')
|
expected_stdout = read_file_to_str('test/print_verbose_output.txt')
|
||||||
|
|
||||||
|
if not qreader_available:
|
||||||
|
expected_stdout = expected_stdout.replace('QReader installed: True', 'QReader installed: False')
|
||||||
|
|
||||||
if relaxed or sys.implementation.name == 'pypy':
|
if relaxed or sys.implementation.name == 'pypy':
|
||||||
print('\nRelaxed mode\n')
|
print('\nRelaxed mode\n')
|
||||||
|
|
||||||
|
|
@ -390,6 +395,7 @@ def test_extract_help(capsys):
|
||||||
assert e.type == SystemExit
|
assert e.type == SystemExit
|
||||||
assert e.value.code == 0
|
assert e.value.code == 0
|
||||||
|
|
||||||
|
|
||||||
def test_extract_no_arguments(capsys, mocker):
|
def test_extract_no_arguments(capsys, mocker):
|
||||||
if qreader_available:
|
if qreader_available:
|
||||||
# Arrange
|
# Arrange
|
||||||
|
|
@ -554,8 +560,7 @@ def test_img_qr_reader_from_stdin(capsys, monkeypatch):
|
||||||
# Assert
|
# Assert
|
||||||
captured = capsys.readouterr()
|
captured = capsys.readouterr()
|
||||||
|
|
||||||
expected_stdout =\
|
expected_stdout = '''Name: Test1:test1@example1.com
|
||||||
'''Name: Test1:test1@example1.com
|
|
||||||
Secret: JBSWY3DPEHPK3PXP
|
Secret: JBSWY3DPEHPK3PXP
|
||||||
Issuer: Test1
|
Issuer: Test1
|
||||||
Type: totp
|
Type: totp
|
||||||
|
|
@ -705,8 +710,7 @@ Type: totp
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
EXPECTED_STDOUT_FROM_EXAMPLE_EXPORT_PNG =\
|
EXPECTED_STDOUT_FROM_EXAMPLE_EXPORT_PNG = '''Name: Test1:test1@example1.com
|
||||||
'''Name: Test1:test1@example1.com
|
|
||||||
Secret: JBSWY3DPEHPK3PXP
|
Secret: JBSWY3DPEHPK3PXP
|
||||||
Issuer: Test1
|
Issuer: Test1
|
||||||
Type: totp
|
Type: totp
|
||||||
|
|
|
||||||
|
|
@ -23,15 +23,16 @@ from utils import Capturing
|
||||||
|
|
||||||
import extract_otp_secret_keys
|
import extract_otp_secret_keys
|
||||||
|
|
||||||
|
|
||||||
class TestQRImageExtract(unittest.TestCase):
|
class TestQRImageExtract(unittest.TestCase):
|
||||||
def test_img_qr_reader_happy_path(self):
|
def test_img_qr_reader_happy_path(self):
|
||||||
with Capturing() as actual_output:
|
with Capturing() as actual_output:
|
||||||
extract_otp_secret_keys.main(['test/test_googleauth_export.png'])
|
extract_otp_secret_keys.main(['test/test_googleauth_export.png'])
|
||||||
|
|
||||||
expected_output =\
|
expected_output =\
|
||||||
['Name: Test1:test1@example1.com', 'Secret: JBSWY3DPEHPK3PXP', 'Issuer: Test1', 'Type: totp', '',
|
['Name: Test1:test1@example1.com', 'Secret: JBSWY3DPEHPK3PXP', 'Issuer: Test1', 'Type: totp', '',
|
||||||
'Name: Test2:test2@example2.com', 'Secret: JBSWY3DPEHPK3PXQ', 'Issuer: Test2', 'Type: totp', '',
|
'Name: Test2:test2@example2.com', 'Secret: JBSWY3DPEHPK3PXQ', 'Issuer: Test2', 'Type: totp', '',
|
||||||
'Name: Test3:test3@example3.com', 'Secret: JBSWY3DPEHPK3PXR', 'Issuer: Test3', 'Type: totp', '']
|
'Name: Test3:test3@example3.com', 'Secret: JBSWY3DPEHPK3PXR', 'Issuer: Test3', 'Type: totp', '']
|
||||||
|
|
||||||
self.assertEqual(actual_output, expected_output)
|
self.assertEqual(actual_output, expected_output)
|
||||||
|
|
||||||
|
|
@ -40,8 +41,7 @@ class TestQRImageExtract(unittest.TestCase):
|
||||||
with self.assertRaises(SystemExit) as context:
|
with self.assertRaises(SystemExit) as context:
|
||||||
extract_otp_secret_keys.main(['test/lena_std.tif'])
|
extract_otp_secret_keys.main(['test/lena_std.tif'])
|
||||||
|
|
||||||
expected_output =\
|
expected_output = ['', 'ERROR: Unable to read QR Code from file.', 'input file: test/lena_std.tif']
|
||||||
['', 'ERROR: Unable to read QR Code from file.', 'input file: test/lena_std.tif']
|
|
||||||
|
|
||||||
self.assertEqual(actual_output, expected_output)
|
self.assertEqual(actual_output, expected_output)
|
||||||
self.assertEqual(context.exception.code, 1)
|
self.assertEqual(context.exception.code, 1)
|
||||||
|
|
@ -51,8 +51,7 @@ class TestQRImageExtract(unittest.TestCase):
|
||||||
with self.assertRaises(SystemExit) as context:
|
with self.assertRaises(SystemExit) as context:
|
||||||
extract_otp_secret_keys.main(['test/nonexistent.bmp'])
|
extract_otp_secret_keys.main(['test/nonexistent.bmp'])
|
||||||
|
|
||||||
expected_output =\
|
expected_output = ['', 'ERROR: Input file provided is non-existent or not a file.', 'input file: test/nonexistent.bmp']
|
||||||
['', 'ERROR: Input file provided is non-existent or not a file.', 'input file: test/nonexistent.bmp']
|
|
||||||
|
|
||||||
self.assertEqual(actual_output, expected_output)
|
self.assertEqual(actual_output, expected_output)
|
||||||
self.assertEqual(context.exception.code, 1)
|
self.assertEqual(context.exception.code, 1)
|
||||||
|
|
|
||||||
|
|
@ -209,7 +209,7 @@ cmd="$FLAKE8 . --count --select=E9,F63,F7,F82 --show-source --statistics"
|
||||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||||
eval "$cmd"
|
eval "$cmd"
|
||||||
|
|
||||||
cmd="$FLAKE8 . --count --exit-zero --max-complexity=10 --max-line-length=200 --statistics"
|
cmd="$FLAKE8 . --count --exit-zero --max-complexity=10 --max-line-length=200 --statistics --exclude=.git,__pycache__,docs/source/conf.py,old,build,dist,protobuf_generated_python"
|
||||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||||
eval "$cmd"
|
eval "$cmd"
|
||||||
|
|
||||||
|
|
@ -239,7 +239,7 @@ cmd="docker build . -t extract_otp_secret_keys_no_qr_reader -f Dockerfile_no_qr_
|
||||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||||
eval "$cmd"
|
eval "$cmd"
|
||||||
|
|
||||||
cmd="docker run --entrypoint /extract/run_pytest.sh --rm -v "$(pwd)":/files:ro extract_otp_secret_keys_no_qr_reader test_extract_otp_secret_keys_pytest.py -k 'not qreader' -vvv --relaxed"
|
cmd="docker run --entrypoint /extract/run_pytest.sh --rm -v \"$(pwd)\":/files:ro extract_otp_secret_keys_no_qr_reader test_extract_otp_secret_keys_pytest.py -k 'not qreader' -vvv --relaxed"
|
||||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||||
eval "$cmd"
|
eval "$cmd"
|
||||||
|
|
||||||
|
|
@ -247,7 +247,7 @@ cmd="docker build . -t extract_otp_secret_keys --pull"
|
||||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||||
eval "$cmd"
|
eval "$cmd"
|
||||||
|
|
||||||
cmd="docker run --entrypoint /extract/run_pytest.sh --rm -v "$(pwd)":/files:ro extract_otp_secret_keys"
|
cmd="docker run --entrypoint /extract/run_pytest.sh --rm -v \"$(pwd)\":/files:ro extract_otp_secret_keys"
|
||||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||||
eval "$cmd"
|
eval "$cmd"
|
||||||
|
|
||||||
|
|
|
||||||
2
utils.py
2
utils.py
|
|
@ -104,11 +104,13 @@ def read_file_to_str(filename):
|
||||||
"""Returns a str."""
|
"""Returns a str."""
|
||||||
return "".join(read_file_to_list(filename))
|
return "".join(read_file_to_list(filename))
|
||||||
|
|
||||||
|
|
||||||
def read_binary_file_as_stream(filename):
|
def read_binary_file_as_stream(filename):
|
||||||
"""Returns binary file content."""
|
"""Returns binary file content."""
|
||||||
with open(filename, "rb",) as infile:
|
with open(filename, "rb",) as infile:
|
||||||
return io.BytesIO(infile.read())
|
return io.BytesIO(infile.read())
|
||||||
|
|
||||||
|
|
||||||
def replace_escaped_octal_utf8_bytes_with_str(str):
|
def replace_escaped_octal_utf8_bytes_with_str(str):
|
||||||
encoded_name_strings = re.findall(r'name: .*$', str, flags=re.MULTILINE)
|
encoded_name_strings = re.findall(r'name: .*$', str, flags=re.MULTILINE)
|
||||||
for encoded_name_string in encoded_name_strings:
|
for encoded_name_string in encoded_name_strings:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue