From 96d535cf9a88032c8b73b3839fcddab41efbc90f Mon Sep 17 00:00:00 2001 From: Jan200101 Date: Thu, 11 Nov 2021 10:16:35 +0100 Subject: initial commit --- .gitignore | 5 +++ LICENSE | 22 ++++++++++++++ MANIFEST.in | 3 ++ README.md | 22 ++++++++++++++ requirements.txt | 0 setup.py | 49 ++++++++++++++++++++++++++++++ unixreg/__init__.py | 10 ++++++ unixreg/constants.py | 47 ++++++++++++++++++++++++++++ unixreg/functions.py | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++ unixreg/key.py | 34 +++++++++++++++++++++ 10 files changed, 278 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 MANIFEST.in create mode 100644 README.md create mode 100644 requirements.txt create mode 100755 setup.py create mode 100644 unixreg/__init__.py create mode 100644 unixreg/constants.py create mode 100644 unixreg/functions.py create mode 100644 unixreg/key.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fdf69b4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +build +dist +*.egg-info +__pycache__ +*.pyc diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..50f9d6e --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2021 Jan Drögehoff + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..bb910eb --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,3 @@ +include README.md +include LICENSE +include requirements.txt diff --git a/README.md b/README.md new file mode 100644 index 0000000..287214a --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# unixreg + +## why +While working on porting a python application to Linux I came across many uses of winreg that could not easily be ported over. + +Instead of reworking the system I decided to implement a bandaid solution that deals with it transparently. + +## how to use +Update your winreg imports with this + +```py +try: + import winreg +except ImportError: + import unixreg as winreg +``` + +simply importing unixreg should be enough though, winreg is imported if found + +## license +this project is licensed under the [MIT License](LICENSE) +feel free to do whatever you want with it diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e69de29 diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..b0b7f5b --- /dev/null +++ b/setup.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +import setuptools +import re + +requirements = [] +with open('requirements.txt') as f: + requirements = f.read().splitlines() + +version = None +with open('unixreg/__init__.py') as f: + version = re.search(r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]', f.read(), re.MULTILINE).group(1) + +if not version: + raise RuntimeError('version is not set') + +long_description = "" +with open("README.md", "r") as fh: + long_description = fh.read() + + +setuptools.setup( + name="unixreg", + version=version, + author="Jan Drögehoff", + author_email="jandroegehoff@gmail.com", + description="winreg implementation for non NT systems", + long_description=long_description, + long_description_content_type="text/markdown", + url="https://github.com/Jan200101/unixreg", + packages=["unixreg"], + license="MIT", + install_requires=requirements, + include_package_data=True, + classifiers=[ + "Development Status :: 3 - Alpha", + + "Programming Language :: Python :: 3", + + "License :: OSI Approved :: MIT License", + + "Operating System :: POSIX", + "Operating System :: POSIX :: BSD", + "Operating System :: POSIX :: Linux", + + "Topic :: Software Development :: Libraries :: Python Modules", + + "Typing :: Typed" + ], +) diff --git a/unixreg/__init__.py b/unixreg/__init__.py new file mode 100644 index 0000000..21e4674 --- /dev/null +++ b/unixreg/__init__.py @@ -0,0 +1,10 @@ +__version__ = "0.0.0" + + +# upwards compatibility with winreg +try: + from winreg import * +except ImportError: + from .functions import * + from .constants import * + from .key import * diff --git a/unixreg/constants.py b/unixreg/constants.py new file mode 100644 index 0000000..b073707 --- /dev/null +++ b/unixreg/constants.py @@ -0,0 +1,47 @@ +# 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 + +# https://docs.microsoft.com/en-us/windows/win32/secauthz/standard-access-rights +STANDARD_RIGHTS_REQUIRED = 1 +STANDARD_RIGHTS_WRITE = 1 +STANDARD_RIGHTS_READ = 1 + +# Access Rights +KEY_EXECUTE = 1 << 0 +KEY_QUERY_VALUE = 1 << 1 +KEY_SET_VALUE = 1 << 2 +KEY_CREATE_SUB_KEY = 1 << 3 +KEY_ENUMERATE_SUB_KEYS = 1 << 4 +KEY_NOTIFY = 1 << 5 +KEY_CREATE_LINK = 1 << 6 + +KEY_WRITE = STANDARD_RIGHTS_WRITE ^ KEY_SET_VALUE ^ KEY_CREATE_SUB_KEY +KEY_READ = STANDARD_RIGHTS_READ ^ KEY_QUERY_VALUE ^ KEY_ENUMERATE_SUB_KEYS +KEY_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED ^ KEY_QUERY_VALUE ^ KEY_SET_VALUE ^ KEY_CREATE_SUB_KEY ^ KEY_ENUMERATE_SUB_KEYS ^ KEY_NOTIFY ^ KEY_CREATE_LINK + +# 64-bit Specific +KEY_WOW64_64KEY = 1 << 7 +KEY_WOW64_32KEY = 1 << 8 + +# Value Types +REG_BINARY = 1 << 0 +REG_DWORD = 1 << 1 +REG_DWORD_LITTLE_ENDIAN = 1 << 2 +REG_DWORD_BIG_ENDIAN = 1 << 3 +REG_EXPAND_SZ = 1 << 4 +REG_LINK = 1 << 5 +REG_MULTI_SZ = 1 << 6 +REG_NONE = 1 << 7 +REG_QWORD = 1 << 8 +REG_QWORD_LITTLE_ENDIAN = 1 << 9 +REG_RESOURCE_LIST = 1 << 10 +REG_FULL_RESOURCE_DESCRIPTOR = 1 << 11 +REG_RESOURCE_REQUIREMENTS_LIST = 1 << 12 +REG_SZ = 1 << 13 + diff --git a/unixreg/functions.py b/unixreg/functions.py new file mode 100644 index 0000000..9b6de32 --- /dev/null +++ b/unixreg/functions.py @@ -0,0 +1,86 @@ +import os +from typing import Union + +from .constants import * + +KEY_TYPE = Union[str] + +_KEY_CACHE = {} +_ENV_REPLACE = { + "USERPROFILE": "HOME" +} + +def CloseKey(key): + pass + +def ConnectRegistry(computer: Union[str, None], key: str): + if not computer: + return OpenKey(key, None) + + raise OSError("Not Implemented") + +def CreateKey(key: KEY_TYPE, sub_key: Union[str, None]): + return CreateKeyEx(key, sub_key) + +def CreateKeyEx(key: KEY_TYPE, sub_key: Union[str, None], reserved=0, access=KEY_WRITE): + pass + +def DeleteKey(key: KEY_TYPE, sub_key: Union[str, None]): + return DeleteKeyEx(key, sub_key) + +def DeleteKeyEx(key: KEY_TYPE, sub_key: Union[str, None], access=KEY_WOW64_64KEY, reserved=0): + pass + +def DeleteValue(key: KEY_TYPE, value: str): + pass + +def EnumKey(key: KEY_TYPE, index: int): + pass + +def EnumValue(key: KEY_TYPE, index: int): + pass + +def ExpandEnvironmentStrings(env: str): + """ + TODO Jan: correctly implement + %HOME%/whatever => /home/sentry/whatever + """ + return os.getenv(env) + +def FlushKey(key: KEY_TYPE): + pass + +def LoadKey(key: KEY_TYPE, sub_key: Union[str, None], file_name: str): + pass + +def OpenKeyEx(key: KEY_TYPE, sub_key: Union[str, None], reserved=0, access=KEY_READ): + pass + +OpenKey = OpenKeyEx + +def QueryInfoKey(key: KEY_TYPE): + pass + +def QueryValueEx(key: KEY_TYPE, sub_key: Union[str, None]): + pass + +QueryValue = QueryValueEx + +def SaveKey(key: KEY_TYPE, file_name: str): + pass + +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 + +def DisableReflectionKey(key: KEY_TYPE): + raise NotImplementedError("Not Implemented") + +def EnableReflectionKey(key: KEY_TYPE): + raise NotImplementedError("Not Implemented") + +def QueryReflectionKey(key: KEY_TYPE): + raise NotImplementedError("Not Implemented") + diff --git a/unixreg/key.py b/unixreg/key.py new file mode 100644 index 0000000..36d65e6 --- /dev/null +++ b/unixreg/key.py @@ -0,0 +1,34 @@ +from copy import deepcopy +from typing import Union + +_HANDLE_COUNTER = 0 + +class RegKey: + + def __init__(self): + pass + + def __add__(self, other: Union[str]): + if isinstance(other, __class__): + other = other.key + + if isinstance(other, str): + retval = deepcopy(self) + retval.key = f"{self.key}/{other}" + + return None + + def __enter__(self): + pass + + def __exit__(self): + pass + + def Close(self): + pass + + def Detach(self): + pass + + +PyHKEY = RegKey \ No newline at end of file -- cgit v1.2.3