From 1562848999186ab7efba708c4cb421f0fbc51345 Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Fri, 8 Mar 2019 19:57:44 -0600 Subject: [PATCH] more refactoring and secured requirements.txt --- README.md | 2 +- onionr/onionr.py | 274 +++++----------------- onionr/onionrcommands/__init__.py | 23 +- onionr/onionrcommands/daemonlaunch.py | 19 +- onionr/onionrcommands/filecommands.py | 27 ++- onionr/onionrcommands/keyadders.py | 31 +++ onionr/onionrcommands/onionrstatistics.py | 21 +- onionr/onionrcommands/plugincommands.py | 68 ++++++ onionr/onionrproofs.py | 6 +- onionr/setupconfig.py | 69 ++++++ requirements.in | 9 + requirements.txt | 205 +++++++++++++++- 12 files changed, 513 insertions(+), 241 deletions(-) create mode 100644 onionr/onionrcommands/keyadders.py create mode 100644 onionr/onionrcommands/plugincommands.py create mode 100644 onionr/setupconfig.py create mode 100755 requirements.in mode change 100755 => 100644 requirements.txt diff --git a/README.md b/README.md index f5b2681e..3a4ab52d 100755 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ Encrypted, metadata-masking mail application. The following applies to Ubuntu Bionic. Other distros may have different package or command names. -* Have python3.5+, python3-pip, Tor (daemon, not browser) installed (python3-dev recommended) +* Have python3.6+, python3-pip, Tor (daemon, not browser) installed (python3-dev recommended) * Clone the git repo: `$ git clone https://gitlab.com/beardog/onionr` * cd into install direction: `$ cd onionr/` * Install the Python dependencies ([virtualenv strongly recommended](https://virtualenv.pypa.io/en/stable/userguide/)): `$ pip3 install -r requirements.txt` diff --git a/onionr/onionr.py b/onionr/onionr.py index 58dd45c5..fb9d7f20 100755 --- a/onionr/onionr.py +++ b/onionr/onionr.py @@ -33,7 +33,7 @@ import onionrutils import netcontroller, onionrstorage from netcontroller import NetController from onionrblockapi import Block -import onionrproofs, onionrexceptions, communicator +import onionrproofs, onionrexceptions, communicator, setupconfig from onionrusers import onionrusers import onionrcommands as commands # Many command definitions are here @@ -148,9 +148,15 @@ class Onionr: def exitSigterm(self, signum, frame): self.killed = True - ''' - THIS SECTION HANDLES THE COMMANDS - ''' + def setupConfig(dataDir, self = None): + setupconfig.setup_config(dataDir, self) + + def header(self, message = logger.colors.fg.pink + logger.colors.bold + 'Onionr' + logger.colors.reset + logger.colors.fg.pink + ' has started.'): + if os.path.exists('static-data/header.txt') and logger.get_level() <= logger.LEVEL_INFO: + with open('static-data/header.txt', 'rb') as file: + # only to stdout, not file or log or anything + sys.stderr.write(file.read().decode().replace('P', logger.colors.fg.pink).replace('W', logger.colors.reset + logger.colors.bold).replace('G', logger.colors.fg.green).replace('\n', logger.colors.reset + '\n').replace('B', logger.colors.bold).replace('A', '%s' % API_VERSION).replace('V', ONIONR_VERSION)) + logger.info(logger.colors.fg.lightgreen + '-> ' + str(message) + logger.colors.reset + logger.colors.fg.lightgreen + ' <-\n') def doExport(self, bHash): exportDir = self.dataDir + 'block-export/' @@ -163,6 +169,44 @@ class Onionr: with open('%s/%s.dat' % (exportDir, bHash), 'wb') as exportFile: exportFile.write(data) + def deleteRunFiles(self): + try: + os.remove(self.onionrCore.publicApiHostFile) + except FileNotFoundError: + pass + try: + os.remove(self.onionrCore.privateApiHostFile) + except FileNotFoundError: + pass + + def get_hostname(self): + try: + with open('./' + self.dataDir + 'hs/hostname', 'r') as hostname: + return hostname.read().strip() + except FileNotFoundError: + return "Not Generated" + except Exception: + return None + + def getConsoleWidth(self): + ''' + Returns an integer, the width of the terminal/cmd window + ''' + + columns = 80 + + try: + columns = int(os.popen('stty size', 'r').read().split()[1]) + except: + # if it errors, it's probably windows, so default to 80. + pass + + return columns + + ''' + THIS SECTION HANDLES THE COMMANDS + ''' + def exportBlock(self): exportDir = self.dataDir + 'block-export/' try: @@ -195,26 +239,6 @@ class Onionr: ''' commands.pubkeymanager.friend_command(self) - def deleteRunFiles(self): - try: - os.remove(self.onionrCore.publicApiHostFile) - except FileNotFoundError: - pass - try: - os.remove(self.onionrCore.privateApiHostFile) - except FileNotFoundError: - pass - - def deleteRunFiles(self): - try: - os.remove(self.onionrCore.publicApiHostFile) - except FileNotFoundError: - pass - try: - os.remove(self.onionrCore.privateApiHostFile) - except FileNotFoundError: - pass - def banBlock(self): try: ban = sys.argv[2] @@ -233,7 +257,6 @@ class Onionr: logger.warn('That block is already blacklisted') else: logger.error('Invalid block hash') - return def listConn(self): commands.onionrstatistics.show_peers(self) @@ -293,12 +316,6 @@ class Onionr: command = commands.get(argument, self.notFound) command() - return - - ''' - THIS SECTION DEFINES THE COMMANDS - ''' - def version(self, verbosity = 5, function = logger.info): ''' Displays the Onionr version @@ -310,8 +327,6 @@ class Onionr: if verbosity >= 2: function('Running on %s %s' % (platform.platform(), platform.release())) - return - def doPEX(self): '''make communicator do pex''' logger.info('Sending pex to command queue...') @@ -321,126 +336,43 @@ class Onionr: ''' Displays a list of keys (used to be called peers) (?) ''' - logger.info('%sPublic keys in database: \n%s%s' % (logger.colors.fg.lightgreen, logger.colors.fg.green, '\n'.join(self.onionrCore.listPeers()))) def addPeer(self): ''' Adds a peer (?) ''' - try: - newPeer = sys.argv[2] - except: - pass - else: - if self.onionrUtils.hasKey(newPeer): - logger.info('We already have that key') - return - logger.info("Adding peer: " + logger.colors.underline + newPeer) - try: - if self.onionrCore.addPeer(newPeer): - logger.info('Successfully added key') - except AssertionError: - logger.error('Failed to add key') - return + commands.keyadders.add_peer(self) def addAddress(self): ''' Adds a Onionr node address ''' - - try: - newAddress = sys.argv[2] - newAddress = newAddress.replace('http:', '').replace('/', '') - except: - pass - else: - logger.info("Adding address: " + logger.colors.underline + newAddress) - if self.onionrCore.addAddress(newAddress): - logger.info("Successfully added address.") - else: - logger.warn("Unable to add address.") - return + commands.keyadders.add_address(self) def enablePlugin(self): ''' Enables and starts the given plugin ''' - - if len(sys.argv) >= 3: - plugin_name = sys.argv[2] - logger.info('Enabling plugin "%s"...' % plugin_name) - plugins.enable(plugin_name, self) - else: - logger.info('%s %s ' % (sys.argv[0], sys.argv[1])) - - return + commands.plugincommands.enable_plugin(self) def disablePlugin(self): ''' Disables and stops the given plugin ''' - - if len(sys.argv) >= 3: - plugin_name = sys.argv[2] - logger.info('Disabling plugin "%s"...' % plugin_name) - plugins.disable(plugin_name, self) - else: - logger.info('%s %s ' % (sys.argv[0], sys.argv[1])) - - return + commands.plugincommands.disable_plugin(self) def reloadPlugin(self): ''' Reloads (stops and starts) all plugins, or the given plugin ''' - - if len(sys.argv) >= 3: - plugin_name = sys.argv[2] - logger.info('Reloading plugin "%s"...' % plugin_name) - plugins.stop(plugin_name, self) - plugins.start(plugin_name, self) - else: - logger.info('Reloading all plugins...') - plugins.reload(self) - - return + commands.plugincommands.reload_plugin(self) def createPlugin(self): ''' Creates the directory structure for a plugin name ''' - - if len(sys.argv) >= 3: - try: - plugin_name = re.sub('[^0-9a-zA-Z_]+', '', str(sys.argv[2]).lower()) - - if not plugins.exists(plugin_name): - logger.info('Creating plugin "%s"...' % plugin_name) - - os.makedirs(plugins.get_plugins_folder(plugin_name)) - with open(plugins.get_plugins_folder(plugin_name) + '/main.py', 'a') as main: - contents = '' - with open('static-data/default_plugin.py', 'rb') as file: - contents = file.read().decode() - - # TODO: Fix $user. os.getlogin() is B U G G Y - main.write(contents.replace('$user', 'some random developer').replace('$date', datetime.datetime.now().strftime('%Y-%m-%d')).replace('$name', plugin_name)) - - with open(plugins.get_plugins_folder(plugin_name) + '/info.json', 'a') as main: - main.write(json.dumps({'author' : 'anonymous', 'description' : 'the default description of the plugin', 'version' : '1.0'})) - - logger.info('Enabling plugin "%s"...' % plugin_name) - plugins.enable(plugin_name, self) - else: - logger.warn('Cannot create plugin directory structure; plugin "%s" exists.' % plugin_name) - - except Exception as e: - logger.error('Failed to create plugin directory structure.', e) - else: - logger.info('%s %s ' % (sys.argv[0], sys.argv[1])) - - return + commands.plugincommands.create_plugin(self) def notFound(self): ''' @@ -494,30 +426,6 @@ class Onionr: ''' commands.show_help(self, command) - def get_hostname(self): - try: - with open('./' + self.dataDir + 'hs/hostname', 'r') as hostname: - return hostname.read().strip() - except FileNotFoundError: - return "Not Generated" - except Exception: - return None - - def getConsoleWidth(self): - ''' - Returns an integer, the width of the terminal/cmd window - ''' - - columns = 80 - - try: - columns = int(os.popen('stty size', 'r').read().split()[1]) - except: - # if it errors, it's probably windows, so default to 80. - pass - - return columns - def getFile(self): ''' Get a file from onionr blocks @@ -536,79 +444,5 @@ class Onionr: ''' commands.filecommands.add_file(self, singleBlock, blockType) - def setupConfig(dataDir, self = None): - data_exists = os.path.exists(dataDir) - - if not data_exists: - os.mkdir(dataDir) - - if os.path.exists('static-data/default_config.json'): - # this is the default config, it will be overwritten if a config file already exists. Else, it saves it - with open('static-data/default_config.json', 'r') as configReadIn: - config.set_config(json.loads(configReadIn.read())) - else: - # the default config file doesn't exist, try hardcoded config - logger.warn('Default configuration file does not exist, switching to hardcoded fallback configuration!') - config.set_config({'dev_mode': True, 'log': {'file': {'output': True, 'path': dataDir + 'output.log'}, 'console': {'output': True, 'color': True}}}) - if not data_exists: - config.save() - config.reload() # this will read the configuration file into memory - - settings = 0b000 - if config.get('log.console.color', True): - settings = settings | logger.USE_ANSI - if config.get('log.console.output', True): - settings = settings | logger.OUTPUT_TO_CONSOLE - if config.get('log.file.output', True): - settings = settings | logger.OUTPUT_TO_FILE - logger.set_settings(settings) - - if not self is None: - if str(config.get('general.dev_mode', True)).lower() == 'true': - self._developmentMode = True - logger.set_level(logger.LEVEL_DEBUG) - else: - self._developmentMode = False - logger.set_level(logger.LEVEL_INFO) - - verbosity = str(config.get('log.verbosity', 'default')).lower().strip() - if not verbosity in ['default', 'null', 'none', 'nil']: - map = { - str(logger.LEVEL_DEBUG) : logger.LEVEL_DEBUG, - 'verbose' : logger.LEVEL_DEBUG, - 'debug' : logger.LEVEL_DEBUG, - str(logger.LEVEL_INFO) : logger.LEVEL_INFO, - 'info' : logger.LEVEL_INFO, - 'information' : logger.LEVEL_INFO, - str(logger.LEVEL_WARN) : logger.LEVEL_WARN, - 'warn' : logger.LEVEL_WARN, - 'warning' : logger.LEVEL_WARN, - 'warnings' : logger.LEVEL_WARN, - str(logger.LEVEL_ERROR) : logger.LEVEL_ERROR, - 'err' : logger.LEVEL_ERROR, - 'error' : logger.LEVEL_ERROR, - 'errors' : logger.LEVEL_ERROR, - str(logger.LEVEL_FATAL) : logger.LEVEL_FATAL, - 'fatal' : logger.LEVEL_FATAL, - str(logger.LEVEL_IMPORTANT) : logger.LEVEL_IMPORTANT, - 'silent' : logger.LEVEL_IMPORTANT, - 'quiet' : logger.LEVEL_IMPORTANT, - 'important' : logger.LEVEL_IMPORTANT - } - - if verbosity in map: - logger.set_level(map[verbosity]) - else: - logger.warn('Verbosity level %s is not valid, using default verbosity.' % verbosity) - - return data_exists - - def header(self, message = logger.colors.fg.pink + logger.colors.bold + 'Onionr' + logger.colors.reset + logger.colors.fg.pink + ' has started.'): - if os.path.exists('static-data/header.txt') and logger.get_level() <= logger.LEVEL_INFO: - with open('static-data/header.txt', 'rb') as file: - # only to stdout, not file or log or anything - sys.stderr.write(file.read().decode().replace('P', logger.colors.fg.pink).replace('W', logger.colors.reset + logger.colors.bold).replace('G', logger.colors.fg.green).replace('\n', logger.colors.reset + '\n').replace('B', logger.colors.bold).replace('A', '%s' % API_VERSION).replace('V', ONIONR_VERSION)) - logger.info(logger.colors.fg.lightgreen + '-> ' + str(message) + logger.colors.reset + logger.colors.fg.lightgreen + ' <-\n') - if __name__ == "__main__": Onionr() diff --git a/onionr/onionrcommands/__init__.py b/onionr/onionrcommands/__init__.py index b631f31b..35de3107 100644 --- a/onionr/onionrcommands/__init__.py +++ b/onionr/onionrcommands/__init__.py @@ -18,9 +18,26 @@ along with this program. If not, see . ''' -import webbrowser +import webbrowser, sys import logger -from . import pubkeymanager, onionrstatistics, daemonlaunch, filecommands +from . import pubkeymanager, onionrstatistics, daemonlaunch, filecommands, plugincommands, keyadders + +def show_help(o_inst, command): + + helpmenu = o_inst.getHelp() + + if command is None and len(sys.argv) >= 3: + for cmd in sys.argv[2:]: + o_inst.showHelp(cmd) + elif not command is None: + if command.lower() in helpmenu: + logger.info(logger.colors.bold + command + logger.colors.reset + logger.colors.fg.blue + ' : ' + logger.colors.reset + helpmenu[command.lower()], timestamp = False) + else: + logger.warn(logger.colors.bold + command + logger.colors.reset + logger.colors.fg.blue + ' : ' + logger.colors.reset + 'No help menu entry was found', timestamp = False) + else: + o_inst.version(0) + for command, helpmessage in helpmenu.items(): + o_inst.showHelp(command) def open_home(o_inst): try: @@ -28,7 +45,7 @@ def open_home(o_inst): except FileNotFoundError: logger.error('Onionr seems to not be running (could not get api host)') else: - url = 'http://%s/#%s' % (url, config.get('client.webpassword')) + url = 'http://%s/#%s' % (url, o_inst.onionrCore.config.get('client.webpassword')) print('If Onionr does not open automatically, use this URL:', url) webbrowser.open_new_tab(url) diff --git a/onionr/onionrcommands/daemonlaunch.py b/onionr/onionrcommands/daemonlaunch.py index 4ee4c26f..b7452a46 100644 --- a/onionr/onionrcommands/daemonlaunch.py +++ b/onionr/onionrcommands/daemonlaunch.py @@ -102,4 +102,21 @@ def kill_daemon(o_inst): net.killTor() except Exception as e: logger.error('Failed to shutdown daemon.', error = e, timestamp = False) - return \ No newline at end of file + return + +def start(o_inst, input = False, override = False): + if os.path.exists('.onionr-lock') and not override: + logger.fatal('Cannot start. Daemon is already running, or it did not exit cleanly.\n(if you are sure that there is not a daemon running, delete .onionr-lock & try again).') + else: + if not o_inst.debug and not o_inst._developmentMode: + lockFile = open('.onionr-lock', 'w') + lockFile.write('') + lockFile.close() + o_inst.running = True + o_inst.daemon() + o_inst.running = False + if not o_inst.debug and not o_inst._developmentMode: + try: + os.remove('.onionr-lock') + except FileNotFoundError: + pass \ No newline at end of file diff --git a/onionr/onionrcommands/filecommands.py b/onionr/onionrcommands/filecommands.py index e059ebb5..f9d05f01 100644 --- a/onionr/onionrcommands/filecommands.py +++ b/onionr/onionrcommands/filecommands.py @@ -1,5 +1,6 @@ import base64, sys, os import logger +from onionrblockapi import Block def add_file(o_inst, singleBlock=False, blockType='bin'): ''' Adds a file to the onionr network @@ -21,4 +22,28 @@ def add_file(o_inst, singleBlock=False, blockType='bin'): except: logger.error('Failed to save file in block.', timestamp = False) else: - logger.error('%s add-file ' % sys.argv[0], timestamp = False) \ No newline at end of file + logger.error('%s add-file ' % sys.argv[0], timestamp = False) + +def getFile(o_inst): + ''' + Get a file from onionr blocks + ''' + try: + fileName = sys.argv[2] + bHash = sys.argv[3] + except IndexError: + logger.error("Syntax %s %s" % (sys.argv[0], '/path/to/filename ')) + else: + logger.info(fileName) + + contents = None + if os.path.exists(fileName): + logger.error("File already exists") + return + if not o_inst.onionrUtils.validateHash(bHash): + logger.error('Block hash is invalid') + return + + with open(fileName, 'wb') as myFile: + myFile.write(base64.b64decode(Block(bHash, core=o_inst.onionrCore).bcontent)) + return \ No newline at end of file diff --git a/onionr/onionrcommands/keyadders.py b/onionr/onionrcommands/keyadders.py new file mode 100644 index 00000000..5004afb3 --- /dev/null +++ b/onionr/onionrcommands/keyadders.py @@ -0,0 +1,31 @@ +import sys +import logger + +def add_peer(o_inst): + try: + newPeer = sys.argv[2] + except: + pass + else: + if o_inst.onionrUtils.hasKey(newPeer): + logger.info('We already have that key') + return + logger.info("Adding peer: " + logger.colors.underline + newPeer) + try: + if o_inst.onionrCore.addPeer(newPeer): + logger.info('Successfully added key') + except AssertionError: + logger.error('Failed to add key') + +def add_address(o_inst): + try: + newAddress = sys.argv[2] + newAddress = newAddress.replace('http:', '').replace('/', '') + except: + pass + else: + logger.info("Adding address: " + logger.colors.underline + newAddress) + if self.onionrCore.addAddress(newAddress): + logger.info("Successfully added address.") + else: + logger.warn("Unable to add address.") \ No newline at end of file diff --git a/onionr/onionrcommands/onionrstatistics.py b/onionr/onionrcommands/onionrstatistics.py index beb6790d..04264655 100644 --- a/onionr/onionrcommands/onionrstatistics.py +++ b/onionr/onionrcommands/onionrstatistics.py @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . ''' -import os +import os, uuid, time import logger, onionrutils from onionrblockapi import Block import onionr @@ -90,4 +90,21 @@ def show_details(o_inst): } for detail in details: - logger.info('%s%s: \n%s%s\n' % (logger.colors.fg.lightgreen, detail, logger.colors.fg.green, details[detail]), sensitive = True) \ No newline at end of file + logger.info('%s%s: \n%s%s\n' % (logger.colors.fg.lightgreen, detail, logger.colors.fg.green, details[detail]), sensitive = True) + +def show_peers(o_inst): + randID = str(uuid.uuid4()) + o_inst.onionrCore.daemonQueueAdd('connectedPeers', responseID=randID) + while True: + try: + time.sleep(3) + peers = o_inst.onionrCore.daemonQueueGetResponse(randID) + except KeyboardInterrupt: + break + if not type(peers) is None: + if peers not in ('', 'failure', None): + if peers != False: + print(peers) + else: + print('Daemon probably not running. Unable to list connected peers.') + break \ No newline at end of file diff --git a/onionr/onionrcommands/plugincommands.py b/onionr/onionrcommands/plugincommands.py new file mode 100644 index 00000000..5978f039 --- /dev/null +++ b/onionr/onionrcommands/plugincommands.py @@ -0,0 +1,68 @@ +import sys +import logger, onionrplugins as plugins + +def enable_plugin(o_inst): + if len(sys.argv) >= 3: + plugin_name = sys.argv[2] + logger.info('Enabling plugin "%s"...' % plugin_name) + plugins.enable(plugin_name, o_inst) + else: + logger.info('%s %s ' % (sys.argv[0], sys.argv[1])) + +def disable_plugin(o_inst): + + if len(sys.argv) >= 3: + plugin_name = sys.argv[2] + logger.info('Disabling plugin "%s"...' % plugin_name) + plugins.disable(plugin_name, o_inst) + else: + logger.info('%s %s ' % (sys.argv[0], sys.argv[1])) + +def reload_plugin(o_inst): + ''' + Reloads (stops and starts) all plugins, or the given plugin + ''' + + if len(sys.argv) >= 3: + plugin_name = sys.argv[2] + logger.info('Reloading plugin "%s"...' % plugin_name) + plugins.stop(plugin_name, o_inst) + plugins.start(plugin_name, o_inst) + else: + logger.info('Reloading all plugins...') + plugins.reload(o_inst) + + +def create_plugin(o_inst): + ''' + Creates the directory structure for a plugin name + ''' + + if len(sys.argv) >= 3: + try: + plugin_name = re.sub('[^0-9a-zA-Z_]+', '', str(sys.argv[2]).lower()) + + if not plugins.exists(plugin_name): + logger.info('Creating plugin "%s"...' % plugin_name) + + os.makedirs(plugins.get_plugins_folder(plugin_name)) + with open(plugins.get_plugins_folder(plugin_name) + '/main.py', 'a') as main: + contents = '' + with open('static-data/default_plugin.py', 'rb') as file: + contents = file.read().decode() + + # TODO: Fix $user. os.getlogin() is B U G G Y + main.write(contents.replace('$user', 'some random developer').replace('$date', datetime.datetime.now().strftime('%Y-%m-%d')).replace('$name', plugin_name)) + + with open(plugins.get_plugins_folder(plugin_name) + '/info.json', 'a') as main: + main.write(json.dumps({'author' : 'anonymous', 'description' : 'the default description of the plugin', 'version' : '1.0'})) + + logger.info('Enabling plugin "%s"...' % plugin_name) + plugins.enable(plugin_name, o_inst) + else: + logger.warn('Cannot create plugin directory structure; plugin "%s" exists.' % plugin_name) + + except Exception as e: + logger.error('Failed to create plugin directory structure.', e) + else: + logger.info('%s %s ' % (sys.argv[0], sys.argv[1])) \ No newline at end of file diff --git a/onionr/onionrproofs.py b/onionr/onionrproofs.py index 040d810f..496573d0 100755 --- a/onionr/onionrproofs.py +++ b/onionr/onionrproofs.py @@ -17,10 +17,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . ''' - -import nacl.encoding, nacl.hash, nacl.utils, time, math, threading, binascii, logger, sys, base64, json -import core, onionrutils, config -import onionrblockapi +import multiprocessing, nacl.encoding, nacl.hash, nacl.utils, time, math, threading, binascii, sys, base64, json +import core, onionrutils, config, logger, onionrblockapi def getDifficultyModifier(coreOrUtilsInst=None): '''Accepts a core or utils instance returns diff --git a/onionr/setupconfig.py b/onionr/setupconfig.py new file mode 100644 index 00000000..1229faeb --- /dev/null +++ b/onionr/setupconfig.py @@ -0,0 +1,69 @@ +import os, json +import config, logger + +def setup_config(dataDir, o_inst = None): + data_exists = os.path.exists(dataDir) + + if not data_exists: + os.mkdir(dataDir) + + if os.path.exists('static-data/default_config.json'): + # this is the default config, it will be overwritten if a config file already exists. Else, it saves it + with open('static-data/default_config.json', 'r') as configReadIn: + config.set_config(json.loads(configReadIn.read())) + else: + # the default config file doesn't exist, try hardcoded config + logger.warn('Default configuration file does not exist, switching to hardcoded fallback configuration!') + config.set_config({'dev_mode': True, 'log': {'file': {'output': True, 'path': dataDir + 'output.log'}, 'console': {'output': True, 'color': True}}}) + if not data_exists: + config.save() + config.reload() # this will read the configuration file into memory + + settings = 0b000 + if config.get('log.console.color', True): + settings = settings | logger.USE_ANSI + if config.get('log.console.output', True): + settings = settings | logger.OUTPUT_TO_CONSOLE + if config.get('log.file.output', True): + settings = settings | logger.OUTPUT_TO_FILE + logger.set_settings(settings) + + if not o_inst is None: + if str(config.get('general.dev_mode', True)).lower() == 'true': + o_inst._developmentMode = True + logger.set_level(logger.LEVEL_DEBUG) + else: + o_inst._developmentMode = False + logger.set_level(logger.LEVEL_INFO) + + verbosity = str(config.get('log.verbosity', 'default')).lower().strip() + if not verbosity in ['default', 'null', 'none', 'nil']: + map = { + str(logger.LEVEL_DEBUG) : logger.LEVEL_DEBUG, + 'verbose' : logger.LEVEL_DEBUG, + 'debug' : logger.LEVEL_DEBUG, + str(logger.LEVEL_INFO) : logger.LEVEL_INFO, + 'info' : logger.LEVEL_INFO, + 'information' : logger.LEVEL_INFO, + str(logger.LEVEL_WARN) : logger.LEVEL_WARN, + 'warn' : logger.LEVEL_WARN, + 'warning' : logger.LEVEL_WARN, + 'warnings' : logger.LEVEL_WARN, + str(logger.LEVEL_ERROR) : logger.LEVEL_ERROR, + 'err' : logger.LEVEL_ERROR, + 'error' : logger.LEVEL_ERROR, + 'errors' : logger.LEVEL_ERROR, + str(logger.LEVEL_FATAL) : logger.LEVEL_FATAL, + 'fatal' : logger.LEVEL_FATAL, + str(logger.LEVEL_IMPORTANT) : logger.LEVEL_IMPORTANT, + 'silent' : logger.LEVEL_IMPORTANT, + 'quiet' : logger.LEVEL_IMPORTANT, + 'important' : logger.LEVEL_IMPORTANT + } + + if verbosity in map: + logger.set_level(map[verbosity]) + else: + logger.warn('Verbosity level %s is not valid, using default verbosity.' % verbosity) + + return data_exists \ No newline at end of file diff --git a/requirements.in b/requirements.in new file mode 100755 index 00000000..6b1cb663 --- /dev/null +++ b/requirements.in @@ -0,0 +1,9 @@ +urllib3==1.23 +requests==2.20.0 +PyNaCl==1.2.1 +gevent==1.3.6 +defusedxml==0.5.0 +Flask==1.0.2 +PySocks==1.6.8 +stem==1.6.0 +deadsimplekv==0.0.1 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt old mode 100755 new mode 100644 index 6b1cb663..b2c93d7c --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,196 @@ -urllib3==1.23 -requests==2.20.0 -PyNaCl==1.2.1 -gevent==1.3.6 -defusedxml==0.5.0 -Flask==1.0.2 -PySocks==1.6.8 -stem==1.6.0 -deadsimplekv==0.0.1 \ No newline at end of file +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile --generate-hashes --output-file requirements.txt requirements.in +# +certifi==2018.11.29 \ + --hash=sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7 \ + --hash=sha256:993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033 \ + # via requests +cffi==1.12.2 \ + --hash=sha256:00b97afa72c233495560a0793cdc86c2571721b4271c0667addc83c417f3d90f \ + --hash=sha256:0ba1b0c90f2124459f6966a10c03794082a2f3985cd699d7d63c4a8dae113e11 \ + --hash=sha256:0bffb69da295a4fc3349f2ec7cbe16b8ba057b0a593a92cbe8396e535244ee9d \ + --hash=sha256:21469a2b1082088d11ccd79dd84157ba42d940064abbfa59cf5f024c19cf4891 \ + --hash=sha256:2e4812f7fa984bf1ab253a40f1f4391b604f7fc424a3e21f7de542a7f8f7aedf \ + --hash=sha256:2eac2cdd07b9049dd4e68449b90d3ef1adc7c759463af5beb53a84f1db62e36c \ + --hash=sha256:2f9089979d7456c74d21303c7851f158833d48fb265876923edcb2d0194104ed \ + --hash=sha256:3dd13feff00bddb0bd2d650cdb7338f815c1789a91a6f68fdc00e5c5ed40329b \ + --hash=sha256:4065c32b52f4b142f417af6f33a5024edc1336aa845b9d5a8d86071f6fcaac5a \ + --hash=sha256:51a4ba1256e9003a3acf508e3b4f4661bebd015b8180cc31849da222426ef585 \ + --hash=sha256:59888faac06403767c0cf8cfb3f4a777b2939b1fbd9f729299b5384f097f05ea \ + --hash=sha256:59c87886640574d8b14910840327f5cd15954e26ed0bbd4e7cef95fa5aef218f \ + --hash=sha256:610fc7d6db6c56a244c2701575f6851461753c60f73f2de89c79bbf1cc807f33 \ + --hash=sha256:70aeadeecb281ea901bf4230c6222af0248c41044d6f57401a614ea59d96d145 \ + --hash=sha256:71e1296d5e66c59cd2c0f2d72dc476d42afe02aeddc833d8e05630a0551dad7a \ + --hash=sha256:8fc7a49b440ea752cfdf1d51a586fd08d395ff7a5d555dc69e84b1939f7ddee3 \ + --hash=sha256:9b5c2afd2d6e3771d516045a6cfa11a8da9a60e3d128746a7fe9ab36dfe7221f \ + --hash=sha256:9c759051ebcb244d9d55ee791259ddd158188d15adee3c152502d3b69005e6bd \ + --hash=sha256:b4d1011fec5ec12aa7cc10c05a2f2f12dfa0adfe958e56ae38dc140614035804 \ + --hash=sha256:b4f1d6332339ecc61275bebd1f7b674098a66fea11a00c84d1c58851e618dc0d \ + --hash=sha256:c030cda3dc8e62b814831faa4eb93dd9a46498af8cd1d5c178c2de856972fd92 \ + --hash=sha256:c2e1f2012e56d61390c0e668c20c4fb0ae667c44d6f6a2eeea5d7148dcd3df9f \ + --hash=sha256:c37c77d6562074452120fc6c02ad86ec928f5710fbc435a181d69334b4de1d84 \ + --hash=sha256:c8149780c60f8fd02752d0429246088c6c04e234b895c4a42e1ea9b4de8d27fb \ + --hash=sha256:cbeeef1dc3c4299bd746b774f019de9e4672f7cc666c777cd5b409f0b746dac7 \ + --hash=sha256:e113878a446c6228669144ae8a56e268c91b7f1fafae927adc4879d9849e0ea7 \ + --hash=sha256:e21162bf941b85c0cda08224dade5def9360f53b09f9f259adb85fc7dd0e7b35 \ + --hash=sha256:fb6934ef4744becbda3143d30c6604718871495a5e36c408431bf33d9c146889 \ + # via pynacl +chardet==3.0.4 \ + --hash=sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae \ + --hash=sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691 \ + # via requests +click==7.0 \ + --hash=sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13 \ + --hash=sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7 \ + # via flask +deadsimplekv==0.0.1 \ + --hash=sha256:1bb78e4feb01d975e89e81cac7b0141666a14ebefa06fffc1c2d86c3308e3930 +defusedxml==0.5.0 \ + --hash=sha256:24d7f2f94f7f3cb6061acb215685e5125fbcdc40a857eff9de22518820b0a4f4 \ + --hash=sha256:702a91ade2968a82beb0db1e0766a6a273f33d4616a6ce8cde475d8e09853b20 +flask==1.0.2 \ + --hash=sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48 \ + --hash=sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05 +gevent==1.3.6 \ + --hash=sha256:03d03ea4f33e535b0a99b6be2696fde9c7417022b8ee67fb15b78f47672a0b86 \ + --hash=sha256:13a0e74432ede9efdad5fd9aed73bd30bcfc73ddcbffe719849210f4546db833 \ + --hash=sha256:23d623b41a431e04a9410b046520778517f5304dfbb9bfd3b1bbcc722eeaeea5 \ + --hash=sha256:2f82d8b4d09285ca4aef34ae5c093ccf966da90e7db3bd34764ffb014c8bfa68 \ + --hash=sha256:3223eb697d819d73dedc9a55b3dfa0cc1931e6459df4f0bf83c7c27ca256a3bd \ + --hash=sha256:3c00ade4ae707dd6a17d6d56ebac689dc56719b83389f9aeb6a10b1e01326177 \ + --hash=sha256:652bdd59afb330ad95550bda6864b87876e977aa4e48b9216235d932368e1987 \ + --hash=sha256:7b413c391e8ad6607b7f7540d698a94349abd64e4935184c595f7cdcc69904c6 \ + --hash=sha256:7feaf556fe2dc94340b603a3bfb00fbb526aaafcb8d804960939244ace4a262f \ + --hash=sha256:810ae07c1baee83cb3d54f7dca236803554659dc00ef662ac962e4e4fd3e79bb \ + --hash=sha256:86fa642228b8fc6a8fa268efab20440bb26599d28814e8dcd99af5dc92da10d7 \ + --hash=sha256:a9a0a61f8dc652b3dd5dc8b9f5f9ace5d2f91f5e81f368e9ef180c8eec968234 \ + --hash=sha256:ac3d258521b1056acb922b3aa77031a64888bb8cda1f7f6f370692cf3e224761 \ + --hash=sha256:af7b0d16541dea42f1eceac4a02815ea3ebd8fe1eb6fc714c81ab1842ec259d4 \ + --hash=sha256:bafef5a426473b52648c25d0ff9027aa8806982b57f8bc03abcc5f4669bfe19f \ + --hash=sha256:bc31cdec2e584106c026a4fd24f800cb575ea8ebfcce7974b630b65d61cf36df \ + --hash=sha256:cc42af305cb7bf1766b0084011520a81e56315dcc5b7662c209ef71a00764634 \ + --hash=sha256:e01223b43b2e9d92733ab9953038c7a99b9c3cdb32dc865b9ce94f03a2199f96 \ + --hash=sha256:e57f9d267b45ef9e3eb0e234307faaffa5a79cdb1477afa1befbf04de0cd8cbe \ + --hash=sha256:e9e2942704f7fe75064ef0bc17ba46b097a57ec0e70eca1d790d5a3edb691628 \ + --hash=sha256:f2ca6fc669def8e622b4a10809f6f6a4b6a822a1cc1175b89ad8eb34235aaa2e \ + --hash=sha256:f456a6321f0955e802e305946ce7e7d672a7da313417ea4b4add6809630d3b0e \ + --hash=sha256:ff8e09696a8c9100b1c88066ee44b50fbbea367ae91d830910561c902d1e7f3c +greenlet==0.4.15 \ + --hash=sha256:000546ad01e6389e98626c1367be58efa613fa82a1be98b0c6fc24b563acc6d0 \ + --hash=sha256:0d48200bc50cbf498716712129eef819b1729339e34c3ae71656964dac907c28 \ + --hash=sha256:23d12eacffa9d0f290c0fe0c4e81ba6d5f3a5b7ac3c30a5eaf0126bf4deda5c8 \ + --hash=sha256:37c9ba82bd82eb6a23c2e5acc03055c0e45697253b2393c9a50cef76a3985304 \ + --hash=sha256:51503524dd6f152ab4ad1fbd168fc6c30b5795e8c70be4410a64940b3abb55c0 \ + --hash=sha256:8041e2de00e745c0e05a502d6e6db310db7faa7c979b3a5877123548a4c0b214 \ + --hash=sha256:81fcd96a275209ef117e9ec91f75c731fa18dcfd9ffaa1c0adbdaa3616a86043 \ + --hash=sha256:853da4f9563d982e4121fed8c92eea1a4594a2299037b3034c3c898cb8e933d6 \ + --hash=sha256:8b4572c334593d449113f9dc8d19b93b7b271bdbe90ba7509eb178923327b625 \ + --hash=sha256:9416443e219356e3c31f1f918a91badf2e37acf297e2fa13d24d1cc2380f8fbc \ + --hash=sha256:9854f612e1b59ec66804931df5add3b2d5ef0067748ea29dc60f0efdcda9a638 \ + --hash=sha256:99a26afdb82ea83a265137a398f570402aa1f2b5dfb4ac3300c026931817b163 \ + --hash=sha256:a19bf883b3384957e4a4a13e6bd1ae3d85ae87f4beb5957e35b0be287f12f4e4 \ + --hash=sha256:a9f145660588187ff835c55a7d2ddf6abfc570c2651c276d3d4be8a2766db490 \ + --hash=sha256:ac57fcdcfb0b73bb3203b58a14501abb7e5ff9ea5e2edfa06bb03035f0cff248 \ + --hash=sha256:bcb530089ff24f6458a81ac3fa699e8c00194208a724b644ecc68422e1111939 \ + --hash=sha256:beeabe25c3b704f7d56b573f7d2ff88fc99f0138e43480cecdfcaa3b87fe4f87 \ + --hash=sha256:d634a7ea1fc3380ff96f9e44d8d22f38418c1c381d5fac680b272d7d90883720 \ + --hash=sha256:d97b0661e1aead761f0ded3b769044bb00ed5d33e1ec865e891a8b128bf7c656 \ + # via gevent +idna==2.7 \ + --hash=sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e \ + --hash=sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16 \ + # via requests +itsdangerous==1.1.0 \ + --hash=sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19 \ + --hash=sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749 \ + # via flask +jinja2==2.10 \ + --hash=sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd \ + --hash=sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4 \ + # via flask +markupsafe==1.1.1 \ + --hash=sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473 \ + --hash=sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161 \ + --hash=sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235 \ + --hash=sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5 \ + --hash=sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff \ + --hash=sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b \ + --hash=sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1 \ + --hash=sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e \ + --hash=sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183 \ + --hash=sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66 \ + --hash=sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1 \ + --hash=sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1 \ + --hash=sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e \ + --hash=sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b \ + --hash=sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905 \ + --hash=sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735 \ + --hash=sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d \ + --hash=sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e \ + --hash=sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d \ + --hash=sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c \ + --hash=sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21 \ + --hash=sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2 \ + --hash=sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5 \ + --hash=sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b \ + --hash=sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6 \ + --hash=sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f \ + --hash=sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f \ + --hash=sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7 \ + # via jinja2 +pycparser==2.19 \ + --hash=sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3 \ + # via cffi +pynacl==1.2.1 \ + --hash=sha256:04e30e5bdeeb2d5b34107f28cd2f5bbfdc6c616f3be88fc6f53582ff1669eeca \ + --hash=sha256:0bfa0d94d2be6874e40f896e0a67e290749151e7de767c5aefbad1121cad7512 \ + --hash=sha256:11aa4e141b2456ce5cecc19c130e970793fa3a2c2e6fbb8ad65b28f35aa9e6b6 \ + --hash=sha256:13bdc1fe084ff9ac7653ae5a924cae03bf4bb07c6667c9eb5b6eb3c570220776 \ + --hash=sha256:14339dc233e7a9dda80a3800e64e7ff89d0878ba23360eea24f1af1b13772cac \ + --hash=sha256:1d33e775fab3f383167afb20b9927aaf4961b953d76eeb271a5703a6d756b65b \ + --hash=sha256:2a42b2399d0428619e58dac7734838102d35f6dcdee149e0088823629bf99fbb \ + --hash=sha256:2dce05ac8b3c37b9e2f65eab56c544885607394753e9613fd159d5e2045c2d98 \ + --hash=sha256:63cfccdc6217edcaa48369191ae4dca0c390af3c74f23c619e954973035948cd \ + --hash=sha256:6453b0dae593163ffc6db6f9c9c1597d35c650598e2c39c0590d1757207a1ac2 \ + --hash=sha256:73a5a96fb5fbf2215beee2353a128d382dbca83f5341f0d3c750877a236569ef \ + --hash=sha256:8abb4ef79161a5f58848b30ab6fb98d8c466da21fdd65558ce1d7afc02c70b5f \ + --hash=sha256:8ac1167195b32a8755de06efd5b2d2fe76fc864517dab66aaf65662cc59e1988 \ + --hash=sha256:8f505f42f659012794414fa57c498404e64db78f1d98dfd40e318c569f3c783b \ + --hash=sha256:9c8a06556918ee8e3ab48c65574f318f5a0a4d31437fc135da7ee9d4f9080415 \ + --hash=sha256:a1e25fc5650cf64f01c9e435033e53a4aca9de30eb9929d099f3bb078e18f8f2 \ + --hash=sha256:be71cd5fce04061e1f3d39597f93619c80cdd3558a6c9ba99a546f144a8d8101 \ + --hash=sha256:c5b1a7a680218dee9da0f1b5e24072c46b3c275d35712bc1d505b85bb03441c0 \ + --hash=sha256:cb785db1a9468841a1265c9215c60fe5d7af2fb1b209e3316a152704607fc582 \ + --hash=sha256:cf6877124ae6a0698404e169b3ba534542cfbc43f939d46b927d956daf0a373a \ + --hash=sha256:d0eb5b2795b7ee2cbcfcadacbe95a13afbda048a262bd369da9904fecb568975 \ + --hash=sha256:d3a934e2b9f20abac009d5b6951067cfb5486889cb913192b4d8288b216842f1 \ + --hash=sha256:d795f506bcc9463efb5ebb0f65ed77921dcc9e0a50499dedd89f208445de9ecb \ + --hash=sha256:d8aaf7e5d6b0e0ef7d6dbf7abeb75085713d0100b4eb1a4e4e857de76d77ac45 \ + --hash=sha256:de2aaca8386cf4d70f1796352f2346f48ddb0bed61dc43a3ce773ba12e064031 \ + --hash=sha256:e0d38fa0a75f65f556fb912f2c6790d1fa29b7dd27a1d9cc5591b281321eaaa9 \ + --hash=sha256:eb2acabbd487a46b38540a819ef67e477a674481f84a82a7ba2234b9ba46f752 \ + --hash=sha256:eeee629828d0eb4f6d98ac41e9a3a6461d114d1d0aa111a8931c049359298da0 \ + --hash=sha256:f5836463a3c0cca300295b229b6c7003c415a9d11f8f9288ddbd728e2746524c \ + --hash=sha256:f5ce9e26d25eb0b2d96f3ef0ad70e1d3ae89b5d60255c462252a3e456a48c053 \ + --hash=sha256:fabf73d5d0286f9e078774f3435601d2735c94ce9e514ac4fb945701edead7e4 +pysocks==1.6.8 \ + --hash=sha256:3fe52c55890a248676fd69dc9e3c4e811718b777834bcaab7a8125cf9deac672 +requests==2.20.0 \ + --hash=sha256:99dcfdaaeb17caf6e526f32b6a7b780461512ab3f1d992187801694cba42770c \ + --hash=sha256:a84b8c9ab6239b578f22d1c21d51b696dcfe004032bb80ea832398d6909d7279 +six==1.12.0 \ + --hash=sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c \ + --hash=sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73 \ + # via pynacl +stem==1.6.0 \ + --hash=sha256:d7fe1fb13ed5a94d610b5ad77e9f1b3404db0ca0586ded7a34afd323e3b849ed +urllib3==1.23 \ + --hash=sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf \ + --hash=sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5 +werkzeug==0.14.1 \ + --hash=sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c \ + --hash=sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b \ + # via flask