renamed onionr dir and bugfixes/linting progress
This commit is contained in:
parent
2b996da17f
commit
720efe4fca
226 changed files with 179 additions and 142 deletions
29
src/onionrcommands/README.md
Executable file
29
src/onionrcommands/README.md
Executable file
|
@ -0,0 +1,29 @@
|
|||
# onionrcommands
|
||||
|
||||
This module contains handlers/functions for Onionr cli interface commands.
|
||||
|
||||
## Files
|
||||
|
||||
parser/: Registers and handles Onionr CLI commands
|
||||
|
||||
__init__.py: stores the command references (aside from plugins) and help info.
|
||||
|
||||
banblocks.py: command handler for manually removing blocks from one's node
|
||||
|
||||
daemonlaunch.py: command to run Onionr (start the api servers, tor and communicator)
|
||||
|
||||
exportblocks.py: command to export an onionr block to the export folder. Exported blocks can be manually shared outside of the Onionr network
|
||||
|
||||
filecommands.py commands to insert and fetch files from the Onionr network
|
||||
|
||||
keyadders.py: commands to add an onionr user key or transport address
|
||||
|
||||
onionrstatistics.py: commands to print out various information about one's Onionr node
|
||||
|
||||
openwebinterface.py: command to open the web interface (useful because it requires a randomly generated token)
|
||||
|
||||
plugincommands.py: commands to enable/disable/reload plugins
|
||||
|
||||
pubkeymanager.py: commands to generate a new onionr user id, change the active id, or add/remove/list friends
|
||||
|
||||
resettor.py: command to delete the Tor data directory
|
0
src/onionrcommands/__init__.py
Executable file
0
src/onionrcommands/__init__.py
Executable file
53
src/onionrcommands/banblocks.py
Executable file
53
src/onionrcommands/banblocks.py
Executable file
|
@ -0,0 +1,53 @@
|
|||
'''
|
||||
Onionr - Private P2P Communication
|
||||
|
||||
This file contains the command for banning blocks from the node
|
||||
'''
|
||||
'''
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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 sys
|
||||
import logger
|
||||
from onionrutils import stringvalidators
|
||||
from onionrstorage import removeblock
|
||||
from onionrstorage import deleteBlock
|
||||
from onionrblocks import onionrblacklist
|
||||
from utils import reconstructhash
|
||||
|
||||
def ban_block():
|
||||
"""Deletes a block, permanently blacklisting it"""
|
||||
blacklist = onionrblacklist.OnionrBlackList()
|
||||
try:
|
||||
ban = sys.argv[2]
|
||||
except IndexError:
|
||||
# Get the hash if its not provided as a CLI argument
|
||||
ban = logger.readline('Enter a block hash:').strip()
|
||||
# Make sure the hash has no truncated zeroes
|
||||
ban = reconstructhash.reconstruct_hash(ban)
|
||||
if stringvalidators.validate_hash(ban):
|
||||
if not blacklist.inBlacklist(ban):
|
||||
try:
|
||||
blacklist.addToDB(ban)
|
||||
removeblock.remove_block(ban)
|
||||
deleteBlock(ban)
|
||||
except Exception as error:
|
||||
logger.error('Could not blacklist block', error=error, terminal=True)
|
||||
else:
|
||||
logger.info('Block blacklisted', terminal=True)
|
||||
else:
|
||||
logger.warn('That block is already blacklisted', terminal=True)
|
||||
else:
|
||||
logger.error('Invalid block hash', terminal=True)
|
||||
|
||||
ban_block.onionr_help = "<block hash>: deletes and blacklists a block"
|
164
src/onionrcommands/daemonlaunch.py
Executable file
164
src/onionrcommands/daemonlaunch.py
Executable file
|
@ -0,0 +1,164 @@
|
|||
'''
|
||||
Onionr - Private P2P Communication
|
||||
|
||||
launch the api servers and communicator
|
||||
'''
|
||||
'''
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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, time, sys, platform, sqlite3, signal
|
||||
from threading import Thread
|
||||
|
||||
import toomanyobjs
|
||||
|
||||
import config, apiservers, logger, communicator
|
||||
from onionrplugins import onionrevents as events
|
||||
from netcontroller import NetController
|
||||
from onionrutils import localcommand
|
||||
import filepaths
|
||||
from coredb import daemonqueue
|
||||
from etc import onionrvalues, cleanup
|
||||
from onionrcrypto import getourkeypair
|
||||
from utils import hastor, logoheader
|
||||
from . import version
|
||||
import serializeddata
|
||||
import runtests
|
||||
|
||||
def _proper_shutdown():
|
||||
localcommand.local_command('shutdown')
|
||||
sys.exit(1)
|
||||
|
||||
def daemon():
|
||||
'''
|
||||
Starts the Onionr communication daemon
|
||||
'''
|
||||
if not hastor.has_tor():
|
||||
logger.error("Tor is not present in system path or Onionr directory", terminal=True)
|
||||
sys.exit(1)
|
||||
|
||||
# remove runcheck if it exists
|
||||
if os.path.isfile(filepaths.run_check_file):
|
||||
logger.debug('Runcheck file found on daemon start, deleting in advance.')
|
||||
os.remove(filepaths.run_check_file)
|
||||
|
||||
# Create shared objects
|
||||
|
||||
shared_state = toomanyobjs.TooMany()
|
||||
|
||||
Thread(target=shared_state.get(apiservers.ClientAPI).start, daemon=True, name='client HTTP API').start()
|
||||
Thread(target=shared_state.get(apiservers.PublicAPI).start, daemon=True, name='public HTTP API').start()
|
||||
|
||||
# Init run time tester (ensures Onionr is running right, for testing purposes)
|
||||
|
||||
shared_state.get(runtests.OnionrRunTestManager)
|
||||
shared_state.get(serializeddata.SerializedData)
|
||||
shared_state.share_object() # share the parent object to the threads
|
||||
|
||||
apiHost = ''
|
||||
while apiHost == '':
|
||||
try:
|
||||
with open(filepaths.public_API_host_file, 'r') as hostFile:
|
||||
apiHost = hostFile.read()
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
time.sleep(0.5)
|
||||
|
||||
logger.raw('', terminal=True)
|
||||
# print nice header thing :)
|
||||
if config.get('general.display_header', True):
|
||||
logoheader.header()
|
||||
version.version(verbosity = 5, function = logger.info)
|
||||
logger.debug('Python version %s' % platform.python_version())
|
||||
|
||||
if onionrvalues.DEVELOPMENT_MODE:
|
||||
logger.warn('Development mode enabled', timestamp = False, terminal=True)
|
||||
|
||||
net = NetController(config.get('client.public.port', 59497), apiServerIP=apiHost)
|
||||
shared_state.add(net)
|
||||
|
||||
logger.info('Tor is starting...', terminal=True)
|
||||
if not net.startTor():
|
||||
localcommand.local_command('shutdown')
|
||||
cleanup.delete_run_files()
|
||||
sys.exit(1)
|
||||
if len(net.myID) > 0 and config.get('general.security_level', 1) == 0:
|
||||
logger.debug('Started .onion service: %s' % (logger.colors.underline + net.myID))
|
||||
else:
|
||||
logger.debug('.onion service disabled')
|
||||
logger.info('Using public key: %s' % (logger.colors.underline + getourkeypair.get_keypair()[0][:52]))
|
||||
|
||||
try:
|
||||
time.sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
events.event('init', threaded = False)
|
||||
events.event('daemon_start')
|
||||
communicator.startCommunicator(shared_state)
|
||||
|
||||
localcommand.local_command('shutdown')
|
||||
|
||||
net.killTor()
|
||||
try:
|
||||
time.sleep(5) # Time to allow threads to finish, if not any "daemon" threads will be slaughtered http://docs.python.org/library/threading.html#threading.Thread.daemon
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
cleanup.delete_run_files()
|
||||
|
||||
def _ignore_sigint(sig, frame):
|
||||
'''This space intentionally left blank'''
|
||||
return
|
||||
|
||||
def kill_daemon():
|
||||
'''
|
||||
Shutdown the Onionr daemon (communicator)
|
||||
'''
|
||||
logger.warn('Stopping the running daemon...', timestamp = False, terminal=True)
|
||||
try:
|
||||
# On platforms where we can, fork out to prevent locking
|
||||
try:
|
||||
pid = os.fork()
|
||||
if pid != 0: return
|
||||
except (AttributeError, OSError) as e: pass
|
||||
|
||||
events.event('daemon_stop')
|
||||
net = NetController(config.get('client.port', 59496))
|
||||
try:
|
||||
daemonqueue.daemon_queue_add('shutdown')
|
||||
except sqlite3.OperationalError:
|
||||
pass
|
||||
|
||||
net.killTor()
|
||||
except Exception as e:
|
||||
logger.error('Failed to shutdown daemon: ' + str(e), error = e, timestamp = False, terminal=True)
|
||||
return
|
||||
|
||||
kill_daemon.onionr_help = "Gracefully stops the Onionr API servers"
|
||||
|
||||
def start(input: bool = False, override: bool = False):
|
||||
"""If no lock file, make one and start onionr, error if there is and its not overridden"""
|
||||
if os.path.exists(filepaths.lock_file) 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).', terminal=True)
|
||||
else:
|
||||
if not onionrvalues.DEVELOPMENT_MODE:
|
||||
lockFile = open(filepaths.lock_file, 'w')
|
||||
lockFile.write('delete at your own risk')
|
||||
lockFile.close()
|
||||
daemon()
|
||||
try:
|
||||
os.remove(filepaths.lock_file)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
start.onionr_help = "Start Onionr node (public and clients API servers)"
|
43
src/onionrcommands/exportblocks.py
Executable file
43
src/onionrcommands/exportblocks.py
Executable file
|
@ -0,0 +1,43 @@
|
|||
'''
|
||||
Onionr - Private P2P Communication
|
||||
|
||||
This file handles the command for exporting blocks to disk
|
||||
'''
|
||||
'''
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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 sys, os
|
||||
import logger, onionrstorage
|
||||
from utils import createdirs
|
||||
from onionrutils import stringvalidators
|
||||
import filepaths
|
||||
def doExport(bHash):
|
||||
createdirs.create_dirs()
|
||||
data = onionrstorage.getData(bHash)
|
||||
with open('%s/%s.dat' % (filepaths.export_location, bHash), 'wb') as exportFile:
|
||||
exportFile.write(data)
|
||||
logger.info('Block exported as file', terminal=True)
|
||||
|
||||
def export_block():
|
||||
exportDir = filepaths.export_location
|
||||
try:
|
||||
if not stringvalidators.validate_hash(sys.argv[2]): raise ValueError
|
||||
except (IndexError, ValueError):
|
||||
logger.error('No valid block hash specified.', terminal=True)
|
||||
sys.exit(1)
|
||||
else:
|
||||
bHash = sys.argv[2]
|
||||
doExport(bHash)
|
||||
|
||||
export_block.onionr_help = "<block hash>: Export an Onionr block to a file. Export directory is in the Onionr data directory under block-export/"
|
89
src/onionrcommands/filecommands.py
Executable file
89
src/onionrcommands/filecommands.py
Executable file
|
@ -0,0 +1,89 @@
|
|||
"""
|
||||
Onionr - Private P2P Communication
|
||||
|
||||
This file handles the commands for adding and getting files from the Onionr network
|
||||
"""
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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 base64, sys, os
|
||||
import logger
|
||||
from onionrblocks.onionrblockapi import Block
|
||||
import onionrexceptions
|
||||
from onionrutils import stringvalidators
|
||||
from etc import onionrvalues
|
||||
from onionrblocks import insert
|
||||
_ORIG_DIR = onionrvalues.ORIG_RUN_DIR_ENV_VAR
|
||||
|
||||
def _get_dir(path: str)->str:
|
||||
if not os.getenv(_ORIG_DIR) is None: return os.getenv(_ORIG_DIR) + '/' + path
|
||||
else: return path
|
||||
|
||||
def add_html(singleBlock=True, blockType='html'):
|
||||
add_file(singleBlock, blockType)
|
||||
|
||||
add_html.onionr_help = "Adds an HTML file into Onionr. Does not currently include dependant resources"
|
||||
|
||||
def add_file(singleBlock=False, blockType='bin'):
|
||||
"""
|
||||
Adds a file to the onionr network
|
||||
"""
|
||||
|
||||
if len(sys.argv) >= 3:
|
||||
filename = sys.argv[2]
|
||||
contents = None
|
||||
if not os.path.exists(_get_dir(filename)):
|
||||
logger.error('That file does not exist. Improper path (specify full path)?', terminal=True)
|
||||
return
|
||||
logger.info('Adding file... this might take a long time.', terminal=True)
|
||||
try:
|
||||
with open(_get_dir(filename), 'rb') as singleFile:
|
||||
blockhash = insert(singleFile.read(), header=blockType)
|
||||
if len(blockhash) > 0:
|
||||
logger.info('File %s saved in block %s' % (filename, blockhash), terminal=True)
|
||||
except Exception as e:
|
||||
logger.error('Failed to save file in block ' + str(e), timestamp = False, terminal=True)
|
||||
else:
|
||||
logger.error('%s add-file <filename>' % sys.argv[0], timestamp = False, terminal=True)
|
||||
|
||||
add_file.onionr_help = "<file path> Add a file into the Onionr network"
|
||||
|
||||
def get_file():
|
||||
"""
|
||||
Get a file from onionr blocks
|
||||
"""
|
||||
try:
|
||||
fileName = _get_dir(sys.argv[2])
|
||||
bHash = sys.argv[3]
|
||||
except IndexError:
|
||||
logger.error("Syntax %s %s" % (sys.argv[0], '/path/to/filename <blockhash>'), terminal=True)
|
||||
else:
|
||||
logger.info(fileName, terminal=True)
|
||||
|
||||
contents = None
|
||||
if os.path.exists(fileName):
|
||||
logger.error("File already exists", terminal=True)
|
||||
return
|
||||
if not stringvalidators.validate_hash(bHash):
|
||||
logger.error('Block hash is invalid', terminal=True)
|
||||
return
|
||||
|
||||
try:
|
||||
with open(fileName, 'wb') as myFile:
|
||||
myFile.write(Block(bHash).bcontent)
|
||||
except onionrexceptions.NoDataAvailable:
|
||||
logger.error('That block is not available. Trying again later may work.', terminal=True)
|
||||
|
||||
get_file.onionr_help = "<file path> <block hash>: Download a file from the onionr network."
|
37
src/onionrcommands/keyadders.py
Executable file
37
src/onionrcommands/keyadders.py
Executable file
|
@ -0,0 +1,37 @@
|
|||
'''
|
||||
Onionr - Private P2P Communication
|
||||
|
||||
add keys (transport and pubkey)
|
||||
'''
|
||||
'''
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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 sys
|
||||
import logger
|
||||
from coredb import keydb
|
||||
|
||||
def add_address():
|
||||
try:
|
||||
newAddress = sys.argv[2]
|
||||
newAddress = newAddress.replace('http:', '').replace('/', '')
|
||||
except IndexError:
|
||||
pass
|
||||
else:
|
||||
logger.info("Adding address: " + logger.colors.underline + newAddress, terminal=True)
|
||||
if keydb.addkeys.add_address(newAddress):
|
||||
logger.info("Successfully added address.", terminal=True)
|
||||
else:
|
||||
logger.warn("Unable to add address.", terminal=True)
|
||||
|
||||
add_address.onionr_help = "Adds a node transport address to the local node list"
|
15
src/onionrcommands/motdcreator.py
Normal file
15
src/onionrcommands/motdcreator.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
import onionrblocks
|
||||
|
||||
def motd_creator():
|
||||
"""Create a new MOTD message for the Onionr network"""
|
||||
motd = ''
|
||||
new = ''
|
||||
print('Enter a new MOTD, quit on a new line:')
|
||||
while new != 'quit':
|
||||
new = input()
|
||||
if new != 'quit':
|
||||
motd += new
|
||||
bl = onionrblocks.insert(motd, header='motd', sign=True)
|
||||
print(f"inserted in {bl}")
|
||||
|
||||
motd_creator.onionr_help = "Create a new MOTD message for the onionr network"
|
103
src/onionrcommands/onionrstatistics.py
Executable file
103
src/onionrcommands/onionrstatistics.py
Executable file
|
@ -0,0 +1,103 @@
|
|||
'''
|
||||
Onionr - Private P2P Communication
|
||||
|
||||
This module defines commands to show stats/details about the local node
|
||||
'''
|
||||
'''
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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, uuid, time
|
||||
import logger
|
||||
from onionrblocks import onionrblockapi
|
||||
from onionrblocks import onionrblacklist
|
||||
from onionrutils import checkcommunicator, mnemonickeys
|
||||
from utils import sizeutils, gethostname, getconsolewidth, identifyhome
|
||||
from coredb import blockmetadb, daemonqueue, keydb
|
||||
import onionrcrypto, config
|
||||
from etc import onionrvalues
|
||||
def show_stats():
|
||||
try:
|
||||
# define stats messages here
|
||||
totalBlocks = len(blockmetadb.get_block_list())
|
||||
home = identifyhome.identify_home()
|
||||
signedBlocks = len(onionrblockapi.Block.getBlocks(signed = True))
|
||||
totalBanned = len(onionrblacklist.OnionrBlackList().getList())
|
||||
|
||||
messages = {
|
||||
# info about local client
|
||||
'Onionr Daemon Status' : ((logger.colors.fg.green + 'Online') if checkcommunicator.is_communicator_running(timeout = 9) else logger.colors.fg.red + 'Offline'),
|
||||
|
||||
# file and folder size stats
|
||||
'div1' : True, # this creates a solid line across the screen, a div
|
||||
'Total Block Size' : sizeutils.human_size(sizeutils.size(home + 'blocks/')),
|
||||
'Total Plugin Size' : sizeutils.human_size(sizeutils.size(home + 'plugins/')),
|
||||
'Log File Size' : sizeutils.human_size(sizeutils.size(home + 'output.log')),
|
||||
|
||||
# count stats
|
||||
'div2' : True,
|
||||
'Known Peers (nodes)' : str(max(len(keydb.listkeys.list_adders()) - 1, 0)),
|
||||
'Enabled Plugins' : str(len(config.get('plugins.enabled', list()))) + ' / ' + str(len(os.listdir(home + 'plugins/'))),
|
||||
'Stored Blocks' : str(totalBlocks),
|
||||
'Deleted Blocks' : str(totalBanned),
|
||||
'Percent Blocks Signed' : str(round(100 * signedBlocks / max(totalBlocks, 1), 2)) + '%'
|
||||
}
|
||||
|
||||
# color configuration
|
||||
colors = {
|
||||
'title' : logger.colors.bold,
|
||||
'key' : logger.colors.fg.lightgreen,
|
||||
'val' : logger.colors.fg.green,
|
||||
'border' : logger.colors.fg.lightblue,
|
||||
|
||||
'reset' : logger.colors.reset
|
||||
}
|
||||
|
||||
# pre-processing
|
||||
maxlength = 0
|
||||
width = getconsolewidth.get_console_width()
|
||||
for key, val in messages.items():
|
||||
if not (type(val) is bool and val is True):
|
||||
maxlength = max(len(key), maxlength)
|
||||
prewidth = maxlength + len(' | ')
|
||||
groupsize = width - prewidth - len('[+] ')
|
||||
|
||||
# generate stats table
|
||||
logger.info(colors['title'] + 'Onionr v%s Statistics' % onionrvalues.ONIONR_VERSION + colors['reset'], terminal=True)
|
||||
logger.info(colors['border'] + '-' * (maxlength + 1) + '+' + colors['reset'], terminal=True)
|
||||
for key, val in messages.items():
|
||||
if not (type(val) is bool and val is True):
|
||||
val = [str(val)[i:i + groupsize] for i in range(0, len(str(val)), groupsize)]
|
||||
|
||||
logger.info(colors['key'] + str(key).rjust(maxlength) + colors['reset'] + colors['border'] + ' | ' + colors['reset'] + colors['val'] + str(val.pop(0)) + colors['reset'], terminal=True)
|
||||
|
||||
for value in val:
|
||||
logger.info(' ' * maxlength + colors['border'] + ' | ' + colors['reset'] + colors['val'] + str(value) + colors['reset'], terminal=True)
|
||||
else:
|
||||
logger.info(colors['border'] + '-' * (maxlength + 1) + '+' + colors['reset'], terminal=True)
|
||||
logger.info(colors['border'] + '-' * (maxlength + 1) + '+' + colors['reset'], terminal=True)
|
||||
except Exception as e:
|
||||
logger.error('Failed to generate statistics table. ' + str(e), error = e, timestamp = False, terminal=True)
|
||||
|
||||
def show_details():
|
||||
details = {
|
||||
'Node Address' : gethostname.get_hostname(),
|
||||
'Public Key' : onionrcrypto.pub_key.replace('=', ''),
|
||||
'Human-readable Public Key' : mnemonickeys.get_human_readable_ID()
|
||||
}
|
||||
|
||||
for detail in details:
|
||||
logger.info('%s%s: \n%s%s\n' % (logger.colors.fg.lightgreen, detail, logger.colors.fg.green, details[detail]), terminal = True)
|
||||
|
||||
show_details.onionr_help = "Shows relevant information for your Onionr install: node address, and active public key."
|
||||
show_stats.onionr_help = "Shows statistics for your Onionr node. Slow if Onionr is not running"
|
48
src/onionrcommands/openwebinterface.py
Executable file
48
src/onionrcommands/openwebinterface.py
Executable file
|
@ -0,0 +1,48 @@
|
|||
'''
|
||||
Onionr - Private P2P Communication
|
||||
|
||||
Open the web interface properly into a web browser
|
||||
'''
|
||||
'''
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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 webbrowser
|
||||
import logger
|
||||
from onionrutils import getclientapiserver
|
||||
import config
|
||||
|
||||
def get_url():
|
||||
try:
|
||||
url = getclientapiserver.get_client_API_server()
|
||||
except FileNotFoundError:
|
||||
url = ""
|
||||
logger.error('Onionr seems to not be running (could not get api host)', terminal=True)
|
||||
else:
|
||||
url = 'http://%s/#%s' % (url, config.get('client.webpassword'))
|
||||
logger.info('Onionr web interface URL: ' + url, terminal=True)
|
||||
return url
|
||||
|
||||
get_url.onionr_help = "Shows the Onionr web interface URL with API key"
|
||||
|
||||
def open_home():
|
||||
try:
|
||||
url = getclientapiserver.get_client_API_server()
|
||||
except FileNotFoundError:
|
||||
logger.error('Onionr seems to not be running (could not get api host)', terminal=True)
|
||||
else:
|
||||
url = 'http://%s/#%s' % (url, config.get('client.webpassword'))
|
||||
logger.info('If Onionr does not open automatically, use this URL: ' + url, terminal=True)
|
||||
webbrowser.open_new_tab(url)
|
||||
|
||||
open_home.onionr_help = "Opens the Onionr web UI in the default browser. Node must be running."
|
109
src/onionrcommands/parser/__init__.py
Normal file
109
src/onionrcommands/parser/__init__.py
Normal file
|
@ -0,0 +1,109 @@
|
|||
'''
|
||||
Onionr - Private P2P Communication
|
||||
|
||||
This module loads in the Onionr arguments and their help messages
|
||||
'''
|
||||
'''
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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 sys
|
||||
import os
|
||||
|
||||
from etc import onionrvalues
|
||||
import logger, onionrexceptions
|
||||
import onionrplugins
|
||||
from onionrplugins import onionrpluginapi
|
||||
from . import arguments, recommend
|
||||
|
||||
plugin_command = lambda cmd: 'on_%s_cmd' % (cmd,)
|
||||
|
||||
def register_plugin_commands(cmd)->bool:
|
||||
plugin_cmd = plugin_command(cmd)
|
||||
for pl in onionrplugins.get_enabled_plugins():
|
||||
pl = onionrplugins.get_plugin(pl)
|
||||
if hasattr(pl, plugin_cmd):
|
||||
getattr(pl, plugin_cmd)(onionrpluginapi.PluginAPI)
|
||||
return True
|
||||
return False
|
||||
|
||||
def register():
|
||||
"""Registers commands and handles help command processing"""
|
||||
def get_help_message(cmd: str, default: str = 'No help available for this command'):
|
||||
"""Return help message for a given command, supports plugin commands"""
|
||||
pl_cmd = plugin_command(cmd)
|
||||
for pl in onionrplugins.get_enabled_plugins():
|
||||
pl = onionrplugins.get_plugin(pl)
|
||||
if hasattr(pl, pl_cmd):
|
||||
try:
|
||||
return getattr(pl, pl_cmd).onionr_help
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
for i in arguments.get_arguments():
|
||||
for alias in i:
|
||||
try:
|
||||
return arguments.get_help(cmd)
|
||||
except AttributeError:
|
||||
pass
|
||||
return default # Return the help string
|
||||
|
||||
PROGRAM_NAME = "onionr"
|
||||
|
||||
# Get the command
|
||||
try:
|
||||
cmd = sys.argv[1]
|
||||
except IndexError:
|
||||
logger.debug("Detected Onionr run with no commands specified")
|
||||
return
|
||||
|
||||
is_help_cmd = False
|
||||
if cmd.replace('--', '').lower() == 'help': is_help_cmd = True
|
||||
|
||||
try:
|
||||
try:
|
||||
if not cmd in ('start', 'details', 'show-details') : os.chdir(os.environ['ORIG_ONIONR_RUN_DIR'])
|
||||
except KeyError: pass
|
||||
try:
|
||||
arguments.get_func(cmd)()
|
||||
except KeyboardInterrupt: pass
|
||||
except onionrexceptions.NotFound:
|
||||
if not register_plugin_commands(cmd) and not is_help_cmd:
|
||||
recommend.recommend()
|
||||
sys.exit(3)
|
||||
|
||||
if is_help_cmd:
|
||||
try:
|
||||
sys.argv[2]
|
||||
except IndexError:
|
||||
for i in arguments.get_arguments():
|
||||
logger.info('%s <%s>: %s' % (PROGRAM_NAME, '/'.join(i), get_help_message(i[0])), terminal=True)
|
||||
for pl in onionrplugins.get_enabled_plugins():
|
||||
pl = onionrplugins.get_plugin(pl)
|
||||
if hasattr(pl, 'ONIONR_COMMANDS'):
|
||||
print('')
|
||||
try:
|
||||
logger.info('%s commands:' % (pl.plugin_name,), terminal=True)
|
||||
except AttributeError:
|
||||
logger.info('%s commands:' % (pl.__name__,), terminal=True)
|
||||
for plugin_cmd in pl.ONIONR_COMMANDS:
|
||||
logger.info('%s %s: %s' % (PROGRAM_NAME, plugin_cmd, get_help_message(plugin_cmd)), terminal=True)
|
||||
print('')
|
||||
else:
|
||||
try:
|
||||
logger.info('%s %s: %s' % (PROGRAM_NAME, sys.argv[2], get_help_message(sys.argv[2])), terminal=True)
|
||||
except KeyError:
|
||||
logger.error('%s: command does not exist.' % [sys.argv[2]], terminal=True)
|
||||
sys.exit(3)
|
||||
return
|
||||
|
88
src/onionrcommands/parser/arguments.py
Normal file
88
src/onionrcommands/parser/arguments.py
Normal file
|
@ -0,0 +1,88 @@
|
|||
'''
|
||||
Onionr - Private P2P Communication
|
||||
|
||||
Sets CLI arguments for Onionr
|
||||
'''
|
||||
'''
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
'''
|
||||
from typing import Callable
|
||||
|
||||
from .. import onionrstatistics, version, daemonlaunch, keyadders, openwebinterface
|
||||
from .. import banblocks # Command to blacklist a block by its hash
|
||||
from .. import filecommands # commands to share files with onionr
|
||||
from .. import exportblocks # commands to export blocks
|
||||
from .. import pubkeymanager # commands to add or change id
|
||||
from .. import resettor # commands to reset the tor data directory or transport keypair
|
||||
from .. import resetplugins # command to reinstall default plugins
|
||||
from .. import softreset # command to delete onionr blocks
|
||||
from .. import restartonionr # command to restart Onionr
|
||||
from .. import runtimetestcmd
|
||||
from .. import motdcreator
|
||||
from .. import sitecreator
|
||||
|
||||
import onionrexceptions
|
||||
from onionrutils import importnewblocks # func to import new blocks
|
||||
from onionrplugins import onionrevents as events
|
||||
|
||||
def get_arguments()->dict:
|
||||
"""This is a function because we need to be able to dynamically modify them with plugins"""
|
||||
args = {
|
||||
('blacklist', 'blacklist-block', 'remove-block', 'removeblock', 'banblock', 'ban-block'): banblocks.ban_block,
|
||||
('details', 'info'): onionrstatistics.show_details,
|
||||
('stats', 'statistics'): onionrstatistics.show_stats,
|
||||
('version',): version.version,
|
||||
('start', 'daemon'): daemonlaunch.start,
|
||||
('stop', 'kill'): daemonlaunch.kill_daemon,
|
||||
('restart',): restartonionr.restart,
|
||||
('add-address', 'addaddress', 'addadder'): keyadders.add_address,
|
||||
('openhome', 'gui', 'openweb', 'open-home', 'open-web'): openwebinterface.open_home,
|
||||
('get-url', 'url', 'get-web'): openwebinterface.get_url,
|
||||
('addhtml', 'add-html'): filecommands.add_html,
|
||||
('addsite', 'add-site', 'update-site', 'updatesite'): sitecreator.create_multipage_site,
|
||||
('addfile', 'add-file'): filecommands.add_file,
|
||||
('get-file', 'getfile'): filecommands.get_file,
|
||||
('export-block', 'exportblock'): exportblocks.export_block,
|
||||
('importblocks', 'import-blocks', 'import-block'): importnewblocks.import_new_blocks,
|
||||
('addid', 'add-id'): pubkeymanager.add_ID,
|
||||
('changeid', 'change-id'): pubkeymanager.change_ID,
|
||||
('add-vanity', 'addvanity'): pubkeymanager.add_vanity,
|
||||
('resettor', 'reset-tor'): resettor.reset_tor,
|
||||
('resetplugins', 'reset-plugins'): resetplugins.reset,
|
||||
('reset-tor-node-transport',): resettor.reset_tor_key_pair,
|
||||
('soft-reset', 'softreset'): softreset.soft_reset,
|
||||
('runtime-test', 'runtimetest'): runtimetestcmd.do_runtime_test,
|
||||
('makemotd', 'make-motd'): motdcreator.motd_creator
|
||||
|
||||
}
|
||||
return args
|
||||
|
||||
def get_help(arg: str) -> str:
|
||||
"""Returns the help info string from a given command"""
|
||||
arguments = get_arguments()
|
||||
# Iterate the command alias tuples
|
||||
for argument in arguments:
|
||||
# Return the help message if its found in a command alias tuple
|
||||
if arg in argument: return arguments[argument].onionr_help
|
||||
raise KeyError
|
||||
|
||||
def get_func(argument: str) -> Callable:
|
||||
"""Returns the function for a given command argument"""
|
||||
argument = argument.lower()
|
||||
args = get_arguments()
|
||||
|
||||
for arg in args.keys(): # Iterate command alias sets
|
||||
if argument in arg: # If our argument is in the current alias set, return the command function
|
||||
return args[arg]
|
||||
raise onionrexceptions.NotFound
|
15
src/onionrcommands/parser/recommend.py
Normal file
15
src/onionrcommands/parser/recommend.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
import sys
|
||||
from difflib import SequenceMatcher
|
||||
import logger
|
||||
from . import arguments
|
||||
|
||||
def recommend(print_default: bool = True):
|
||||
tried = sys.argv[1]
|
||||
args = arguments.get_arguments()
|
||||
print_message = 'Command not found:'
|
||||
for key in args.keys():
|
||||
for word in key:
|
||||
if SequenceMatcher(None, tried, word).ratio() >= 0.75:
|
||||
logger.warn('%s "%s", did you mean "%s"?' % (print_message, tried, word), terminal=True)
|
||||
return
|
||||
if print_default: logger.error('%s "%s"' % (print_message, tried), terminal=True)
|
119
src/onionrcommands/pubkeymanager.py
Executable file
119
src/onionrcommands/pubkeymanager.py
Executable file
|
@ -0,0 +1,119 @@
|
|||
'''
|
||||
Onionr - Private P2P Communication
|
||||
|
||||
This module defines user ID-related CLI commands
|
||||
'''
|
||||
'''
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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 sys, getpass
|
||||
|
||||
import unpaddedbase32
|
||||
import niceware
|
||||
|
||||
import vanityonionr
|
||||
import logger, onionrexceptions
|
||||
from onionrutils import stringvalidators, bytesconverter
|
||||
from onionrusers import onionrusers, contactmanager
|
||||
import config
|
||||
from coredb import keydb
|
||||
import keymanager, onionrcrypto
|
||||
from etc import onionrvalues
|
||||
|
||||
DETERMINISTIC_REQUIREMENT = onionrvalues.PASSWORD_LENGTH
|
||||
def add_ID():
|
||||
key_manager = keymanager.KeyManager()
|
||||
try:
|
||||
sys.argv[2]
|
||||
if not sys.argv[2].lower() == 'true': raise ValueError
|
||||
except (IndexError, ValueError) as e:
|
||||
newID = key_manager.addKey()[0]
|
||||
else:
|
||||
logger.warn('Deterministic keys require random and long passphrases.', terminal=True)
|
||||
logger.warn('If a good passphrase is not used, your key can be easily stolen.', terminal=True)
|
||||
logger.warn('You should use a series of hard to guess words, see this for reference: https://www.xkcd.com/936/', terminal=True)
|
||||
try:
|
||||
pass1 = getpass.getpass(prompt='Enter at least %s characters: ' % (DETERMINISTIC_REQUIREMENT,))
|
||||
pass2 = getpass.getpass(prompt='Confirm entry: ')
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(42)
|
||||
if onionrcrypto.cryptoutils.safe_compare(pass1, pass2):
|
||||
try:
|
||||
logger.info('Generating deterministic key. This can take a while.', terminal=True)
|
||||
newID, privKey = onionrcrypto.generate_deterministic(pass1)
|
||||
except onionrexceptions.PasswordStrengthError:
|
||||
logger.error('Passphrase must use at least %s characters.' % (DETERMINISTIC_REQUIREMENT,), terminal=True)
|
||||
sys.exit(1)
|
||||
else:
|
||||
logger.error('Passwords do not match.', terminal=True)
|
||||
sys.exit(1)
|
||||
try:
|
||||
key_manager.addKey(pubKey=newID,
|
||||
privKey=privKey)
|
||||
except ValueError:
|
||||
logger.error('That ID is already available, you can change to it with the change-id command.', terminal=True)
|
||||
return
|
||||
logger.info('Added ID: %s' % (bytesconverter.bytes_to_str(newID),), terminal=True)
|
||||
|
||||
add_ID.onionr_help = "If the first argument is true, Onionr will show a deterministic generation prompt. Otherwise it will generate & save a new random key pair."
|
||||
|
||||
def change_ID():
|
||||
key_manager = keymanager.KeyManager()
|
||||
try:
|
||||
key = sys.argv[2]
|
||||
key = unpaddedbase32.repad(key.encode()).decode()
|
||||
except IndexError:
|
||||
logger.warn('Specify pubkey to use', terminal=True)
|
||||
else:
|
||||
if stringvalidators.validate_pub_key(key):
|
||||
key_list = key_manager.getPubkeyList()
|
||||
if key in key_list or key.replace('=', '') in key_list:
|
||||
config.set('general.public_key', key)
|
||||
config.save()
|
||||
logger.info('Set active key to: %s' % (key,), terminal=True)
|
||||
logger.info('Restart Onionr if it is running.', terminal=True)
|
||||
else:
|
||||
logger.warn('That key does not exist', terminal=True)
|
||||
else:
|
||||
logger.warn('Invalid key %s' % (key,), terminal=True)
|
||||
|
||||
change_ID.onionr_help = "<pubkey>: Switches Onionr to use a different user ID key. You should immediately restart Onionr if it is running."
|
||||
|
||||
def add_vanity():
|
||||
key_manager = keymanager.KeyManager()
|
||||
tell = lambda tell: logger.info(tell, terminal=True)
|
||||
words = ''
|
||||
length = len(sys.argv) - 2
|
||||
if length == 0: return
|
||||
for i in range(2, len(sys.argv)):
|
||||
words += ' '
|
||||
words += sys.argv[i]
|
||||
try:
|
||||
if length == 1:
|
||||
tell('Finding vanity, this should only take a few moments.')
|
||||
else:
|
||||
tell('Finding vanity, this will probably take a really long time.')
|
||||
try:
|
||||
vanity = vanityonionr.find_multiprocess(words)
|
||||
except ValueError:
|
||||
logger.warn('Vanity words must be valid english bip39', terminal=True)
|
||||
else:
|
||||
b32_pub = unpaddedbase32.b32encode(vanity[0])
|
||||
tell('Found vanity address:\n' + niceware.bytes_to_passphrase(vanity[0]))
|
||||
tell('Base32 Public key: %s' % (b32_pub.decode(),))
|
||||
key_manager.addKey(b32_pub, unpaddedbase32.b32encode(vanity[1]))
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
add_vanity.onionr_help = "<space separated words> - Generates and stores an Onionr vanity address (see https://github.com/moreati/python-niceware/blob/master/niceware/wordlist.py)"
|
37
src/onionrcommands/resetplugins.py
Normal file
37
src/onionrcommands/resetplugins.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
'''
|
||||
Onionr - Private P2P Communication
|
||||
|
||||
Reset default plugins from source
|
||||
'''
|
||||
'''
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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 shutil
|
||||
|
||||
from utils import identifyhome
|
||||
from onionrsetup import setup_default_plugins
|
||||
import logger
|
||||
|
||||
def reset():
|
||||
"""Reinstalls Onionr default plugins"""
|
||||
home = identifyhome.identify_home()
|
||||
plugin_dir = home + '/plugins/'
|
||||
if not os.path.exists(home): return
|
||||
if os.path.exists(plugin_dir): shutil.rmtree(plugin_dir)
|
||||
|
||||
setup_default_plugins()
|
||||
logger.info('Default plugins have been reset.', terminal=True)
|
||||
|
||||
reset.onionr_help = "reinstalls default Onionr plugins (e.g. mail). Should be done after git pulls or plugin modification."
|
42
src/onionrcommands/resettor.py
Executable file
42
src/onionrcommands/resettor.py
Executable file
|
@ -0,0 +1,42 @@
|
|||
'''
|
||||
Onionr - Private P2P Communication
|
||||
|
||||
Command to delete the Tor data directory if its safe to do so
|
||||
'''
|
||||
'''
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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, shutil
|
||||
import logger
|
||||
from onionrutils import localcommand
|
||||
from utils import identifyhome
|
||||
|
||||
def __delete(directory):
|
||||
tor_dir = '%s/%s/' % (identifyhome.identify_home(), directory)
|
||||
if os.path.exists(tor_dir):
|
||||
if localcommand.local_command('/ping') == 'pong!':
|
||||
logger.warn('Cannot delete Tor data while Onionr is running', terminal=True)
|
||||
else:
|
||||
shutil.rmtree(tor_dir)
|
||||
logger.info('Tor reset', terminal=True)
|
||||
|
||||
def reset_tor():
|
||||
__delete('tordata')
|
||||
|
||||
reset_tor.onionr_help = "Deletes Onionr's Tor data directory. Only do this as a last resort if you have serious Tor issues."
|
||||
|
||||
def reset_tor_key_pair():
|
||||
__delete('hs')
|
||||
|
||||
reset_tor_key_pair.onionr_help = "Delete's your Tor node address permanently. Note that through fingerprinting attackers may be able to know that your new generated node address belongs to the same node as the deleted one."
|
56
src/onionrcommands/restartonionr.py
Normal file
56
src/onionrcommands/restartonionr.py
Normal file
|
@ -0,0 +1,56 @@
|
|||
"""
|
||||
Onionr - Private P2P Communication
|
||||
|
||||
Command to restart Onionr
|
||||
"""
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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 time
|
||||
import os
|
||||
import subprocess
|
||||
import platform
|
||||
|
||||
from etc import onionrvalues
|
||||
from etc import cleanup
|
||||
from onionrutils import localcommand
|
||||
import logger
|
||||
import filepaths
|
||||
|
||||
from . import daemonlaunch
|
||||
|
||||
SCRIPT_NAME = os.path.dirname(os.path.realpath(__file__)) + f'/../../{onionrvalues.SCRIPT_NAME}'
|
||||
|
||||
def restart():
|
||||
logger.info('Restarting Onionr', terminal=True)
|
||||
|
||||
# On platforms where we can, fork out to prevent locking
|
||||
try:
|
||||
pid = os.fork()
|
||||
if pid != 0: return
|
||||
except (AttributeError, OSError) as e:
|
||||
if platform.platform() != 'Windows':
|
||||
logger.warn('Could not fork on restart')
|
||||
|
||||
daemonlaunch.kill_daemon()
|
||||
while localcommand.local_command('ping', maxWait=8) == 'pong!':
|
||||
time.sleep(0.3)
|
||||
time.sleep(15)
|
||||
while os.path.exists(filepaths.private_API_host_file) or os.path.exists(filepaths.daemon_mark_file):
|
||||
time.sleep(1)
|
||||
|
||||
cleanup.delete_run_files()
|
||||
subprocess.Popen([SCRIPT_NAME, 'start'])
|
||||
|
||||
restart.onionr_help = 'Gracefully restart Onionr'
|
6
src/onionrcommands/runtimetestcmd.py
Normal file
6
src/onionrcommands/runtimetestcmd.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from coredb import daemonqueue
|
||||
|
||||
def do_runtime_test():
|
||||
daemonqueue.daemon_queue_add("runtimeTest")
|
||||
|
||||
do_runtime_test.onionr_help = "If Onionr is running, initialize run time tests (check logs)"
|
38
src/onionrcommands/sitecreator.py
Normal file
38
src/onionrcommands/sitecreator.py
Normal file
|
@ -0,0 +1,38 @@
|
|||
import sys
|
||||
import getpass
|
||||
|
||||
from httpapi import onionrsitesapi
|
||||
import onionrexceptions
|
||||
import logger
|
||||
from etc import onionrvalues
|
||||
|
||||
def create_multipage_site():
|
||||
error_encountered = False
|
||||
try:
|
||||
directory = sys.argv[2]
|
||||
except IndexError:
|
||||
directory = '.'
|
||||
try:
|
||||
passphrase = sys.argv[3]
|
||||
except IndexError:
|
||||
logger.warn('''It is critical that this passphrase is long.
|
||||
If you want to update your site later you must remember the passphrase.''', terminal=True)
|
||||
passphrase = getpass.getpass(f'Please enter a site passphrase of at least {onionrvalues.PASSWORD_LENGTH} characters.')
|
||||
confirm = getpass.getpass('Confirm passphrase:')
|
||||
if passphrase != confirm:
|
||||
logger.error('Passphrases do not match', terminal=True)
|
||||
error_encountered = True
|
||||
|
||||
if len(passphrase) < onionrvalues.PASSWORD_LENGTH:
|
||||
error_encountered = True
|
||||
logger.error(f'Passphrase must be at least {onionrvalues.PASSWORD_LENGTH} characters.', terminal=True)
|
||||
|
||||
if error_encountered:
|
||||
sys.exit(1)
|
||||
|
||||
results = onionrsitesapi.sitefiles.create_site(passphrase, directory=directory)
|
||||
results = (results[0].replace('=', ''), results[1])
|
||||
logger.info(f'Site address {results[0]}', terminal=True)
|
||||
logger.info(f'Block for this version {results[1]}', terminal=True)
|
||||
|
||||
create_multipage_site.onionr_help = "[directory path (default relative)] - packages a whole directory and makes it available as an Onionr site."
|
46
src/onionrcommands/softreset.py
Normal file
46
src/onionrcommands/softreset.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
"""
|
||||
Onionr - Private P2P Communication
|
||||
|
||||
Command to soft-reset Onionr (deletes blocks)
|
||||
"""
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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 shutil
|
||||
|
||||
from onionrutils import localcommand
|
||||
from coredb import dbfiles
|
||||
import filepaths
|
||||
from onionrplugins import onionrevents
|
||||
import logger
|
||||
|
||||
def _ignore_not_found_delete(path):
|
||||
try:
|
||||
os.remove(path)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
def soft_reset():
|
||||
if localcommand.local_command('/ping') == 'pong!':
|
||||
logger.warn('Cannot soft reset while Onionr is running', terminal=True)
|
||||
return
|
||||
path = filepaths.block_data_location
|
||||
shutil.rmtree(path)
|
||||
_ignore_not_found_delete(dbfiles.block_meta_db)
|
||||
_ignore_not_found_delete(filepaths.upload_list)
|
||||
onionrevents.event('softreset')
|
||||
logger.info("Soft reset Onionr", terminal=True)
|
||||
|
||||
soft_reset.onionr_help = "Deletes Onionr blocks and their associated metadata, except for any exported block files. Does NOT delete data on other nodes in the network."
|
21
src/onionrcommands/version.py
Normal file
21
src/onionrcommands/version.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
import platform
|
||||
from utils import identifyhome
|
||||
from etc import onionrvalues
|
||||
import logger
|
||||
def version(verbosity = 5, function = logger.info):
|
||||
'''
|
||||
Displays the Onionr version
|
||||
'''
|
||||
|
||||
function('Onionr v%s (%s) (API v%s)' % (onionrvalues.ONIONR_VERSION, platform.machine(), onionrvalues.API_VERSION), terminal=True)
|
||||
if verbosity >= 1:
|
||||
function(onionrvalues.ONIONR_TAGLINE, terminal=True)
|
||||
if verbosity >= 2:
|
||||
pf = platform.platform()
|
||||
release = platform.release()
|
||||
python_imp = platform.python_implementation()
|
||||
python_version = platform.python_version()
|
||||
function(f'{python_imp} {python_version} on {pf} {release}', terminal=True)
|
||||
function('Onionr data dir: %s' % identifyhome.identify_home(), terminal=True)
|
||||
|
||||
version.onionr_help = 'Shows environment details including Onionr version & data directory, OS and Python version'
|
Loading…
Add table
Add a link
Reference in a new issue