11 |
11 |
|
|
12 |
12 |
|
from .log import logger |
13 |
13 |
|
|
|
14 |
+ |
# redirect STDIN/STDERR from subprocess |
|
15 |
+ |
subprocess_piped = partial(subprocess.run, |
|
16 |
+ |
encoding="utf-8", |
|
17 |
+ |
stdout=subprocess.PIPE, |
|
18 |
+ |
stderr=subprocess.PIPE) |
|
19 |
+ |
|
14 |
20 |
|
|
15 |
21 |
|
class KeepassWrapper: |
16 |
22 |
|
""" |
17 |
23 |
|
Functions that create a subprocess and call the keepassxc-cli shell command |
18 |
24 |
|
""" |
19 |
25 |
|
|
20 |
|
- |
subprocess_piped = partial( |
21 |
|
- |
subprocess.run, encoding="utf-8", stdout=subprocess.PIPE, stderr=subprocess.PIPE |
22 |
|
- |
) |
|
26 |
+ |
KEEPASSXC_CLI_NAME = "keepassxc-cli" |
23 |
27 |
|
|
24 |
|
- |
@staticmethod |
25 |
|
- |
def verify_binary_exists(): |
26 |
|
- |
"""Make sure the keepassxc-cli binary exists""" |
27 |
|
- |
if shutil.which("keepassxc-cli") is None: |
28 |
|
- |
logger.critical( |
29 |
|
- |
"Could not find the keepassxc-cli binary. Verify its installed and on your $PATH." |
30 |
|
- |
) |
31 |
|
- |
sys.exit(1) |
|
28 |
+ |
def __init__(self, keepassxc_cli_location: Optional[pathlib.Path] = None): |
|
29 |
+ |
""" |
|
30 |
+ |
Create an instance of KeepassWrapper, with an optional |
|
31 |
+ |
path to the keepassxc-cli binary. |
|
32 |
+ |
|
|
33 |
+ |
|
|
34 |
+ |
Allow the path of the keepassxc-cli to be changed because |
|
35 |
+ |
some package managers (e.g. mint with snap) call |
|
36 |
+ |
this the binary keepassxc.cli |
|
37 |
+ |
""" |
|
38 |
+ |
|
|
39 |
+ |
if keepassxc_cli_location is None: |
|
40 |
+ |
# search for keepassxc-cli which default name on $PATH |
|
41 |
+ |
keepassxc_location_output = shutil.which( |
|
42 |
+ |
self.__class__.KEEPASSXC_CLI_NAME) |
|
43 |
+ |
if keepassxc_location_output is None: |
|
44 |
+ |
logger.critical( |
|
45 |
+ |
"Could not find a binary called {} on your $PATH.".format( |
|
46 |
+ |
self.__class__.KEEPASSXC_CLI_NAME)) |
|
47 |
+ |
sys.exit(1) |
|
48 |
+ |
self.keepassxc_cli_location: pathlib.Path = pathlib.Path( |
|
49 |
+ |
keepassxc_location_output) |
|
50 |
+ |
else: |
|
51 |
+ |
self.keepassxc_cli_location = keepassxc_cli_location |
|
52 |
+ |
logger.debug("keepassxc-cli location: {}".format( |
|
53 |
+ |
self.keepassxc_cli_location)) |
32 |
54 |
|
|
33 |
|
- |
@staticmethod |
34 |
|
- |
def version() -> StrictVersion: |
|
55 |
+ |
def version(self) -> StrictVersion: |
35 |
56 |
|
"""Returns the KeepassXC Version""" |
36 |
|
- |
version_proc: subprocess.CompletedProcess = KeepassWrapper.subprocess_piped( |
37 |
|
- |
shlex.split("keepassxc-cli --version") |
38 |
|
- |
) |
|
57 |
+ |
version_proc: subprocess.CompletedProcess = subprocess_piped( |
|
58 |
+ |
[self.keepassxc_cli_location, "--version"]) |
39 |
59 |
|
version_str: str = version_proc.stdout.strip() |
40 |
|
- |
logger.debug("keepassxc-cli version: {}".format(version_str)) |
|
60 |
+ |
logger.debug("keepassxc cli version: {}".format(version_str)) |
41 |
61 |
|
return StrictVersion(version_str) |
42 |
62 |
|
|
43 |
|
- |
@classmethod |
44 |
|
- |
def backwards_compatible_export(cls) -> str: |
|
63 |
+ |
def backwards_compatible_export(self) -> str: |
45 |
64 |
|
""" |
46 |
65 |
|
In KeepassXC version 2.5.0, the extract command was re-named to export |
47 |
66 |
|
Attempt to parse the version number and generate the correct subcommand |
48 |
67 |
|
""" |
49 |
68 |
|
try: |
50 |
|
- |
version: StrictVersion = cls.version() |
|
69 |
+ |
version: StrictVersion = self.version() |
51 |
70 |
|
if version < StrictVersion("2.5.0"): |
52 |
71 |
|
return "extract" |
53 |
72 |
|
else: |