citadel-core/app/lib/citadelutils.py

103 lines
3.5 KiB
Python
Raw Normal View History

2022-01-28 06:52:26 +00:00
# SPDX-FileCopyrightText: 2021-2022 Citadel and contributors
#
2022-01-21 20:37:48 +00:00
# SPDX-License-Identifier: GPL-3.0-or-later
import re
# Helper functions
2022-01-09 16:32:29 +00:00
# Return a list of env vars in a string, supports both $NAME and ${NAME} format for the env var
# This can potentially be used to get around permissions, so this check is critical for security
# Please report any security vulnerabilities you find in this check to aaron.dewes@protonmail.com
def getEnvVars(string: str):
string = str(string)
envVars = re.findall(r'\$\{.*?\}', string)
newEnvVars = re.findall(r"\$(?!{)([A-z1-9]+)", string)
return [envVar[2:-1] for envVar in envVars] + newEnvVars
# Check if an array only contains values which are also in another array
def checkArrayContainsAllElements(array: list, otherArray: list):
for element in array:
if element not in otherArray:
return False
return True
# Parse a dotenv file
# Values can either be KEY=VALUE or KEY="VALUE" or KEY='VALUE'
# Returns all env vars as a dict
def parse_dotenv(file_path):
envVars: dict = {}
with open(file_path, 'r') as file:
for line in file:
line = line.strip()
if line.startswith('#') or len(line) == 0:
continue
if '=' in line:
key, value = line.split('=', 1)
value = value.strip('"').strip("'")
envVars[key] = value
else:
print("Error: Invalid line in {}: {}".format(file_path, line))
print("Line should be in the format KEY=VALUE or KEY=\"VALUE\" or KEY='VALUE'")
exit(1)
return envVars
2021-11-17 18:04:06 +00:00
# Combines an object and a class
# If the key exists in both objects, the value of the second object is used
# If the key does not exist in the first object, the value from the second object is used
# If a key contains a list, the second object's list is appended to the first object's list
# If a key contains another object, these objects are combined
2021-11-17 18:04:06 +00:00
def combineObjectAndClass(theClass, obj: dict):
for key, value in obj.items():
if key in theClass.__dict__:
if isinstance(value, list):
if isinstance(theClass.__dict__[key], list):
theClass.__dict__[key].extend(value)
else:
theClass.__dict__[key] = [theClass.__dict__[key]] + value
elif isinstance(value, dict):
if isinstance(theClass.__dict__[key], dict):
theClass.__dict__[key].update(value)
else:
theClass.__dict__[key] = {theClass.__dict__[key]: value}
else:
theClass.__dict__[key] = value
else:
theClass.__dict__[key] = value
def is_builtin_type(obj):
2021-11-17 18:47:48 +00:00
return isinstance(obj, (int, float, str, bool, list, dict))
2021-11-17 18:04:06 +00:00
# Convert a class to a dict
# Also strip any class member which is null or empty
def classToDict(theClass):
obj: dict = {}
for key, value in theClass.__dict__.items():
if value is None or (isinstance(value, list) and len(value) == 0):
continue
if isinstance(value, list):
2021-11-21 19:02:47 +00:00
newList = []
2021-11-17 18:04:06 +00:00
for element in value:
if is_builtin_type(element):
newList.append(element)
else:
newList.append(classToDict(element))
obj[key] = newList
elif isinstance(value, dict):
newDict = {}
2021-11-17 18:47:48 +00:00
for subkey, subvalue in value.items():
if is_builtin_type(subvalue):
newDict[subkey] = subvalue
else:
2021-11-17 18:47:48 +00:00
newDict[subkey] = classToDict(subvalue)
2021-11-17 18:04:06 +00:00
obj[key] = newDict
elif is_builtin_type(value):
obj[key] = value
else:
#print(value)
obj[key] = classToDict(value)
return obj