Make Onionr more user friendly
This commit mostly just made messages more readable, worked on logger, and fixed a few bugsmaster
parent
22115891f2
commit
bb08162019
|
@ -24,7 +24,7 @@ from gevent.pywsgi import WSGIServer
|
||||||
import sys, random, threading, hmac, hashlib, base64, time, math, os, json
|
import sys, random, threading, hmac, hashlib, base64, time, math, os, json
|
||||||
import core
|
import core
|
||||||
from onionrblockapi import Block
|
from onionrblockapi import Block
|
||||||
import onionrutils, onionrexceptions, onionrcrypto, blockimporter, onionrevents as events, logger, config
|
import onionrutils, onionrexceptions, onionrcrypto, blockimporter, onionrevents as events, logger, config, onionr
|
||||||
|
|
||||||
class API:
|
class API:
|
||||||
'''
|
'''
|
||||||
|
@ -75,14 +75,8 @@ class API:
|
||||||
This also saves the used host (random localhost IP address) to the data folder in host.txt
|
This also saves the used host (random localhost IP address) to the data folder in host.txt
|
||||||
'''
|
'''
|
||||||
|
|
||||||
config.reload()
|
# configure logger and stuff
|
||||||
|
onionr.Onionr.setupConfig('data/', self = self)
|
||||||
if config.get('dev_mode', True):
|
|
||||||
self._developmentMode = True
|
|
||||||
logger.set_level(logger.LEVEL_DEBUG)
|
|
||||||
else:
|
|
||||||
self._developmentMode = False
|
|
||||||
logger.set_level(logger.LEVEL_INFO)
|
|
||||||
|
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
self._privateDelayTime = 3
|
self._privateDelayTime = 3
|
||||||
|
@ -131,14 +125,14 @@ class API:
|
||||||
resp.headers["Content-Security-Policy"] = "default-src 'none'; script-src 'none'; object-src 'none'; style-src data: 'unsafe-inline'; img-src data:; media-src 'none'; frame-src 'none'; font-src 'none'; connect-src 'none'"
|
resp.headers["Content-Security-Policy"] = "default-src 'none'; script-src 'none'; object-src 'none'; style-src data: 'unsafe-inline'; img-src data:; media-src 'none'; frame-src 'none'; font-src 'none'; connect-src 'none'"
|
||||||
resp.headers['X-Frame-Options'] = 'deny'
|
resp.headers['X-Frame-Options'] = 'deny'
|
||||||
resp.headers['X-Content-Type-Options'] = "nosniff"
|
resp.headers['X-Content-Type-Options'] = "nosniff"
|
||||||
resp.headers['api'] = API_VERSION
|
resp.headers['X-API'] = API_VERSION
|
||||||
|
|
||||||
# reset to text/plain to help prevent browser attacks
|
# reset to text/plain to help prevent browser attacks
|
||||||
self.mimeType = 'text/plain'
|
self.mimeType = 'text/plain'
|
||||||
self.overrideCSP = False
|
self.overrideCSP = False
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
@app.route('/www/private/<path:path>')
|
@app.route('/www/private/<path:path>')
|
||||||
def www_private(path):
|
def www_private(path):
|
||||||
startTime = math.floor(time.time())
|
startTime = math.floor(time.time())
|
||||||
|
|
|
@ -21,12 +21,14 @@
|
||||||
'''
|
'''
|
||||||
import sys, os, core, config, json, requests, time, logger, threading, base64, onionr, uuid
|
import sys, os, core, config, json, requests, time, logger, threading, base64, onionr, uuid
|
||||||
import onionrexceptions, onionrpeers, onionrevents as events, onionrplugins as plugins, onionrblockapi as block
|
import onionrexceptions, onionrpeers, onionrevents as events, onionrplugins as plugins, onionrblockapi as block
|
||||||
import onionrdaemontools, onionrsockets, onionrchat
|
import onionrdaemontools, onionrsockets, onionrchat, onionr
|
||||||
from dependencies import secrets
|
from dependencies import secrets
|
||||||
from defusedxml import minidom
|
from defusedxml import minidom
|
||||||
|
|
||||||
class OnionrCommunicatorDaemon:
|
class OnionrCommunicatorDaemon:
|
||||||
def __init__(self, debug, developmentMode):
|
def __init__(self, debug, developmentMode):
|
||||||
|
# configure logger and stuff
|
||||||
|
onionr.Onionr.setupConfig('data/', self = self)
|
||||||
|
|
||||||
self.isOnline = True # Assume we're connected to the internet
|
self.isOnline = True # Assume we're connected to the internet
|
||||||
|
|
||||||
|
@ -303,9 +305,11 @@ class OnionrCommunicatorDaemon:
|
||||||
self.decrementThreadCount('clearOfflinePeer')
|
self.decrementThreadCount('clearOfflinePeer')
|
||||||
|
|
||||||
def getOnlinePeers(self):
|
def getOnlinePeers(self):
|
||||||
'''Manages the self.onlinePeers attribute list, connects to more peers if we have none connected'''
|
'''
|
||||||
|
Manages the self.onlinePeers attribute list, connects to more peers if we have none connected
|
||||||
|
'''
|
||||||
|
|
||||||
logger.info('Refreshing peer pool.')
|
logger.debug('Refreshing peer pool...')
|
||||||
maxPeers = int(config.get('peers.max_connect', 10))
|
maxPeers = int(config.get('peers.max_connect', 10))
|
||||||
needed = maxPeers - len(self.onlinePeers)
|
needed = maxPeers - len(self.onlinePeers)
|
||||||
|
|
||||||
|
@ -318,11 +322,13 @@ class OnionrCommunicatorDaemon:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
if len(self.onlinePeers) == 0:
|
if len(self.onlinePeers) == 0:
|
||||||
logger.warn('Could not connect to any peer.')
|
logger.debug('Couldn\'t connect to any peers.')
|
||||||
self.decrementThreadCount('getOnlinePeers')
|
self.decrementThreadCount('getOnlinePeers')
|
||||||
|
|
||||||
def addBootstrapListToPeerList(self, peerList):
|
def addBootstrapListToPeerList(self, peerList):
|
||||||
'''Add the bootstrap list to the peer list (no duplicates)'''
|
'''
|
||||||
|
Add the bootstrap list to the peer list (no duplicates)
|
||||||
|
'''
|
||||||
for i in self._core.bootstrapList:
|
for i in self._core.bootstrapList:
|
||||||
if i not in peerList and i not in self.offlinePeers and i != self._core.hsAddress and len(str(i).strip()) > 0:
|
if i not in peerList and i not in self.offlinePeers and i != self._core.hsAddress and len(str(i).strip()) > 0:
|
||||||
peerList.append(i)
|
peerList.append(i)
|
||||||
|
@ -440,11 +446,13 @@ class OnionrCommunicatorDaemon:
|
||||||
def heartbeat(self):
|
def heartbeat(self):
|
||||||
'''Show a heartbeat debug message'''
|
'''Show a heartbeat debug message'''
|
||||||
currentTime = self._core._utils.getEpoch() - self.startTime
|
currentTime = self._core._utils.getEpoch() - self.startTime
|
||||||
logger.debug('heartbeat, running seconds: ' + str(currentTime))
|
logger.debug('Heartbeat. Node online for %s.' % self.daemonTools.humanReadableTime(currentTime))
|
||||||
self.decrementThreadCount('heartbeat')
|
self.decrementThreadCount('heartbeat')
|
||||||
|
|
||||||
def daemonCommands(self):
|
def daemonCommands(self):
|
||||||
'''process daemon commands from daemonQueue'''
|
'''
|
||||||
|
Process daemon commands from daemonQueue
|
||||||
|
'''
|
||||||
cmd = self._core.daemonQueue()
|
cmd = self._core.daemonQueue()
|
||||||
|
|
||||||
if cmd is not False:
|
if cmd is not False:
|
||||||
|
|
|
@ -73,6 +73,7 @@ LEVEL_INFO = 2
|
||||||
LEVEL_WARN = 3
|
LEVEL_WARN = 3
|
||||||
LEVEL_ERROR = 4
|
LEVEL_ERROR = 4
|
||||||
LEVEL_FATAL = 5
|
LEVEL_FATAL = 5
|
||||||
|
LEVEL_IMPORTANT = 6
|
||||||
|
|
||||||
_type = OUTPUT_TO_CONSOLE | USE_ANSI # the default settings for logging
|
_type = OUTPUT_TO_CONSOLE | USE_ANSI # the default settings for logging
|
||||||
_level = LEVEL_DEBUG # the lowest level to log
|
_level = LEVEL_DEBUG # the lowest level to log
|
||||||
|
@ -201,36 +202,36 @@ def confirm(default = 'y', message = 'Are you sure %s? '):
|
||||||
return default == 'y'
|
return default == 'y'
|
||||||
|
|
||||||
# debug: when there is info that could be useful for debugging purposes only
|
# debug: when there is info that could be useful for debugging purposes only
|
||||||
def debug(data, error = None, timestamp = True, prompt = True, sensitive = False):
|
def debug(data, error = None, timestamp = True, prompt = True, sensitive = False, level = LEVEL_DEBUG):
|
||||||
if get_level() <= LEVEL_DEBUG:
|
if get_level() <= level:
|
||||||
log('/', data, timestamp=timestamp, prompt = prompt, sensitive = sensitive)
|
log('/', data, timestamp = timestamp, prompt = prompt, sensitive = sensitive)
|
||||||
if not error is None:
|
if not error is None:
|
||||||
debug('Error: ' + str(error) + parse_error())
|
debug('Error: ' + str(error) + parse_error())
|
||||||
|
|
||||||
# info: when there is something to notify the user of, such as the success of a process
|
# info: when there is something to notify the user of, such as the success of a process
|
||||||
def info(data, timestamp = False, prompt = True, sensitive = False):
|
def info(data, timestamp = False, prompt = True, sensitive = False, level = LEVEL_INFO):
|
||||||
if get_level() <= LEVEL_INFO:
|
if get_level() <= level:
|
||||||
log('+', data, colors.fg.green, timestamp = timestamp, prompt = prompt, sensitive = sensitive)
|
log('+', data, colors.fg.green, timestamp = timestamp, prompt = prompt, sensitive = sensitive)
|
||||||
|
|
||||||
# warn: when there is a potential for something bad to happen
|
# warn: when there is a potential for something bad to happen
|
||||||
def warn(data, error = None, timestamp = True, prompt = True, sensitive = False):
|
def warn(data, error = None, timestamp = True, prompt = True, sensitive = False, level = LEVEL_WARN):
|
||||||
if not error is None:
|
if not error is None:
|
||||||
debug('Error: ' + str(error) + parse_error())
|
debug('Error: ' + str(error) + parse_error())
|
||||||
if get_level() <= LEVEL_WARN:
|
if get_level() <= level:
|
||||||
log('!', data, colors.fg.orange, timestamp = timestamp, prompt = prompt, sensitive = sensitive)
|
log('!', data, colors.fg.orange, timestamp = timestamp, prompt = prompt, sensitive = sensitive)
|
||||||
|
|
||||||
# error: when only one function, module, or process of the program encountered a problem and must stop
|
# error: when only one function, module, or process of the program encountered a problem and must stop
|
||||||
def error(data, error = None, timestamp = True, prompt = True, sensitive = False):
|
def error(data, error = None, timestamp = True, prompt = True, sensitive = False, level = LEVEL_ERROR):
|
||||||
if get_level() <= LEVEL_ERROR:
|
if get_level() <= level:
|
||||||
log('-', data, colors.fg.red, timestamp = timestamp, fd = sys.stderr, prompt = prompt, sensitive = sensitive)
|
log('-', data, colors.fg.red, timestamp = timestamp, fd = sys.stderr, prompt = prompt, sensitive = sensitive)
|
||||||
if not error is None:
|
if not error is None:
|
||||||
debug('Error: ' + str(error) + parse_error())
|
debug('Error: ' + str(error) + parse_error())
|
||||||
|
|
||||||
# fatal: when the something so bad has happened that the program must stop
|
# fatal: when the something so bad has happened that the program must stop
|
||||||
def fatal(data, error = None, timestamp=True, prompt = True, sensitive = False):
|
def fatal(data, error = None, timestamp=True, prompt = True, sensitive = False, level = LEVEL_FATAL):
|
||||||
if not error is None:
|
if not error is None:
|
||||||
debug('Error: ' + str(error) + parse_error(), sensitive = sensitive)
|
debug('Error: ' + str(error) + parse_error(), sensitive = sensitive)
|
||||||
if get_level() <= LEVEL_FATAL:
|
if get_level() <= level:
|
||||||
log('#', data, colors.bg.red + colors.fg.green + colors.bold, timestamp = timestamp, fd = sys.stderr, prompt = prompt, sensitive = sensitive)
|
log('#', data, colors.bg.red + colors.fg.green + colors.bold, timestamp = timestamp, fd = sys.stderr, prompt = prompt, sensitive = sensitive)
|
||||||
|
|
||||||
# returns a formatted error message
|
# returns a formatted error message
|
||||||
|
|
|
@ -141,7 +141,7 @@ HashedControlPassword ''' + str(password) + '''
|
||||||
logger.fatal('Failed to start Tor. Maybe a stray instance of Tor used by Onionr is still running?')
|
logger.fatal('Failed to start Tor. Maybe a stray instance of Tor used by Onionr is still running?')
|
||||||
return False
|
return False
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
logger.fatal("Got keyboard interrupt.")
|
logger.fatal('Got keyboard interrupt.', timestamp = false, level = logger.LEVEL_IMPORTANT)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
logger.debug('Finished starting Tor.', timestamp=True)
|
logger.debug('Finished starting Tor.', timestamp=True)
|
||||||
|
|
151
onionr/onionr.py
151
onionr/onionr.py
|
@ -65,36 +65,7 @@ class Onionr:
|
||||||
|
|
||||||
# Load global configuration data
|
# Load global configuration data
|
||||||
|
|
||||||
data_exists = os.path.exists(self.dataDir)
|
data_exists = Onionr.setupConfig(self.dataDir, self = self)
|
||||||
|
|
||||||
if not data_exists:
|
|
||||||
os.mkdir(self.dataDir)
|
|
||||||
|
|
||||||
if os.path.exists('static-data/default_config.json'):
|
|
||||||
config.set_config(json.loads(open('static-data/default_config.json').read())) # this is the default config, it will be overwritten if a config file already exists. Else, it saves it
|
|
||||||
else:
|
|
||||||
# the default config file doesn't exist, try hardcoded config
|
|
||||||
config.set_config({'dev_mode': True, 'log': {'file': {'output': True, 'path': self.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_file(config.get('log.file.path', '/tmp/onionr.log').replace('data/', self.dataDir))
|
|
||||||
logger.set_settings(settings)
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
self.onionrCore = core.Core()
|
self.onionrCore = core.Core()
|
||||||
self.onionrUtils = onionrutils.OnionrUtils(self.onionrCore)
|
self.onionrUtils = onionrutils.OnionrUtils(self.onionrCore)
|
||||||
|
@ -222,14 +193,18 @@ class Onionr:
|
||||||
'help': 'Displays this Onionr help menu',
|
'help': 'Displays this Onionr help menu',
|
||||||
'version': 'Displays the Onionr version',
|
'version': 'Displays the Onionr version',
|
||||||
'config': 'Configures something and adds it to the file',
|
'config': 'Configures something and adds it to the file',
|
||||||
|
|
||||||
'start': 'Starts the Onionr daemon',
|
'start': 'Starts the Onionr daemon',
|
||||||
'stop': 'Stops the Onionr daemon',
|
'stop': 'Stops the Onionr daemon',
|
||||||
|
|
||||||
'stats': 'Displays node statistics',
|
'stats': 'Displays node statistics',
|
||||||
'get-password': 'Displays the web password',
|
'details': 'Displays the web password, public key, and human readable public key',
|
||||||
|
|
||||||
'enable-plugin': 'Enables and starts a plugin',
|
'enable-plugin': 'Enables and starts a plugin',
|
||||||
'disable-plugin': 'Disables and stops a plugin',
|
'disable-plugin': 'Disables and stops a plugin',
|
||||||
'reload-plugin': 'Reloads a plugin',
|
'reload-plugin': 'Reloads a plugin',
|
||||||
'create-plugin': 'Creates directory structure for a plugin',
|
'create-plugin': 'Creates directory structure for a plugin',
|
||||||
|
|
||||||
'add-peer': 'Adds a peer to database',
|
'add-peer': 'Adds a peer to database',
|
||||||
'list-peers': 'Displays a list of peers',
|
'list-peers': 'Displays a list of peers',
|
||||||
'add-file': 'Create an Onionr block from a file',
|
'add-file': 'Create an Onionr block from a file',
|
||||||
|
@ -357,7 +332,7 @@ class Onionr:
|
||||||
return config.get('client.hmac')
|
return config.get('client.hmac')
|
||||||
|
|
||||||
def printWebPassword(self):
|
def printWebPassword(self):
|
||||||
print(self.getWebPassword())
|
logger.info(self.getWebPassword(), sensitive = True)
|
||||||
|
|
||||||
def getHelp(self):
|
def getHelp(self):
|
||||||
return self.cmdhelp
|
return self.cmdhelp
|
||||||
|
@ -410,16 +385,16 @@ class Onionr:
|
||||||
THIS SECTION DEFINES THE COMMANDS
|
THIS SECTION DEFINES THE COMMANDS
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def version(self, verbosity=5):
|
def version(self, verbosity = 5, function = logger.info):
|
||||||
'''
|
'''
|
||||||
Displays the Onionr version
|
Displays the Onionr version
|
||||||
'''
|
'''
|
||||||
|
|
||||||
logger.info('Onionr %s (%s) - API v%s' % (ONIONR_VERSION, platform.machine(), API_VERSION))
|
function('Onionr v%s (%s) (API v%s)' % (ONIONR_VERSION, platform.machine(), API_VERSION))
|
||||||
if verbosity >= 1:
|
if verbosity >= 1:
|
||||||
logger.info(ONIONR_TAGLINE)
|
function(ONIONR_TAGLINE)
|
||||||
if verbosity >= 2:
|
if verbosity >= 2:
|
||||||
logger.info('Running on %s %s' % (platform.platform(), platform.release()))
|
function('Running on %s %s' % (platform.platform(), platform.release()))
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -635,35 +610,47 @@ class Onionr:
|
||||||
logger.debug('Runcheck file found on daemon start, deleting in advance.')
|
logger.debug('Runcheck file found on daemon start, deleting in advance.')
|
||||||
os.remove('data/.runcheck')
|
os.remove('data/.runcheck')
|
||||||
|
|
||||||
apiThread = Thread(target=api.API, args=(self.debug,API_VERSION))
|
apiThread = Thread(target = api.API, args = (self.debug, API_VERSION))
|
||||||
apiThread.start()
|
apiThread.start()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
logger.info('Got keyboard interrupt')
|
logger.debug('Got keyboard interrupt, shutting down...')
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
self.onionrUtils.localCommand('shutdown')
|
self.onionrUtils.localCommand('shutdown')
|
||||||
else:
|
else:
|
||||||
if apiThread.isAlive():
|
if apiThread.isAlive():
|
||||||
|
# configure logger and stuff
|
||||||
|
Onionr.setupConfig('data/', self = self)
|
||||||
|
|
||||||
if self._developmentMode:
|
if self._developmentMode:
|
||||||
logger.warn('DEVELOPMENT MODE ENABLED (THIS IS LESS SECURE!)', timestamp = False)
|
logger.warn('DEVELOPMENT MODE ENABLED (THIS IS LESS SECURE!)', timestamp = False)
|
||||||
net = NetController(config.get('client.port', 59496))
|
net = NetController(config.get('client.port', 59496))
|
||||||
logger.info('Tor is starting...')
|
logger.debug('Tor is starting...')
|
||||||
if not net.startTor():
|
if not net.startTor():
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
logger.info('Started .onion service: ' + logger.colors.underline + net.myID)
|
logger.debug('Started .onion service: %s' % (logger.colors.underline + net.myID))
|
||||||
logger.info('Our Public key: ' + self.onionrCore._crypto.pubKey)
|
logger.debug('Using public key: %s' % (logger.colors.underline + self.onionrCore._crypto.pubKey))
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
#TODO make runable on windows
|
# TODO: make runable on windows
|
||||||
communicatorProc = subprocess.Popen([communicatorDaemon, "run", str(net.socksPort)])
|
communicatorProc = subprocess.Popen([communicatorDaemon, 'run', str(net.socksPort)])
|
||||||
# Print nice header thing :)
|
|
||||||
|
# print nice header thing :)
|
||||||
if config.get('general.display_header', True):
|
if config.get('general.display_header', True):
|
||||||
self.header()
|
self.header()
|
||||||
logger.debug('Started communicator')
|
|
||||||
|
# print out debug info
|
||||||
|
self.version(verbosity = 5, function = logger.debug)
|
||||||
|
logger.debug('Python version %s' % platform.python_version())
|
||||||
|
|
||||||
|
logger.debug('Started communicator.')
|
||||||
|
|
||||||
events.event('daemon_start', onionr = self)
|
events.event('daemon_start', onionr = self)
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
|
|
||||||
# Break if communicator process ends, so we don't have left over processes
|
# Break if communicator process ends, so we don't have left over processes
|
||||||
if communicatorProc.poll() is not None:
|
if communicatorProc.poll() is not None:
|
||||||
break
|
break
|
||||||
|
@ -810,7 +797,7 @@ class Onionr:
|
||||||
except IndexError:
|
except IndexError:
|
||||||
logger.error("Syntax %s %s" % (sys.argv[0], '/path/to/filename <blockhash>'))
|
logger.error("Syntax %s %s" % (sys.argv[0], '/path/to/filename <blockhash>'))
|
||||||
else:
|
else:
|
||||||
print(fileName)
|
logger.info(fileName)
|
||||||
contents = None
|
contents = None
|
||||||
if os.path.exists(fileName):
|
if os.path.exists(fileName):
|
||||||
logger.error("File already exists")
|
logger.error("File already exists")
|
||||||
|
@ -842,17 +829,83 @@ class Onionr:
|
||||||
else:
|
else:
|
||||||
logger.error('%s add-file <filename>' % sys.argv[0], timestamp = False)
|
logger.error('%s add-file <filename>' % sys.argv[0], timestamp = False)
|
||||||
|
|
||||||
|
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'):
|
||||||
|
config.set_config(json.loads(open('static-data/default_config.json').read())) # this is the default config, it will be overwritten if a config file already exists. Else, it saves it
|
||||||
|
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_file(config.get('log.file.path', '/tmp/onionr.log').replace('data/', dataDir))
|
||||||
|
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 openUI(self):
|
def openUI(self):
|
||||||
url = 'http://127.0.0.1:%s/ui/index.html?timingToken=%s' % (config.get('client.port', 59496), self.onionrUtils.getTimeBypassToken())
|
url = 'http://127.0.0.1:%s/ui/index.html?timingToken=%s' % (config.get('client.port', 59496), self.onionrUtils.getTimeBypassToken())
|
||||||
|
|
||||||
print('Opening %s ...' % url)
|
logger.info('Opening %s ...' % url)
|
||||||
webbrowser.open(url, new = 1, autoraise = True)
|
webbrowser.open(url, new = 1, autoraise = True)
|
||||||
|
|
||||||
def header(self, message = logger.colors.fg.pink + logger.colors.bold + 'Onionr' + logger.colors.reset + logger.colors.fg.pink + ' has started.'):
|
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'):
|
if os.path.exists('static-data/header.txt') and logger.get_level() <= logger.LEVEL_INFO:
|
||||||
with open('static-data/header.txt', 'rb') as file:
|
with open('static-data/header.txt', 'rb') as file:
|
||||||
# only to stdout, not file or log or anything
|
# 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('V', ONIONR_VERSION))
|
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')
|
logger.info(logger.colors.fg.lightgreen + '-> ' + str(message) + logger.colors.reset + logger.colors.fg.lightgreen + ' <-\n')
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -46,4 +46,4 @@ class OnionrChat:
|
||||||
self.communicator.socketClient.sendData(peer, "lol")
|
self.communicator.socketClient.sendData(peer, "lol")
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
|
@ -140,3 +140,23 @@ class DaemonTools:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def humanReadableTime(self, seconds):
|
||||||
|
build = ''
|
||||||
|
|
||||||
|
units = {
|
||||||
|
'year' : 31557600,
|
||||||
|
'month' : (31557600 / 12),
|
||||||
|
'day' : 86400,
|
||||||
|
'hour' : 3600,
|
||||||
|
'minute' : 60,
|
||||||
|
'second' : 1
|
||||||
|
}
|
||||||
|
|
||||||
|
for unit in units:
|
||||||
|
amnt_unit = int(seconds / units[unit])
|
||||||
|
if amnt_unit >= 1:
|
||||||
|
seconds -= amnt_unit * units[unit]
|
||||||
|
build += '%s %s' % (amnt_unit, unit) + ('s' if amnt_unit != 1 else '') + ' '
|
||||||
|
|
||||||
|
return build.strip()
|
||||||
|
|
|
@ -77,7 +77,7 @@ def enable(name, onionr = None, start_event = True):
|
||||||
else:
|
else:
|
||||||
enabled_plugins.append(name)
|
enabled_plugins.append(name)
|
||||||
config.set('plugins.enabled', enabled_plugins, True)
|
config.set('plugins.enabled', enabled_plugins, True)
|
||||||
|
|
||||||
if start_event is True:
|
if start_event is True:
|
||||||
start(name)
|
start(name)
|
||||||
return True
|
return True
|
||||||
|
@ -234,7 +234,7 @@ def check():
|
||||||
config.reload()
|
config.reload()
|
||||||
|
|
||||||
if not config.is_set('plugins'):
|
if not config.is_set('plugins'):
|
||||||
logger.debug('Generating plugin config data...')
|
logger.debug('Generating plugin configuration data...')
|
||||||
config.set('plugins', {'enabled': []}, True)
|
config.set('plugins', {'enabled': []}, True)
|
||||||
|
|
||||||
if not os.path.exists(os.path.dirname(get_plugins_folder())):
|
if not os.path.exists(os.path.dirname(get_plugins_folder())):
|
||||||
|
|
|
@ -72,7 +72,7 @@ class OnionrSocketServer:
|
||||||
self._core.socketServerResponseData[myPeer] = ''
|
self._core.socketServerResponseData[myPeer] = ''
|
||||||
|
|
||||||
return retData
|
return retData
|
||||||
|
|
||||||
def socketStarter(self):
|
def socketStarter(self):
|
||||||
while not self._core.killSockets:
|
while not self._core.killSockets:
|
||||||
try:
|
try:
|
||||||
|
@ -87,14 +87,14 @@ class OnionrSocketServer:
|
||||||
def detectShutdown(self):
|
def detectShutdown(self):
|
||||||
while not self._core.killSockets:
|
while not self._core.killSockets:
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
logger.info('Killing socket server')
|
logger.debug('Killing socket server...')
|
||||||
self.http_server.stop()
|
self.http_server.stop()
|
||||||
|
|
||||||
def addSocket(self, peer, reason=''):
|
def addSocket(self, peer, reason=''):
|
||||||
bindPort = 1337
|
bindPort = 1337
|
||||||
|
|
||||||
assert len(reason) <= 12
|
assert len(reason) <= 12
|
||||||
|
|
||||||
with stem.control.Controller.from_port(port=config.get('tor.controlPort')) as controller:
|
with stem.control.Controller.from_port(port=config.get('tor.controlPort')) as controller:
|
||||||
controller.authenticate(config.get('tor.controlpassword'))
|
controller.authenticate(config.get('tor.controlpassword'))
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ class OnionrSocketServer:
|
||||||
self._core.insertBlock(str(uuid.uuid4()), header='socket', sign=True, encryptType='asym', asymPeer=peer, meta={'reason': reason, 'address': socket.service_id + '.onion'})
|
self._core.insertBlock(str(uuid.uuid4()), header='socket', sign=True, encryptType='asym', asymPeer=peer, meta={'reason': reason, 'address': socket.service_id + '.onion'})
|
||||||
self._core.socketReasons[peer] = reason
|
self._core.socketReasons[peer] = reason
|
||||||
return
|
return
|
||||||
|
|
||||||
class OnionrSocketClient:
|
class OnionrSocketClient:
|
||||||
def __init__(self, coreInst):
|
def __init__(self, coreInst):
|
||||||
self.sockets = {} # pubkey: tor address
|
self.sockets = {} # pubkey: tor address
|
||||||
|
@ -158,7 +158,7 @@ class OnionrSocketClient:
|
||||||
postData = {'data': data}
|
postData = {'data': data}
|
||||||
self.connPool[peer] = {'date': self._core._utils.getEpoch(), 'data': self._core._utils.doPostRequest('http://' + address + '/dc/', data=postData)}
|
self.connPool[peer] = {'date': self._core._utils.getEpoch(), 'data': self._core._utils.doPostRequest('http://' + address + '/dc/', data=postData)}
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
def getResponse(self, peer):
|
def getResponse(self, peer):
|
||||||
retData = ''
|
retData = ''
|
||||||
try:
|
try:
|
||||||
|
@ -166,6 +166,6 @@ class OnionrSocketClient:
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
return
|
return
|
||||||
|
|
||||||
def sendData(self, peer, data):
|
def sendData(self, peer, data):
|
||||||
self.sendData[peer] = data
|
self.sendData[peer] = data
|
||||||
|
|
|
@ -527,7 +527,7 @@ class OnionrUtils:
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
time.sleep(interval)
|
time.sleep(interval)
|
||||||
|
|
||||||
if not os.path.isfile(runcheck_file):
|
if not os.path.isfile(runcheck_file):
|
||||||
return True
|
return True
|
||||||
elif time.time() - starttime >= timeout:
|
elif time.time() - starttime >= timeout:
|
||||||
|
@ -622,12 +622,14 @@ class OnionrUtils:
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
headers = {'user-agent': 'PyOnionr'}
|
headers = {'user-agent': 'PyOnionr'}
|
||||||
|
response_headers = dict()
|
||||||
try:
|
try:
|
||||||
proxies = {'http': 'socks4a://127.0.0.1:' + str(port), 'https': 'socks4a://127.0.0.1:' + str(port)}
|
proxies = {'http': 'socks4a://127.0.0.1:' + str(port), 'https': 'socks4a://127.0.0.1:' + str(port)}
|
||||||
r = requests.get(url, headers=headers, proxies=proxies, allow_redirects=False, timeout=(15, 30))
|
r = requests.get(url, headers=headers, proxies=proxies, allow_redirects=False, timeout=(15, 30))
|
||||||
# Check server is using same API version as us
|
# Check server is using same API version as us
|
||||||
try:
|
try:
|
||||||
if r.headers['api'] != str(API_VERSION):
|
response_headers = r.headers
|
||||||
|
if r.headers['X-API'] != str(API_VERSION):
|
||||||
raise onionrexceptions.InvalidAPIVersion
|
raise onionrexceptions.InvalidAPIVersion
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise onionrexceptions.InvalidAPIVersion
|
raise onionrexceptions.InvalidAPIVersion
|
||||||
|
@ -635,9 +637,12 @@ class OnionrUtils:
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
raise KeyboardInterrupt
|
raise KeyboardInterrupt
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logger.debug('Failed to make request', error = e)
|
logger.debug('Failed to make GET request to %s' % url, error = e, sensitive = True)
|
||||||
except onionrexceptions.InvalidAPIVersion:
|
except onionrexceptions.InvalidAPIVersion:
|
||||||
logger.debug("Node is using different API version :(")
|
if 'X-API' in response_headers:
|
||||||
|
logger.debug('Using API version %s. Cannot communicate with node\'s API version of %s.' % (API_VERSION, response_headers['X-API']))
|
||||||
|
else:
|
||||||
|
logger.debug('Using API version %s. API version was not sent with the request.' % API_VERSION)
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
if not 'ConnectTimeoutError' in str(e) and not 'Request rejected or failed' in str(e):
|
if not 'ConnectTimeoutError' in str(e) and not 'Request rejected or failed' in str(e):
|
||||||
logger.debug('Error: %s' % str(e))
|
logger.debug('Error: %s' % str(e))
|
||||||
|
@ -656,12 +661,12 @@ class OnionrUtils:
|
||||||
retData = ''
|
retData = ''
|
||||||
curTime = self.getRoundedEpoch(rounding)
|
curTime = self.getRoundedEpoch(rounding)
|
||||||
self.nistSaltTimestamp = curTime
|
self.nistSaltTimestamp = curTime
|
||||||
data = self.doGetRequest('https://beacon.nist.gov/rest/record/' + str(curTime), port=torPort)
|
data = self.doGetRequest('https://beacon.nist.gov/rest/record/' + str(curTime), port = torPort)
|
||||||
dataXML = minidom.parseString(data, forbid_dtd=True, forbid_entities=True, forbid_external=True)
|
dataXML = minidom.parseString(data, forbid_dtd = True, forbid_entities = True, forbid_external = True)
|
||||||
try:
|
try:
|
||||||
retData = dataXML.getElementsByTagName('outputValue')[0].childNodes[0].data
|
retData = dataXML.getElementsByTagName('outputValue')[0].childNodes[0].data
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logger.warn('Could not get NIST beacon value')
|
logger.warn('Failed to get the NIST beacon value.')
|
||||||
else:
|
else:
|
||||||
self.powSalt = retData
|
self.powSalt = retData
|
||||||
return retData
|
return retData
|
||||||
|
|
|
@ -38,13 +38,12 @@ class OnionrCLIUI:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
for i in range(100):
|
print('\n' * 80 + logger.colors.reset)
|
||||||
print('')
|
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
'''Main CLI UI interface menu'''
|
'''Main CLI UI interface menu'''
|
||||||
showMenu = True
|
showMenu = True
|
||||||
isOnline = "No"
|
isOnline = 'No'
|
||||||
firstRun = True
|
firstRun = True
|
||||||
choice = ''
|
choice = ''
|
||||||
|
|
||||||
|
@ -53,7 +52,7 @@ class OnionrCLIUI:
|
||||||
|
|
||||||
while showMenu:
|
while showMenu:
|
||||||
if firstRun:
|
if firstRun:
|
||||||
logger.info("please wait while Onionr starts...")
|
logger.info('Please wait while Onionr starts...'')
|
||||||
daemon = subprocess.Popen(["./onionr.py", "start"], stdin=subprocess.PIPE, stdout=subprocess.DEVNULL)
|
daemon = subprocess.Popen(["./onionr.py", "start"], stdin=subprocess.PIPE, stdout=subprocess.DEVNULL)
|
||||||
time.sleep(30)
|
time.sleep(30)
|
||||||
firstRun = False
|
firstRun = False
|
||||||
|
@ -63,9 +62,8 @@ class OnionrCLIUI:
|
||||||
else:
|
else:
|
||||||
isOnline = "No"
|
isOnline = "No"
|
||||||
|
|
||||||
print('''
|
logger.info('''Daemon Running: ''' + isOnline + '''
|
||||||
Daemon Running: ''' + isOnline + '''
|
|
||||||
|
|
||||||
1. Flow (Anonymous public chat, use at your own risk)
|
1. Flow (Anonymous public chat, use at your own risk)
|
||||||
2. Mail (Secure email-like service)
|
2. Mail (Secure email-like service)
|
||||||
3. File Sharing
|
3. File Sharing
|
||||||
|
@ -83,7 +81,7 @@ Daemon Running: ''' + isOnline + '''
|
||||||
elif choice in ("2", "mail"):
|
elif choice in ("2", "mail"):
|
||||||
self.subCommand("mail")
|
self.subCommand("mail")
|
||||||
elif choice in ("3", "file sharing", "file"):
|
elif choice in ("3", "file sharing", "file"):
|
||||||
print("Not supported yet")
|
logger.warn("Not supported yet")
|
||||||
elif choice in ("4", "user settings", "settings"):
|
elif choice in ("4", "user settings", "settings"):
|
||||||
try:
|
try:
|
||||||
self.setName()
|
self.setName()
|
||||||
|
@ -91,21 +89,21 @@ Daemon Running: ''' + isOnline + '''
|
||||||
pass
|
pass
|
||||||
elif choice in ("5", "daemon"):
|
elif choice in ("5", "daemon"):
|
||||||
if isOnline == "Yes":
|
if isOnline == "Yes":
|
||||||
print("Onionr daemon will shutdown...")
|
logger.info("Onionr daemon will shutdown...")
|
||||||
self.myCore.daemonQueueAdd('shutdown')
|
self.myCore.daemonQueueAdd('shutdown')
|
||||||
try:
|
try:
|
||||||
daemon.kill()
|
daemon.kill()
|
||||||
except UnboundLocalError:
|
except UnboundLocalError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
print("Starting Daemon...")
|
logger.info("Starting Daemon...")
|
||||||
daemon = subprocess.Popen(["./onionr.py", "start"], stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
daemon = subprocess.Popen(["./onionr.py", "start"], stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
||||||
elif choice in ("6", "quit"):
|
elif choice in ("6", "quit"):
|
||||||
showMenu = False
|
showMenu = False
|
||||||
elif choice == "":
|
elif choice == "":
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
print("Invalid choice")
|
logger.error("Invalid choice")
|
||||||
return
|
return
|
||||||
|
|
||||||
def setName(self):
|
def setName(self):
|
||||||
|
|
|
@ -71,7 +71,7 @@ class PlainEncryption:
|
||||||
plaintext = data
|
plaintext = data
|
||||||
encrypted = self.api.get_core()._crypto.pubKeyEncrypt(plaintext, pubkey, anonymous=True, encodedData=True)
|
encrypted = self.api.get_core()._crypto.pubKeyEncrypt(plaintext, pubkey, anonymous=True, encodedData=True)
|
||||||
encrypted = self.api.get_core()._utils.bytesToStr(encrypted)
|
encrypted = self.api.get_core()._utils.bytesToStr(encrypted)
|
||||||
print('ONIONR ENCRYPTED DATA %s END ENCRYPTED DATA' % (encrypted,))
|
logger.info('Encrypted Message: \n\nONIONR ENCRYPTED DATA %s END ENCRYPTED DATA' % (encrypted,))
|
||||||
def decrypt(self):
|
def decrypt(self):
|
||||||
plaintext = ""
|
plaintext = ""
|
||||||
data = ""
|
data = ""
|
||||||
|
@ -89,10 +89,10 @@ class PlainEncryption:
|
||||||
myPub = self.api.get_core()._crypto.pubKey
|
myPub = self.api.get_core()._crypto.pubKey
|
||||||
decrypted = self.api.get_core()._crypto.pubKeyDecrypt(encrypted, privkey=self.api.get_core()._crypto.privKey, anonymous=True, encodedData=True)
|
decrypted = self.api.get_core()._crypto.pubKeyDecrypt(encrypted, privkey=self.api.get_core()._crypto.privKey, anonymous=True, encodedData=True)
|
||||||
if decrypted == False:
|
if decrypted == False:
|
||||||
print("Decryption failed")
|
logger.error("Decryption failed")
|
||||||
else:
|
else:
|
||||||
data = json.loads(decrypted)
|
data = json.loads(decrypted)
|
||||||
print(data['data'])
|
logger.info('Decrypted Message: \n\n%s' % data['data'])
|
||||||
try:
|
try:
|
||||||
logger.info("Signing public key: %s" % (data['signer'],))
|
logger.info("Signing public key: %s" % (data['signer'],))
|
||||||
assert self.api.get_core()._crypto.edVerify(data['data'], data['signer'], data['sig']) != False
|
assert self.api.get_core()._crypto.edVerify(data['data'], data['signer'], data['sig']) != False
|
||||||
|
@ -101,7 +101,7 @@ class PlainEncryption:
|
||||||
else:
|
else:
|
||||||
logger.info("Message has good signature.")
|
logger.info("Message has good signature.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def on_init(api, data = None):
|
def on_init(api, data = None):
|
||||||
'''
|
'''
|
||||||
|
@ -114,4 +114,4 @@ def on_init(api, data = None):
|
||||||
encrypt = PlainEncryption(pluginapi)
|
encrypt = PlainEncryption(pluginapi)
|
||||||
api.commands.register(['encrypt'], encrypt.encrypt)
|
api.commands.register(['encrypt'], encrypt.encrypt)
|
||||||
api.commands.register(['decrypt'], encrypt.decrypt)
|
api.commands.register(['decrypt'], encrypt.decrypt)
|
||||||
return
|
return
|
||||||
|
|
|
@ -132,10 +132,10 @@ def createRepository(plugins):
|
||||||
contents = {'plugins' : plugins, 'author' : getpass.getuser(), 'compiled-by' : plugin_name}
|
contents = {'plugins' : plugins, 'author' : getpass.getuser(), 'compiled-by' : plugin_name}
|
||||||
|
|
||||||
block = Block(core = pluginapi.get_core())
|
block = Block(core = pluginapi.get_core())
|
||||||
|
|
||||||
block.setType('repository')
|
block.setType('repository')
|
||||||
block.setContent(json.dumps(contents))
|
block.setContent(json.dumps(contents))
|
||||||
|
|
||||||
return block.save(True)
|
return block.save(True)
|
||||||
|
|
||||||
def check():
|
def check():
|
||||||
|
@ -217,7 +217,7 @@ def pluginToBlock(plugin, import_block = True):
|
||||||
info = ''
|
info = ''
|
||||||
with open(directory + 'info.json').read() as file:
|
with open(directory + 'info.json').read() as file:
|
||||||
info = json.loads(file.read())
|
info = json.loads(file.read())
|
||||||
|
|
||||||
if 'author' in info:
|
if 'author' in info:
|
||||||
author = info['author']
|
author = info['author']
|
||||||
if 'description' in info:
|
if 'description' in info:
|
||||||
|
@ -228,10 +228,10 @@ def pluginToBlock(plugin, import_block = True):
|
||||||
metadata = {'author' : author, 'date' : str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')), 'name' : plugin, 'info' : info, 'compiled-by' : plugin_name, 'content' : data.decode('utf-8'), 'description' : description}
|
metadata = {'author' : author, 'date' : str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')), 'name' : plugin, 'info' : info, 'compiled-by' : plugin_name, 'content' : data.decode('utf-8'), 'description' : description}
|
||||||
|
|
||||||
block = Block(core = pluginapi.get_core())
|
block = Block(core = pluginapi.get_core())
|
||||||
|
|
||||||
block.setType('plugin')
|
block.setType('plugin')
|
||||||
block.setContent(json.dumps(metadata))
|
block.setContent(json.dumps(metadata))
|
||||||
|
|
||||||
hash = block.save(True)
|
hash = block.save(True)
|
||||||
# hash = pluginapi.get_core().insertBlock(, header = 'plugin', sign = True)
|
# hash = pluginapi.get_core().insertBlock(, header = 'plugin', sign = True)
|
||||||
|
|
||||||
|
@ -390,12 +390,12 @@ def commandInstallPlugin():
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warn('Failed to lookup plugin in repositories.', timestamp = False)
|
logger.warn('Failed to lookup plugin in repositories.', timestamp = False)
|
||||||
logger.error('asdf', error = e, timestamp = False)
|
logger.error('asdf', error = e, timestamp = False)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if pkobh is None:
|
if pkobh is None:
|
||||||
logger.error('No key for this plugin found in keystore or repositories, please specify.', timestamp = False)
|
logger.error('No key for this plugin found in keystore or repositories, please specify.', timestamp = False)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
valid_hash = pluginapi.get_utils().validateHash(pkobh)
|
valid_hash = pluginapi.get_utils().validateHash(pkobh)
|
||||||
|
@ -552,49 +552,48 @@ def commandPublishPlugin():
|
||||||
logger.error('Plugin %s does not exist.' % pluginname, timestamp = False)
|
logger.error('Plugin %s does not exist.' % pluginname, timestamp = False)
|
||||||
else:
|
else:
|
||||||
logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' <plugin>')
|
logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' <plugin>')
|
||||||
|
|
||||||
def commandCreateRepository():
|
def commandCreateRepository():
|
||||||
if len(sys.argv) >= 3:
|
if len(sys.argv) >= 3:
|
||||||
check()
|
check()
|
||||||
|
|
||||||
plugins = list()
|
plugins = list()
|
||||||
script = sys.argv[0]
|
script = sys.argv[0]
|
||||||
|
|
||||||
del sys.argv[:2]
|
del sys.argv[:2]
|
||||||
success = True
|
success = True
|
||||||
for pluginname in sys.argv:
|
for pluginname in sys.argv:
|
||||||
distributor = None
|
distributor = None
|
||||||
|
|
||||||
if ':' in pluginname:
|
if ':' in pluginname:
|
||||||
split = pluginname.split(':')
|
split = pluginname.split(':')
|
||||||
pluginname = split[0]
|
pluginname = split[0]
|
||||||
distributor = split[1]
|
distributor = split[1]
|
||||||
|
|
||||||
pluginname = sanitize(pluginname)
|
pluginname = sanitize(pluginname)
|
||||||
|
|
||||||
if distributor is None:
|
if distributor is None:
|
||||||
distributor = getKey(pluginname)
|
distributor = getKey(pluginname)
|
||||||
if distributor is None:
|
if distributor is None:
|
||||||
logger.error('No distributor key was found for the plugin %s.' % pluginname, timestamp = False)
|
logger.error('No distributor key was found for the plugin %s.' % pluginname, timestamp = False)
|
||||||
success = False
|
success = False
|
||||||
|
|
||||||
plugins.append([pluginname, distributor])
|
plugins.append([pluginname, distributor])
|
||||||
|
|
||||||
if not success:
|
if not success:
|
||||||
logger.error('Please correct the above errors, then recreate the repository.')
|
logger.error('Please correct the above errors, then recreate the repository.')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
blockhash = createRepository(plugins)
|
blockhash = createRepository(plugins)
|
||||||
print(blockhash)
|
|
||||||
if not blockhash is None:
|
if not blockhash is None:
|
||||||
logger.info('Successfully created repository. Execute the following command to add the repository:\n ' + logger.colors.underline + '%s --add-repository %s' % (script, blockhash))
|
logger.info('Successfully created repository. Execute the following command to add the repository:\n ' + logger.colors.underline + '%s --add-repository %s' % (script, blockhash))
|
||||||
else:
|
else:
|
||||||
logger.error('Failed to create repository, an unknown error occurred.')
|
logger.error('Failed to create repository, an unknown error occurred.')
|
||||||
else:
|
else:
|
||||||
logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' [plugins...]')
|
logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' [plugins...]')
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# event listeners
|
# event listeners
|
||||||
|
|
||||||
def on_init(api, data = None):
|
def on_init(api, data = None):
|
||||||
|
|
|
@ -66,7 +66,7 @@ class OnionrMail:
|
||||||
self.sentboxList = []
|
self.sentboxList = []
|
||||||
self.sentMessages = {}
|
self.sentMessages = {}
|
||||||
return
|
return
|
||||||
|
|
||||||
def inbox(self):
|
def inbox(self):
|
||||||
blockCount = 0
|
blockCount = 0
|
||||||
pmBlockMap = {}
|
pmBlockMap = {}
|
||||||
|
@ -87,7 +87,7 @@ class OnionrMail:
|
||||||
continue
|
continue
|
||||||
blockCount += 1
|
blockCount += 1
|
||||||
pmBlockMap[blockCount] = blockHash
|
pmBlockMap[blockCount] = blockHash
|
||||||
|
|
||||||
block = pmBlocks[blockHash]
|
block = pmBlocks[blockHash]
|
||||||
senderKey = block.signer
|
senderKey = block.signer
|
||||||
try:
|
try:
|
||||||
|
@ -102,7 +102,7 @@ class OnionrMail:
|
||||||
displayList.append('%s. %s - %s: %s' % (blockCount, blockDate, senderDisplay[:12], blockHash))
|
displayList.append('%s. %s - %s: %s' % (blockCount, blockDate, senderDisplay[:12], blockHash))
|
||||||
#displayList.reverse()
|
#displayList.reverse()
|
||||||
for i in displayList:
|
for i in displayList:
|
||||||
print(i)
|
logger.info(i)
|
||||||
try:
|
try:
|
||||||
choice = logger.readline('Enter a block number, -r to refresh, or -q to stop: ').strip().lower()
|
choice = logger.readline('Enter a block number, -r to refresh, or -q to stop: ').strip().lower()
|
||||||
except (EOFError, KeyboardInterrupt):
|
except (EOFError, KeyboardInterrupt):
|
||||||
|
@ -129,16 +129,16 @@ class OnionrMail:
|
||||||
else:
|
else:
|
||||||
cancel = ''
|
cancel = ''
|
||||||
readBlock.verifySig()
|
readBlock.verifySig()
|
||||||
print('Message recieved from %s' % (self.myCore._utils.bytesToStr(readBlock.signer,)))
|
logger.info('Message recieved from %s' % (self.myCore._utils.bytesToStr(readBlock.signer,)))
|
||||||
print('Valid signature:', readBlock.validSig)
|
logger.info('Valid signature: %s' % readBlock.validSig)
|
||||||
if not readBlock.validSig:
|
if not readBlock.validSig:
|
||||||
logger.warn('This message has an INVALID signature. ANYONE could have sent this message.')
|
logger.warn('This message has an INVALID signature. ANYONE could have sent this message.')
|
||||||
cancel = logger.readline('Press enter to continue to message, or -q to not open the message (recommended).')
|
cancel = logger.readline('Press enter to continue to message, or -q to not open the message (recommended).')
|
||||||
if cancel != '-q':
|
if cancel != '-q':
|
||||||
print(draw_border(self.myCore._utils.escapeAnsi(readBlock.bcontent.decode().strip())))
|
print(draw_border(self.myCore._utils.escapeAnsi(readBlock.bcontent.decode().strip())))
|
||||||
input("Press enter to continue")
|
logger.readline("Press enter to continue")
|
||||||
return
|
return
|
||||||
|
|
||||||
def sentbox(self):
|
def sentbox(self):
|
||||||
'''
|
'''
|
||||||
Display sent mail messages
|
Display sent mail messages
|
||||||
|
@ -146,7 +146,7 @@ class OnionrMail:
|
||||||
entering = True
|
entering = True
|
||||||
while entering:
|
while entering:
|
||||||
self.getSentList()
|
self.getSentList()
|
||||||
print('Enter block number or -q to return')
|
logger.info('Enter block number or -q to return')
|
||||||
try:
|
try:
|
||||||
choice = input('>')
|
choice = input('>')
|
||||||
except (EOFError, KeyboardInterrupt) as e:
|
except (EOFError, KeyboardInterrupt) as e:
|
||||||
|
@ -158,21 +158,21 @@ class OnionrMail:
|
||||||
try:
|
try:
|
||||||
self.sentboxList[int(choice) - 1]
|
self.sentboxList[int(choice) - 1]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
print('Invalid block')
|
logger.warn('Invalid block.')
|
||||||
else:
|
else:
|
||||||
logger.info('Sent to: ' + self.sentMessages[self.sentboxList[int(choice) - 1]][1])
|
logger.info('Sent to: ' + self.sentMessages[self.sentboxList[int(choice) - 1]][1])
|
||||||
# Print ansi escaped sent message
|
# Print ansi escaped sent message
|
||||||
print(self.myCore._utils.escapeAnsi(self.sentMessages[self.sentboxList[int(choice) - 1]][0]))
|
logger.info(self.myCore._utils.escapeAnsi(self.sentMessages[self.sentboxList[int(choice) - 1]][0]))
|
||||||
input('Press enter to continue...')
|
input('Press enter to continue...')
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def getSentList(self):
|
def getSentList(self):
|
||||||
count = 1
|
count = 1
|
||||||
for i in self.sentboxTools.listSent():
|
for i in self.sentboxTools.listSent():
|
||||||
self.sentboxList.append(i['hash'])
|
self.sentboxList.append(i['hash'])
|
||||||
self.sentMessages[i['hash']] = (i['message'], i['peer'])
|
self.sentMessages[i['hash']] = (i['message'], i['peer'])
|
||||||
print('%s. %s - %s - %s' % (count, i['hash'], i['peer'][:12], i['date']))
|
logger.info('%s. %s - %s - %s' % (count, i['hash'], i['peer'][:12], i['date']))
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
def draftMessage(self):
|
def draftMessage(self):
|
||||||
|
@ -198,7 +198,7 @@ class OnionrMail:
|
||||||
# if -q or ctrl-c/d, exit function here, otherwise we successfully got the public key
|
# if -q or ctrl-c/d, exit function here, otherwise we successfully got the public key
|
||||||
return
|
return
|
||||||
|
|
||||||
print('Enter your message, stop by entering -q on a new line.')
|
logger.info('Enter your message, stop by entering -q on a new line.')
|
||||||
while newLine != '-q':
|
while newLine != '-q':
|
||||||
try:
|
try:
|
||||||
newLine = input()
|
newLine = input()
|
||||||
|
@ -209,7 +209,7 @@ class OnionrMail:
|
||||||
newLine += '\n'
|
newLine += '\n'
|
||||||
message += newLine
|
message += newLine
|
||||||
|
|
||||||
print('Inserting encrypted message as Onionr block....')
|
logger.info('Inserting encrypted message as Onionr block....')
|
||||||
|
|
||||||
blockID = self.myCore.insertBlock(message, header='pm', encryptType='asym', asymPeer=recip, sign=True)
|
blockID = self.myCore.insertBlock(message, header='pm', encryptType='asym', asymPeer=recip, sign=True)
|
||||||
self.sentboxTools.addToSent(blockID, recip, message)
|
self.sentboxTools.addToSent(blockID, recip, message)
|
||||||
|
@ -217,7 +217,7 @@ class OnionrMail:
|
||||||
choice = ''
|
choice = ''
|
||||||
while True:
|
while True:
|
||||||
|
|
||||||
print(self.strings.programTag + '\n\nOur ID: ' + self.myCore._crypto.pubKey + self.strings.mainMenu.title()) # print out main menu
|
logger.info(self.strings.programTag + '\n\nOur ID: ' + self.myCore._crypto.pubKey + self.strings.mainMenu.title()) # print out main menu
|
||||||
|
|
||||||
try:
|
try:
|
||||||
choice = logger.readline('Enter 1-%s:\n' % (len(self.strings.mainMenuChoices))).lower().strip()
|
choice = logger.readline('Enter 1-%s:\n' % (len(self.strings.mainMenuChoices))).lower().strip()
|
||||||
|
@ -251,4 +251,4 @@ def on_init(api, data = None):
|
||||||
mail = OnionrMail(pluginapi)
|
mail = OnionrMail(pluginapi)
|
||||||
api.commands.register(['mail'], mail.menu)
|
api.commands.register(['mail'], mail.menu)
|
||||||
api.commands.register_help('mail', 'Interact with OnionrMail')
|
api.commands.register_help('mail', 'Interact with OnionrMail')
|
||||||
return
|
return
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
"general" : {
|
"general" : {
|
||||||
"dev_mode" : true,
|
"dev_mode" : true,
|
||||||
"display_header" : true,
|
"display_header" : true,
|
||||||
|
|
||||||
"minimum_block_pow": 5,
|
"minimum_block_pow": 5,
|
||||||
"minimum_send_pow": 5,
|
"minimum_send_pow": 5,
|
||||||
|
|
||||||
|
@ -34,7 +35,20 @@
|
||||||
"client" : {
|
"client" : {
|
||||||
|
|
||||||
},
|
},
|
||||||
"log": {
|
|
||||||
|
"plugins" : {
|
||||||
|
"enabled" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
"disabled" : {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"log" : {
|
||||||
|
"verbosity" : "default",
|
||||||
|
|
||||||
"file": {
|
"file": {
|
||||||
"output": false,
|
"output": false,
|
||||||
"path": "data/output.log"
|
"path": "data/output.log"
|
||||||
|
|
|
@ -3,9 +3,9 @@ P G'
|
||||||
P G''
|
P G''
|
||||||
P G'' '
|
P G'' '
|
||||||
P G''''''
|
P G''''''
|
||||||
P :G;'''''P:
|
P :G''''''P:
|
||||||
P ::G;'''P::
|
P ::G''''P::
|
||||||
P :::G;;P:::
|
P :::G''P:::
|
||||||
P ::::::::
|
P ::::::::
|
||||||
P ::::::::::::
|
P ::::::::::::
|
||||||
P :::::::::::::::
|
P :::::::::::::::
|
||||||
|
@ -20,6 +20,7 @@ P :::: ::::: ::::: ::: W :::: :: :: :: ::::: :: :: :: ::
|
||||||
P :::: :::::: :::::: ::::
|
P :::: :::::: :::::: ::::
|
||||||
P :::: :::::::::::: :::: GvPBV
|
P :::: :::::::::::: :::: GvPBV
|
||||||
P ::::: :::::::: ::::
|
P ::::: :::::::: ::::
|
||||||
P ::::: ::::::
|
P ::::: :::::
|
||||||
P ::::::::::::::::
|
P ::::::::::::::::
|
||||||
P :::::::
|
P :::::::
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue