more refactoring and secured requirements.txt

This commit is contained in:
Kevin Froman 2019-03-08 19:57:44 -06:00
parent 236edac257
commit 1562848999
12 changed files with 513 additions and 241 deletions

View file

@ -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 <plugin>' % (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 <plugin>' % (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 <plugin>' % (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()

View file

@ -18,9 +18,26 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
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)

View file

@ -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
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

View file

@ -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 <filename>' % sys.argv[0], timestamp = False)
logger.error('%s add-file <filename>' % 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 <blockhash>'))
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

View file

@ -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.")

View file

@ -17,7 +17,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
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)
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

View file

@ -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 <plugin>' % (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 <plugin>' % (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 <plugin>' % (sys.argv[0], sys.argv[1]))

View file

@ -17,10 +17,8 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
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

69
onionr/setupconfig.py Normal file
View file

@ -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