mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-10 00:09:04 +00:00
@@ -18,9 +18,9 @@ import hashlib
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
import shutil
|
import shutil
|
||||||
import time
|
import time
|
||||||
import select
|
|
||||||
import builtins
|
import builtins
|
||||||
from termcolor import colored
|
from termcolor import colored
|
||||||
|
from utils.input_utils import timed_input
|
||||||
|
|
||||||
from password_manager.encryption import EncryptionManager
|
from password_manager.encryption import EncryptionManager
|
||||||
from password_manager.entry_management import EntryManager
|
from password_manager.entry_management import EntryManager
|
||||||
@@ -1285,14 +1285,12 @@ class PasswordManager:
|
|||||||
sys.stdout.write(f"\r{bar} {remaining:2d}s")
|
sys.stdout.write(f"\r{bar} {remaining:2d}s")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
try:
|
try:
|
||||||
if (
|
user_input = timed_input("", 1)
|
||||||
sys.stdin
|
if user_input.strip().lower() == "b":
|
||||||
in select.select([sys.stdin], [], [], 1)[0]
|
exit_loop = True
|
||||||
):
|
break
|
||||||
user_input = sys.stdin.readline().strip().lower()
|
except TimeoutError:
|
||||||
if user_input == "b":
|
pass
|
||||||
exit_loop = True
|
|
||||||
break
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
exit_loop = True
|
exit_loop = True
|
||||||
print()
|
print()
|
||||||
@@ -2009,10 +2007,11 @@ class PasswordManager:
|
|||||||
print(f"[{idx}] {label}: {code} {bar} {remaining:2d}s")
|
print(f"[{idx}] {label}: {code} {bar} {remaining:2d}s")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
try:
|
try:
|
||||||
if sys.stdin in select.select([sys.stdin], [], [], 1)[0]:
|
user_input = timed_input("", 1)
|
||||||
user_input = sys.stdin.readline().strip().lower()
|
if user_input.strip().lower() == "b":
|
||||||
if user_input == "b":
|
break
|
||||||
break
|
except TimeoutError:
|
||||||
|
pass
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print()
|
print()
|
||||||
break
|
break
|
||||||
|
@@ -30,6 +30,15 @@ from cryptography.hazmat.primitives.asymmetric import ed25519
|
|||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
from bip_utils import Bip39SeedGenerator
|
from bip_utils import Bip39SeedGenerator
|
||||||
|
|
||||||
|
# Ensure the ``imghdr`` module is available for ``pgpy`` on Python 3.13+
|
||||||
|
try: # pragma: no cover - only executed on Python >= 3.13
|
||||||
|
import imghdr # type: ignore
|
||||||
|
except ModuleNotFoundError: # pragma: no cover - fallback for removed module
|
||||||
|
from utils import imghdr_stub as imghdr # type: ignore
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.modules.setdefault("imghdr", imghdr)
|
||||||
|
|
||||||
from local_bip85.bip85 import BIP85
|
from local_bip85.bip85 import BIP85
|
||||||
|
|
||||||
from constants import DEFAULT_PASSWORD_LENGTH, MIN_PASSWORD_LENGTH, MAX_PASSWORD_LENGTH
|
from constants import DEFAULT_PASSWORD_LENGTH, MIN_PASSWORD_LENGTH, MAX_PASSWORD_LENGTH
|
||||||
|
@@ -50,7 +50,7 @@ def test_handle_display_totp_codes(monkeypatch, capsys):
|
|||||||
|
|
||||||
# interrupt the loop after first iteration
|
# interrupt the loop after first iteration
|
||||||
monkeypatch.setattr(
|
monkeypatch.setattr(
|
||||||
"password_manager.manager.select.select",
|
"password_manager.manager.timed_input",
|
||||||
lambda *a, **k: (_ for _ in ()).throw(KeyboardInterrupt()),
|
lambda *a, **k: (_ for _ in ()).throw(KeyboardInterrupt()),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ def test_display_totp_codes_excludes_blacklisted(monkeypatch, capsys):
|
|||||||
)
|
)
|
||||||
|
|
||||||
monkeypatch.setattr(
|
monkeypatch.setattr(
|
||||||
"password_manager.manager.select.select",
|
"password_manager.manager.timed_input",
|
||||||
lambda *a, **k: (_ for _ in ()).throw(KeyboardInterrupt()),
|
lambda *a, **k: (_ for _ in ()).throw(KeyboardInterrupt()),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -69,10 +69,9 @@ def test_list_entries_show_details(monkeypatch, capsys):
|
|||||||
pm.entry_manager, "get_totp_time_remaining", lambda *a, **k: 1
|
pm.entry_manager, "get_totp_time_remaining", lambda *a, **k: 1
|
||||||
)
|
)
|
||||||
monkeypatch.setattr("password_manager.manager.time.sleep", lambda *a, **k: None)
|
monkeypatch.setattr("password_manager.manager.time.sleep", lambda *a, **k: None)
|
||||||
monkeypatch.setattr(sys.stdin, "readline", lambda *a, **k: "b\n")
|
|
||||||
monkeypatch.setattr(
|
monkeypatch.setattr(
|
||||||
"password_manager.manager.select.select",
|
"password_manager.manager.timed_input",
|
||||||
lambda *a, **k: ([sys.stdin], [], []),
|
lambda *a, **k: "b",
|
||||||
)
|
)
|
||||||
|
|
||||||
inputs = iter(["1", "0"])
|
inputs = iter(["1", "0"])
|
||||||
|
@@ -49,10 +49,9 @@ def test_handle_retrieve_totp_entry(monkeypatch, capsys):
|
|||||||
pm.entry_manager, "get_totp_time_remaining", lambda *a, **k: 1
|
pm.entry_manager, "get_totp_time_remaining", lambda *a, **k: 1
|
||||||
)
|
)
|
||||||
monkeypatch.setattr("password_manager.manager.time.sleep", lambda *a, **k: None)
|
monkeypatch.setattr("password_manager.manager.time.sleep", lambda *a, **k: None)
|
||||||
monkeypatch.setattr(sys.stdin, "readline", lambda *a, **k: "b\n")
|
|
||||||
monkeypatch.setattr(
|
monkeypatch.setattr(
|
||||||
"password_manager.manager.select.select",
|
"password_manager.manager.timed_input",
|
||||||
lambda *a, **k: ([sys.stdin], [], []),
|
lambda *a, **k: "b",
|
||||||
)
|
)
|
||||||
|
|
||||||
pm.handle_retrieve_entry()
|
pm.handle_retrieve_entry()
|
||||||
|
@@ -66,7 +66,7 @@ def test_totp_display_secret_mode(monkeypatch, capsys):
|
|||||||
pm.entry_manager, "get_totp_time_remaining", lambda *a, **k: 30
|
pm.entry_manager, "get_totp_time_remaining", lambda *a, **k: 30
|
||||||
)
|
)
|
||||||
monkeypatch.setattr(
|
monkeypatch.setattr(
|
||||||
"password_manager.manager.select.select",
|
"password_manager.manager.timed_input",
|
||||||
lambda *a, **k: (_ for _ in ()).throw(KeyboardInterrupt()),
|
lambda *a, **k: (_ for _ in ()).throw(KeyboardInterrupt()),
|
||||||
)
|
)
|
||||||
called = []
|
called = []
|
||||||
@@ -115,7 +115,7 @@ def test_totp_display_no_secret_mode(monkeypatch, capsys):
|
|||||||
pm.entry_manager, "get_totp_time_remaining", lambda *a, **k: 30
|
pm.entry_manager, "get_totp_time_remaining", lambda *a, **k: 30
|
||||||
)
|
)
|
||||||
monkeypatch.setattr(
|
monkeypatch.setattr(
|
||||||
"password_manager.manager.select.select",
|
"password_manager.manager.timed_input",
|
||||||
lambda *a, **k: (_ for _ in ()).throw(KeyboardInterrupt()),
|
lambda *a, **k: (_ for _ in ()).throw(KeyboardInterrupt()),
|
||||||
)
|
)
|
||||||
called = []
|
called = []
|
||||||
|
216
src/utils/imghdr_stub.py
Normal file
216
src/utils/imghdr_stub.py
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
"""Compat module providing :mod:`imghdr` for Python 3.13+.
|
||||||
|
|
||||||
|
This is a copy of Python 3.12's :mod:`imghdr` module which was removed in
|
||||||
|
Python 3.13. It is used by the ``pgpy`` dependency when deriving PGP keys.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from os import PathLike
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
__all__ = ["what"]
|
||||||
|
|
||||||
|
warnings._deprecated(__name__, remove=(3, 13))
|
||||||
|
|
||||||
|
# -------------------------
|
||||||
|
# Recognize image headers
|
||||||
|
# -------------------------
|
||||||
|
|
||||||
|
|
||||||
|
def what(file, h=None):
|
||||||
|
"""Return the type of image contained in a file or byte stream."""
|
||||||
|
f = None
|
||||||
|
try:
|
||||||
|
if h is None:
|
||||||
|
if isinstance(file, (str, PathLike)):
|
||||||
|
f = open(file, "rb")
|
||||||
|
h = f.read(32)
|
||||||
|
else:
|
||||||
|
location = file.tell()
|
||||||
|
h = file.read(32)
|
||||||
|
file.seek(location)
|
||||||
|
for tf in tests:
|
||||||
|
res = tf(h, f)
|
||||||
|
if res:
|
||||||
|
return res
|
||||||
|
finally:
|
||||||
|
if f:
|
||||||
|
f.close()
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------
|
||||||
|
# Subroutines per image file type
|
||||||
|
# ---------------------------------
|
||||||
|
|
||||||
|
tests: list = []
|
||||||
|
|
||||||
|
|
||||||
|
def test_jpeg(h, f):
|
||||||
|
"""Test for JPEG data with JFIF or Exif markers; and raw JPEG."""
|
||||||
|
if h[6:10] in (b"JFIF", b"Exif"):
|
||||||
|
return "jpeg"
|
||||||
|
elif h[:4] == b"\xff\xd8\xff\xdb":
|
||||||
|
return "jpeg"
|
||||||
|
|
||||||
|
|
||||||
|
tests.append(test_jpeg)
|
||||||
|
|
||||||
|
|
||||||
|
def test_png(h, f):
|
||||||
|
"""Verify if the image is a PNG."""
|
||||||
|
if h.startswith(b"\211PNG\r\n\032\n"):
|
||||||
|
return "png"
|
||||||
|
|
||||||
|
|
||||||
|
tests.append(test_png)
|
||||||
|
|
||||||
|
|
||||||
|
def test_gif(h, f):
|
||||||
|
"""Verify if the image is a GIF ('87 or '89 variants)."""
|
||||||
|
if h[:6] in (b"GIF87a", b"GIF89a"):
|
||||||
|
return "gif"
|
||||||
|
|
||||||
|
|
||||||
|
tests.append(test_gif)
|
||||||
|
|
||||||
|
|
||||||
|
def test_tiff(h, f):
|
||||||
|
"""Verify if the image is a TIFF (Motorola or Intel)."""
|
||||||
|
if h[:2] in (b"MM", b"II"):
|
||||||
|
return "tiff"
|
||||||
|
|
||||||
|
|
||||||
|
tests.append(test_tiff)
|
||||||
|
|
||||||
|
|
||||||
|
def test_rgb(h, f):
|
||||||
|
"""Test for the SGI image library."""
|
||||||
|
if h.startswith(b"\001\332"):
|
||||||
|
return "rgb"
|
||||||
|
|
||||||
|
|
||||||
|
tests.append(test_rgb)
|
||||||
|
|
||||||
|
|
||||||
|
def test_pbm(h, f):
|
||||||
|
"""Verify if the image is a PBM."""
|
||||||
|
if len(h) >= 3 and h[0] == ord(b"P") and h[1] in b"14" and h[2] in b" \t\n\r":
|
||||||
|
return "pbm"
|
||||||
|
|
||||||
|
|
||||||
|
tests.append(test_pbm)
|
||||||
|
|
||||||
|
|
||||||
|
def test_pgm(h, f):
|
||||||
|
"""Verify if the image is a PGM."""
|
||||||
|
if len(h) >= 3 and h[0] == ord(b"P") and h[1] in b"25" and h[2] in b" \t\n\r":
|
||||||
|
return "pgm"
|
||||||
|
|
||||||
|
|
||||||
|
tests.append(test_pgm)
|
||||||
|
|
||||||
|
|
||||||
|
def test_ppm(h, f):
|
||||||
|
"""Verify if the image is a PPM."""
|
||||||
|
if len(h) >= 3 and h[0] == ord(b"P") and h[1] in b"36" and h[2] in b" \t\n\r":
|
||||||
|
return "ppm"
|
||||||
|
|
||||||
|
|
||||||
|
tests.append(test_ppm)
|
||||||
|
|
||||||
|
|
||||||
|
def test_rast(h, f):
|
||||||
|
"""Test for the Sun raster file."""
|
||||||
|
if h.startswith(b"\x59\xa6\x6a\x95"):
|
||||||
|
return "rast"
|
||||||
|
|
||||||
|
|
||||||
|
tests.append(test_rast)
|
||||||
|
|
||||||
|
|
||||||
|
def test_xbm(h, f):
|
||||||
|
"""Verify if the image is a X bitmap."""
|
||||||
|
if h.startswith(b"#define "):
|
||||||
|
return "xbm"
|
||||||
|
|
||||||
|
|
||||||
|
tests.append(test_xbm)
|
||||||
|
|
||||||
|
|
||||||
|
def test_bmp(h, f):
|
||||||
|
"""Verify if the image is a BMP file."""
|
||||||
|
if h.startswith(b"BM"):
|
||||||
|
return "bmp"
|
||||||
|
|
||||||
|
|
||||||
|
tests.append(test_bmp)
|
||||||
|
|
||||||
|
|
||||||
|
def test_webp(h, f):
|
||||||
|
"""Verify if the image is a WebP."""
|
||||||
|
if h.startswith(b"RIFF") and h[8:12] == b"WEBP":
|
||||||
|
return "webp"
|
||||||
|
|
||||||
|
|
||||||
|
tests.append(test_webp)
|
||||||
|
|
||||||
|
|
||||||
|
def test_exr(h, f):
|
||||||
|
"""Verify if the image is an OpenEXR file."""
|
||||||
|
if h.startswith(b"\x76\x2f\x31\x01"):
|
||||||
|
return "exr"
|
||||||
|
|
||||||
|
|
||||||
|
tests.append(test_exr)
|
||||||
|
|
||||||
|
|
||||||
|
# --------------------
|
||||||
|
# Small test program
|
||||||
|
# --------------------
|
||||||
|
|
||||||
|
|
||||||
|
def test(): # pragma: no cover - only used for manual testing
|
||||||
|
import sys
|
||||||
|
|
||||||
|
recursive = 0
|
||||||
|
if sys.argv[1:] and sys.argv[1] == "-r":
|
||||||
|
del sys.argv[1:2]
|
||||||
|
recursive = 1
|
||||||
|
try:
|
||||||
|
if sys.argv[1:]:
|
||||||
|
testall(sys.argv[1:], recursive, 1)
|
||||||
|
else:
|
||||||
|
testall(["."], recursive, 1)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
sys.stderr.write("\n[Interrupted]\n")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def testall(list, recursive, toplevel): # pragma: no cover - only for manual use
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
for filename in list:
|
||||||
|
if os.path.isdir(filename):
|
||||||
|
print(filename + "/:", end=" ")
|
||||||
|
if recursive or toplevel:
|
||||||
|
print("recursing down:")
|
||||||
|
import glob
|
||||||
|
|
||||||
|
names = glob.glob(os.path.join(glob.escape(filename), "*"))
|
||||||
|
testall(names, recursive, 0)
|
||||||
|
else:
|
||||||
|
print("*** directory (use -r) ***")
|
||||||
|
else:
|
||||||
|
print(filename + ":", end=" ")
|
||||||
|
sys.stdout.flush()
|
||||||
|
try:
|
||||||
|
print(what(filename))
|
||||||
|
except OSError:
|
||||||
|
print("*** not found ***")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__": # pragma: no cover - manual run
|
||||||
|
test()
|
Reference in New Issue
Block a user