2012-05-14 19:17:49 +04:00
|
|
|
import time
|
|
|
|
import os
|
|
|
|
import glob
|
|
|
|
import tempfile
|
|
|
|
import sys
|
2015-05-10 20:19:02 +03:00
|
|
|
import codecs
|
|
|
|
import unicodedata
|
|
|
|
from functools import partial
|
2012-05-14 19:17:49 +04:00
|
|
|
|
2015-05-10 20:19:02 +03:00
|
|
|
from zerobin import default_settings
|
2012-05-14 19:17:49 +04:00
|
|
|
|
|
|
|
try:
|
2015-05-10 20:19:02 +03:00
|
|
|
from zerobin.privilege import drop_privileges_permanently, coerce_user, coerce_group
|
2012-05-14 19:17:49 +04:00
|
|
|
except (AttributeError):
|
2015-05-10 20:19:02 +03:00
|
|
|
pass # privilege does't work on several plateform
|
2012-05-14 19:17:49 +04:00
|
|
|
|
2014-06-22 09:42:21 +04:00
|
|
|
try:
|
|
|
|
from runpy import run_path
|
|
|
|
except ImportError:
|
|
|
|
# python-2.6 or earlier - use simplier less-optimized execfile()
|
|
|
|
def run_path(file_path):
|
2020-08-11 17:37:03 +03:00
|
|
|
mod_globals = {"__file__": file_path}
|
2014-06-22 09:42:21 +04:00
|
|
|
execfile(file_path, mod_globals)
|
|
|
|
return mod_globals
|
|
|
|
|
2012-05-14 19:17:49 +04:00
|
|
|
|
|
|
|
def drop_privileges(user=None, group=None, wait=5):
|
|
|
|
"""
|
|
|
|
Try to set the process user and group to another one.
|
|
|
|
If no group is provided, it's set to the same as the user.
|
|
|
|
You can wait for a certain time before doing so.
|
|
|
|
"""
|
|
|
|
if wait:
|
|
|
|
time.sleep(wait)
|
|
|
|
if user:
|
|
|
|
group = group or user
|
|
|
|
try:
|
|
|
|
user = coerce_user(user)
|
|
|
|
group = coerce_group(group)
|
|
|
|
|
2020-08-11 17:37:03 +03:00
|
|
|
lock_files = glob.glob(os.path.join(tempfile.gettempdir(), "bottle.*.lock"))
|
2012-05-14 19:17:49 +04:00
|
|
|
for lock_file in lock_files:
|
|
|
|
os.chown(lock_file, user, group)
|
|
|
|
|
|
|
|
drop_privileges_permanently(user, group, ())
|
|
|
|
except Exception:
|
2015-05-10 20:19:02 +03:00
|
|
|
print("Failed to drop privileges. Running with current user.")
|
2012-05-14 19:17:49 +04:00
|
|
|
|
|
|
|
|
|
|
|
def dmerge(*args):
|
|
|
|
"""
|
|
|
|
Return new directionay being the sum of all merged dictionaries passed
|
|
|
|
as arguments
|
|
|
|
"""
|
|
|
|
dictionary = {}
|
|
|
|
for arg in args:
|
|
|
|
dictionary.update(arg)
|
|
|
|
return dictionary
|
|
|
|
|
|
|
|
|
2015-05-10 20:19:02 +03:00
|
|
|
class SettingsValidationError(Exception):
|
|
|
|
pass
|
2013-04-29 22:17:37 +04:00
|
|
|
|
|
|
|
|
2012-05-14 19:17:49 +04:00
|
|
|
class SettingsContainer(object):
|
|
|
|
"""
|
|
|
|
Singleton containing the settings for the whole app
|
|
|
|
"""
|
|
|
|
|
|
|
|
_instance = None
|
|
|
|
|
|
|
|
def __new__(cls, *args, **kwargs):
|
|
|
|
|
|
|
|
if not cls._instance:
|
2020-08-11 17:37:03 +03:00
|
|
|
cls._instance = super(SettingsContainer, cls).__new__(cls, *args, **kwargs)
|
2012-05-14 19:17:49 +04:00
|
|
|
cls._instance.update_with_module(default_settings)
|
|
|
|
return cls._instance
|
|
|
|
|
2014-06-22 09:42:21 +04:00
|
|
|
def update_with_dict(self, dict):
|
2012-05-14 19:17:49 +04:00
|
|
|
"""
|
2014-06-22 09:42:21 +04:00
|
|
|
Update settings with values from the given mapping object.
|
2012-05-14 19:17:49 +04:00
|
|
|
(Taking only variable with uppercased name)
|
|
|
|
"""
|
2015-05-10 20:19:02 +03:00
|
|
|
for name, value in dict.items():
|
2012-05-14 19:17:49 +04:00
|
|
|
if name.isupper():
|
|
|
|
setattr(self, name, value)
|
|
|
|
return self
|
|
|
|
|
2014-06-22 09:42:21 +04:00
|
|
|
def update_with_module(self, module):
|
|
|
|
"""
|
|
|
|
Update settings with values from the given module.
|
|
|
|
Uses update_with_dict() behind the scenes.
|
|
|
|
"""
|
|
|
|
return self.update_with_dict(module.__dict__)
|
|
|
|
|
2012-05-14 19:17:49 +04:00
|
|
|
@classmethod
|
|
|
|
def from_module(cls, module):
|
|
|
|
"""
|
|
|
|
Create an instance of SettingsContainer with values based
|
|
|
|
on the one in the passed module.
|
|
|
|
"""
|
|
|
|
settings = cls()
|
|
|
|
settings.update_with_module(module)
|
|
|
|
return settings
|
|
|
|
|
|
|
|
def update_with_file(self, filepath):
|
|
|
|
"""
|
|
|
|
Update settings with values from the given module file.
|
2014-06-22 09:42:21 +04:00
|
|
|
Uses update_with_dict() behind the scenes.
|
2012-05-14 19:17:49 +04:00
|
|
|
"""
|
2014-06-22 09:42:21 +04:00
|
|
|
settings = run_path(filepath)
|
|
|
|
return self.update_with_dict(settings)
|
2012-05-14 19:17:49 +04:00
|
|
|
|
|
|
|
|
|
|
|
settings = SettingsContainer()
|
2015-05-10 20:19:02 +03:00
|
|
|
|
|
|
|
|
|
|
|
def to_ascii(utext):
|
|
|
|
""" Take a unicode string and return ascii bytes.
|
|
|
|
|
|
|
|
Try to replace non ASCII char by similar ASCII char. If it can't,
|
|
|
|
replace it with "?".
|
|
|
|
"""
|
2020-08-11 17:37:03 +03:00
|
|
|
return unicodedata.normalize("NFKD", utext).encode("ascii", "replace")
|
2015-05-10 20:19:02 +03:00
|
|
|
|
|
|
|
|
|
|
|
# Make sure to always specify encoding when using open in Python 2 or 3
|
|
|
|
safe_open = partial(codecs.open, encoding="utf8")
|
|
|
|
|
|
|
|
|
|
|
|
def as_unicode(obj):
|
|
|
|
""" Return the unicode representation of an object """
|
|
|
|
try:
|
|
|
|
return unicode(obj)
|
|
|
|
except NameError:
|
|
|
|
return str(obj)
|