From 3cdc601d9cf56c5ffac428b7500116a867f4cd15 Mon Sep 17 00:00:00 2001 From: Jan200101 Date: Fri, 12 Nov 2021 20:36:24 +0100 Subject: implement basic functionality far enough to be useful --- README.md | 4 +-- unixreg/__init__.py | 2 +- unixreg/constants.py | 14 ++++---- unixreg/functions.py | 96 ++++++++++++++++++++++++++++++++++++---------------- unixreg/key.py | 37 +++++++++++++++----- 5 files changed, 105 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 287214a..a8c167c 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ Update your winreg imports with this ```py try: - import winreg + import winreg except ImportError: - import unixreg as winreg + import unixreg as winreg ``` simply importing unixreg should be enough though, winreg is imported if found diff --git a/unixreg/__init__.py b/unixreg/__init__.py index 21e4674..fdab30a 100644 --- a/unixreg/__init__.py +++ b/unixreg/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.0.0" +__version__ = "0.1.0" # upwards compatibility with winreg diff --git a/unixreg/constants.py b/unixreg/constants.py index b073707..4a1e4b9 100644 --- a/unixreg/constants.py +++ b/unixreg/constants.py @@ -1,11 +1,11 @@ # HKEY_* -HKEY_CLASSES_ROOT = 1 -HKEY_CURRENT_USER = 2 -HKEY_LOCAL_MACHINE = 3 -HKEY_USERS = 4 -HKEY_PERFORMANCE_DATA = 5 -HKEY_CURRENT_CONFIG = 6 -HKEY_DYN_DATA = 7 +HKEY_CLASSES_ROOT = "HKEY_CLASSES_ROOT" +HKEY_CURRENT_USER = "HKEY_CURRENT_USER" +HKEY_LOCAL_MACHINE = "HKEY_LOCAL_MACHINE" +HKEY_USERS = "HKEY_USERS" +HKEY_PERFORMANCE_DATA = "HKEY_PERFORMANCE_DATA" +HKEY_CURRENT_CONFIG = "HKEY_CURRENT_CONFIG" +HKEY_DYN_DATA = "HKEY_DYN_DATA" # https://docs.microsoft.com/en-us/windows/win32/secauthz/standard-access-rights STANDARD_RIGHTS_REQUIRED = 1 diff --git a/unixreg/functions.py b/unixreg/functions.py index 9b6de32..50d4be5 100644 --- a/unixreg/functions.py +++ b/unixreg/functions.py @@ -1,79 +1,115 @@ import os from typing import Union -from .constants import * +from .key import RegKey +from .constants import KEY_WOW64_64KEY, KEY_WRITE, KEY_READ -KEY_TYPE = Union[str] +KEY_TYPE = Union[str, RegKey] +SUBKEY_TYPE = KEY_TYPE | Union[None] _KEY_CACHE = {} _ENV_REPLACE = { - "USERPROFILE": "HOME" + "USERPROFILE": os.getenv("HOME") } -def CloseKey(key): - pass +_CONFIG_DIR = os.getenv("XDG_CONFIG_HOME") +if not _CONFIG_DIR: + _CONFIG_DIR = os.path.join(os.getenv("HOME"), ".config") +_CONFIG_DIR = os.path.join(_CONFIG_DIR, "unixreg") -def ConnectRegistry(computer: Union[str, None], key: str): +def __init_values(key: KEY_TYPE, sub_key, access): + if isinstance(key, str): + key = RegKey(key) + + if sub_key: + key = key + sub_key + key.access = access + + return key + +def __create_key(key: RegKey): + path = os.path.join(_CONFIG_DIR, key.key) + + os.makedirs(path, exist_ok=True) + +def CloseKey(key: KEY_TYPE): + if isinstance(key, RegKey): + key.Close() + +def ConnectRegistry(computer: SUBKEY_TYPE, key: str): if not computer: return OpenKey(key, None) + # ConnectRegistry is expected to throw an OSError on failure + # any program that fails to catch this is to blame raise OSError("Not Implemented") -def CreateKey(key: KEY_TYPE, sub_key: Union[str, None]): +def CreateKey(key: KEY_TYPE, sub_key: SUBKEY_TYPE): return CreateKeyEx(key, sub_key) -def CreateKeyEx(key: KEY_TYPE, sub_key: Union[str, None], reserved=0, access=KEY_WRITE): - pass +def CreateKeyEx(key: KEY_TYPE, sub_key: SUBKEY_TYPE, reserved=0, access=KEY_WRITE): + key = __init_values(key, sub_key, access) + + __create_key(key) + + return key -def DeleteKey(key: KEY_TYPE, sub_key: Union[str, None]): + +def DeleteKey(key: KEY_TYPE, sub_key: SUBKEY_TYPE): return DeleteKeyEx(key, sub_key) -def DeleteKeyEx(key: KEY_TYPE, sub_key: Union[str, None], access=KEY_WOW64_64KEY, reserved=0): - pass +def DeleteKeyEx(key: KEY_TYPE, sub_key: SUBKEY_TYPE, access=KEY_WOW64_64KEY, reserved=0): + key = __init_values(key, sub_key, access) + + path = os.path.join(_CONFIG_DIR, key.key) + if os.path.isfile(path): + os.remove(path) def DeleteValue(key: KEY_TYPE, value: str): - pass + raise NotImplementedError("Not Implemented") def EnumKey(key: KEY_TYPE, index: int): - pass + raise NotImplementedError("Not Implemented") def EnumValue(key: KEY_TYPE, index: int): - pass + raise NotImplementedError("Not Implemented") def ExpandEnvironmentStrings(env: str): - """ - TODO Jan: correctly implement - %HOME%/whatever => /home/sentry/whatever - """ - return os.getenv(env) + for var in _ENV_REPLACE: + env = env.replace(f"%{var}%", _ENV_REPLACE[var]) + env.replace("\\", os.path.sep) + return env def FlushKey(key: KEY_TYPE): - pass + raise NotImplementedError("Not Implemented") -def LoadKey(key: KEY_TYPE, sub_key: Union[str, None], file_name: str): - pass +def LoadKey(key: KEY_TYPE, sub_key: SUBKEY_TYPE, file_name: str): + raise NotImplementedError("Not Implemented") -def OpenKeyEx(key: KEY_TYPE, sub_key: Union[str, None], reserved=0, access=KEY_READ): - pass +def OpenKeyEx(key: KEY_TYPE, sub_key: SUBKEY_TYPE, reserved=0, access=KEY_READ): + return CreateKeyEx(key, sub_key, reserved, access) OpenKey = OpenKeyEx def QueryInfoKey(key: KEY_TYPE): - pass + QueryValueEx(key, None) -def QueryValueEx(key: KEY_TYPE, sub_key: Union[str, None]): - pass +def QueryValueEx(key: KEY_TYPE, sub_key: SUBKEY_TYPE): + return "bla" QueryValue = QueryValueEx def SaveKey(key: KEY_TYPE, file_name: str): - pass + raise NotImplementedError("Not Implemented") def SetValue(key: KEY_TYPE, sub_key: str, typei: int, value: str): return SetValueEx(key, sub_key, 0, typei, value) def SetValueEx(key: KEY_TYPE, value_name: str, reserved: int, type: int, value: str): - pass + print("BLABLABLA", key, value_name, value) + filepath = os.path.join(_CONFIG_DIR, key.key, value_name) + with open(filepath, "w") as file: + file.write(value) def DisableReflectionKey(key: KEY_TYPE): raise NotImplementedError("Not Implemented") diff --git a/unixreg/key.py b/unixreg/key.py index 36d65e6..e50415b 100644 --- a/unixreg/key.py +++ b/unixreg/key.py @@ -1,29 +1,50 @@ +import os from copy import deepcopy -from typing import Union +from typing import TypeVar, Union + +from .constants import STANDARD_RIGHTS_REQUIRED + +RegKeyT = TypeVar("RegKeyT", bound="RegKey") _HANDLE_COUNTER = 0 class RegKey: - def __init__(self): - pass + def __init__(self, key: str = "", access: int = STANDARD_RIGHTS_REQUIRED): + global _HANDLE_COUNTER + _HANDLE_COUNTER += 1 + + self.key = key + self.handle = _HANDLE_COUNTER + self.access = access - def __add__(self, other: Union[str]): + def __add__(self, other: Union[str, RegKeyT]) -> RegKeyT: if isinstance(other, __class__): other = other.key if isinstance(other, str): + other = other.replace("\\\\", "\\").replace("\\", os.path.sep) retval = deepcopy(self) - retval.key = f"{self.key}/{other}" + retval.key = os.path.join(self.key, other) + return retval return None - def __enter__(self): - pass + def __access(self, access): + self.access = access + + def __enter__(self) -> RegKeyT: + return self - def __exit__(self): + def __exit__(self, *args, **kwargs): pass + def __repr__(self): + return __class__.__name__ + + def __str__(self): + return f"{__class__.__name__}({self.key}, {self.handle}, {self.access})" + def Close(self): pass -- cgit v1.2.3