Removed crappy logger and replaced it with a sane built in logging logger

This commit is contained in:
Kevin F 2022-09-27 17:21:00 +00:00
parent 2eea681e98
commit e9efffff34
61 changed files with 307 additions and 851 deletions

View File

@ -1,12 +0,0 @@
# Incomplete List of Contributors
Onionr is created by a team of hard working volunteers.
In no order of importance, these people make Onionr happen:
* [Beardog (Kevin Froman)](https://www.chaoswebs.net/) - Project founder, owner and core developer
* [InvisaMage](https://invisamage.com/) - Web UI Bulma design
* [Arinerron](https://arinerron.com/) - Logger and config modules, testing and other contributions
* [Anhar Ismail](https://github.com/anharismail) - Created Onionr's logo
+ Other contributors and testers

View File

@ -64,6 +64,8 @@ def sigusr_stacktrace(signum, frame):
signal.signal(signal.SIGUSR1, sigusr_stacktrace)
# Importing initailzes logging
from logger import log as logging
ran_as_script = False
if __name__ == "__main__": ran_as_script = True

View File

@ -2,7 +2,7 @@ from typing import Set
from onionrblocks import Block
import logger
from logger import log as logging
from .deleteblock import delete_block
from .getblocks import get_blocks_after_timestamp
@ -18,7 +18,7 @@ def clean_block_database():
Block(block.id, block.raw, auto_verify=True)
except ValueError: # block expired
remove_set.add(block)
if len(remove_set):
logger.info(f"Cleaning {len(remove_set)} blocks", terminal=True)
logging.info(f"Cleaning {len(remove_set)} blocks")
[i for i in map(delete_block, remove_set)]

View File

@ -6,7 +6,7 @@ import os
from json import JSONDecodeError
import ujson as json
import logger
from logger import log as logging
import filepaths
"""
@ -106,7 +106,7 @@ def save():
with open(get_config_file(), 'w', encoding="utf8") as configfile:
json.dump(get_config(), configfile, indent=2)
except JSONDecodeError:
logger.warn('Failed to write to configuration file.')
logging.warn('Failed to write to configuration file.')
def reload():
@ -117,7 +117,7 @@ def reload():
set_config(json.loads(configfile.read()))
except (FileNotFoundError, JSONDecodeError) as e:
pass
#logger.debug('Failed to parse configuration file.')
#logging.debug('Failed to parse configuration file.')
def get_config():

View File

@ -1,6 +1,7 @@
import threading
from time import sleep
from typing import TYPE_CHECKING, Set, Tuple
from logger import log as logging
if TYPE_CHECKING:
from ordered_set import OrderedSet
@ -11,7 +12,6 @@ if TYPE_CHECKING:
from onionrthreads import add_onionr_thread
import onionrplugins
import logger
from .connectpeer import connect_peer
from .client import start_gossip_client
@ -56,4 +56,4 @@ def start_gossip_threads():
sleep(60)
if len(gossip_peer_set):
return
logger.error("Could not connect to any peers :(", terminal=True)
logging.error("Could not connect to any peers :(")

View File

@ -21,7 +21,7 @@ if TYPE_CHECKING:
from ..peer import Peer
from ordered_set import OrderedSet
import logger
from logger import log as logging
import config
import onionrplugins
from ..commands import GossipCommands
@ -61,20 +61,20 @@ def block_queue_processing():
while not len(gossip_peer_set):
sleep(1)
if dandelion_phase.remaining_time() <= 15:
#logger.debug("Sleeping", terminal=True)
#logging.debug("Sleeping")
sleep(dandelion_phase.remaining_time())
if dandelion_phase.is_stem_phase() and config.get('security.dandelion.enabled', True):
logger.debug("Entering stem phase", terminal=True)
logging.debug("Entering stem phase")
try:
# Stem out blocks for (roughly) remaining epoch time
asyncio.run(stem_out(dandelion_phase))
except TimeoutError:
pass
except Exception:
logger.error(traceback.format_exc(), terminal=True)
logging.error(traceback.format_exc())
pass
else:
#logger.debug("Entering fluff phase", terminal=True)
#logging.debug("Entering fluff phase")
# Add block to primary block db, where the diffuser can read it
sleep(0.1)
store_blocks(dandelion_phase)

View File

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING:
from .. import Peer
import logger
from logger import log as logging
import onionrplugins
from ..commands import GossipCommands, command_to_byte
@ -28,7 +28,7 @@ def do_announce():
sock.sendall(command_to_byte(GossipCommands.ANNOUNCE))
sock.sendall(our_transport_address)
if int.from_bytes(sock.recv(1), 'big') != 1:
logger.warn(
logging.warn(
f"Could not announce with {announce_peer.transport_address}")
sock.close()

View File

@ -11,7 +11,7 @@ from ordered_set import OrderedSet
import config
from onionrthreads import add_delayed_thread
from blockdb import add_block_to_db
import logger
from logger import log as logging
from ...constants import BLACKHOLE_EVADE_TIMER_SECS, OUTBOUND_DANDELION_EDGES
from ...commands import GossipCommands, command_to_byte
@ -45,9 +45,9 @@ async def _setup_edge(
try:
s = peer.get_socket(12)
except TimeoutError:
logger.debug(f"{peer.transport_address} timed out when trying stemout")
logging.debug(f"{peer.transport_address} timed out when trying stemout")
except Exception:
logger.debug(traceback.format_exc())
logging.debug(traceback.format_exc())
return
try:
@ -56,18 +56,18 @@ async def _setup_edge(
if s.recv(1) == dandelion.StemAcceptResult.DENY:
raise StemConnectionDenied
except TimeoutError:
logger.debug(
"Peer timed out when establishing stem connection", terminal=True)
logger.debug(traceback.format_exc())
logging.debug(
"Peer timed out when establishing stem connection")
logging.debug(traceback.format_exc())
except StemConnectionDenied:
logger.debug(
logging.debug(
"Stem connection denied (peer has too many) " +
f"{peer.transport_address}")
logger.debug(traceback.format_exc())
logging.debug(traceback.format_exc())
except Exception:
logger.warn(
logging.warn(
"Error asking peer to establish stem connection" +
traceback.format_exc(), terminal=True)
traceback.format_exc())
else:
# Return peer socket if it is in stem reception mode successfully
return s
@ -113,10 +113,10 @@ async def stem_out(d_phase: 'DandelionPhase'):
await _setup_edge(gossip_peer_set, tried_edges))
except NotEnoughEdges:
# No possible edges at this point (edges < OUTBOUND_DANDELION_EDGE)
#logger.debug(
#logging.debug(
# "Making too few edges for stemout " +
# "this is bad for anonymity if frequent.",
# terminal=True)
# )
if strict_dandelion:
not_enough_edges = True
else:
@ -133,10 +133,10 @@ async def stem_out(d_phase: 'DandelionPhase'):
else:
# Ran out of time for stem phase
if not d_phase.is_stem_phase() or d_phase.remaining_time() < 5:
logger.error(
logging.error(
"Did not stem out any blocks in time, " +
"if this happens regularly you may be under attack",
terminal=False)
)
for s in peer_sockets:
if s:
s.close()
@ -155,7 +155,7 @@ async def stem_out(d_phase: 'DandelionPhase'):
except Empty:
pass
except Exception:
logger.warn(traceback.format_exc())
logging.warn(traceback.format_exc())
else:
# stream routine exited early
pass

View File

@ -4,7 +4,7 @@ from queue import Empty
from typing import TYPE_CHECKING
import logger
from logger import log as logging
from ...constants import BLOCK_ID_SIZE, BLOCK_MAX_SIZE, BLOCK_SIZE_LEN
if TYPE_CHECKING:
@ -22,7 +22,7 @@ async def do_stem_stream(
remaining_time = d_phase.remaining_time()
my_phase_id = d_phase.phase_id
while remaining_time > 1 and my_phase_id == d_phase.phase_id:
# Primary client component that communicate's with gossip.server.acceptstem
remaining_time = d_phase.remaining_time()
@ -35,7 +35,7 @@ async def do_stem_stream(
await sleep(1)
else:
break
logger.info("Sending block over dandelion++", terminal=True)
logging.info("Sending block over dandelion++")
block_size = str(len(bl.raw)).zfill(BLOCK_SIZE_LEN)
def _send_it():

View File

@ -6,7 +6,7 @@ if TYPE_CHECKING:
from socket import socket
from onionrplugins import onionrevents
import logger
from logger import log as logging
from socks import GeneralProxyError
@ -23,9 +23,9 @@ def _do_ask_peer(peer):
try:
_ask_peer(peer)
except TimeoutError:
logger.debug("Timed out when asking for new peers")
logging.debug("Timed out when asking for new peers")
except Exception:
logger.error(format_exc(), terminal=True)
logging.error(format_exc())
def _ask_peer(peer):
s: 'socket' = peer.get_socket(12)
@ -46,14 +46,14 @@ def _ask_peer(peer):
'address': peer,
'callback': connectpeer.connect_peer
}
#logger.info("Got new peer from exchange " + peer.decode('utf-8'), terminal=True)
#logging.info("Got new peer from exchange " + peer.decode('utf-8'))
onionrevents.event('announce_rec', data=connect_data, threaded=True)
s.close()
def get_new_peers():
if not len(gossip_peer_set):
logger.debug("Peer set empty, cannot get new peers")
logging.debug("Peer set empty, cannot get new peers")
return
# Deep copy the peer list

View File

@ -22,7 +22,7 @@ if TYPE_CHECKING:
from ordered_set import OrderedSet
import logger
from logger import log as logging
import onionrblocks
from ...peerset import gossip_peer_set
@ -71,7 +71,7 @@ def stream_from_peers():
need_socket_lock.release()
return
except Exception:
logger.warn(traceback.format_exc(), terminal=True)
logging.warn(traceback.format_exc())
need_socket_lock.release()
return
try:
@ -83,7 +83,7 @@ def stream_from_peers():
while stream_times >= stream_counter:
stream_counter += 1
#logger.debug("Reading block of id in stream with " + peer.transport_address, terminal=True)
#logging.debug("Reading block of id in stream with " + peer.transport_address)
sock.settimeout(5)
block_id = sock.recv(BLOCK_ID_SIZE)
if blockdb.has_block(block_id):
@ -91,12 +91,12 @@ def stream_from_peers():
continue
sock.sendall(int(1).to_bytes(1, 'big'))
#logger.debug("Reading block size in stream", terminal=True)
#logging.debug("Reading block size in stream")
sock.settimeout(5)
block_size = int(sock.recv(BLOCK_SIZE_LEN))
if block_size > BLOCK_MAX_SIZE or block_size <= 0:
logger.warn(
logging.warn(
f"Peer {peer.transport_address} " +
"reported block size out of range")
break
@ -104,9 +104,9 @@ def stream_from_peers():
sock.settimeout(5)
block_data = sock.recv(block_size)
#logger.debug(
#logging.debug(
# "We got a block from stream, assuming it is valid",
# terminal=True)
# )
try:
blockdb.add_block_to_db(
onionrblocks.Block(
@ -120,10 +120,10 @@ def stream_from_peers():
sock.sendall(int(1).to_bytes(1, 'big'))
except (BrokenPipeError, TimeoutError, ConnectionError) as e:
pass
#logger.debug(f"{e} when streaming from peers", terminal=True)
#logger.debug(traceback.format_exc())
#logging.debug(f"{e} when streaming from peers")
#logging.debug(traceback.format_exc())
except Exception:
logger.warn(traceback.format_exc(), terminal=True)
logging.warn(traceback.format_exc())
finally:
sock.close()
need_socket_lock.release()

View File

@ -2,7 +2,7 @@ import traceback
from gossip.commands import GossipCommands, command_to_byte
from .peerset import gossip_peer_set
import logger
from logger import log as logging
def connect_peer(peer):
@ -11,12 +11,12 @@ def connect_peer(peer):
try:
s = peer.get_socket(120)
except Exception:
logger.warn(f"Could not connect to {peer.transport_address}")
logger.warn(traceback.format_exc())
logging.warn(f"Could not connect to {peer.transport_address}")
logging.warn(traceback.format_exc())
else:
with s:
s.sendall(command_to_byte(GossipCommands.PING))
if s.recv(4).decode('utf-8') == 'PONG':
gossip_peer_set.add(peer)
logger.info(f"connected to {peer.transport_address}", terminal=True)
logging.info(f"connected to {peer.transport_address}")

View File

@ -12,7 +12,7 @@ from gossip import constants
from ..connectpeer import connect_peer
from onionrplugins import onionrevents
import logger
from logger import log as logging
if TYPE_CHECKING:
from onionrblocks import Block
@ -88,9 +88,9 @@ def gossip_server():
try:
await diffuse_blocks(reader, writer)
except Exception:
logger.warn(
logging.warn(
f"Err streaming blocks\n{traceback.format_exc()}",
terminal=True)
)
case GossipCommands.PUT_BLOCKS:
# Pick block queue & append stemmed blocks to it
try:
@ -99,18 +99,18 @@ def gossip_server():
inbound_dandelion_edge_count)
except asyncio.exceptions.TimeoutError:
pass
logger.debug(
logging.debug(
"Inbound edge timed out when steming blocks to us",
terminal=True)
)
except asyncio.exceptions.IncompleteReadError:
pass
logger.debug(
logging.debug(
"Inbound edge timed out (Incomplete Read) when steming blocks to us",
terminal=True)
)
except Exception:
logger.warn(
logging.warn(
f"Err accepting stem blocks\n{traceback.format_exc()}",
terminal=True)
)
# Subtract dandelion edge, make sure >=0
inbound_dandelion_edge_count[0] = \
max(inbound_dandelion_edge_count[0] - 1, 0)

View File

@ -5,7 +5,7 @@ from asyncio import wait_for
from onionrblocks import Block
import logger
from logger import log as logging
from ..dandelion import StemAcceptResult
from ..constants import BLOCK_ID_SIZE, BLOCK_SIZE_LEN, BLOCK_MAX_SIZE
from ..constants import MAX_INBOUND_DANDELION_EDGE, MAX_STEM_BLOCKS_PER_STREAM
@ -35,13 +35,13 @@ async def accept_stem_blocks(
for _ in range(MAX_STEM_BLOCKS_PER_STREAM):
read_routine = reader.readexactly(BLOCK_ID_SIZE)
#logger.debug(f"Reading block id in stem server", terminal=True)
#logging.debug(f"Reading block id in stem server")
block_id = await wait_for(read_routine, base_wait_timeout)
block_id = block_id.decode('utf-8')
if not block_id:
break
#logger.debug(f"Reading block size in stem server", terminal=True)
#logging.debug(f"Reading block size in stem server")
block_size = (await wait_for(
reader.readexactly(BLOCK_SIZE_LEN),
base_wait_timeout)).decode('utf-8')
@ -54,14 +54,14 @@ async def accept_stem_blocks(
if block_size > BLOCK_MAX_SIZE:
raise ValueError("Max block size")
#logger.debug(f"Reading block of size {block_size} in stem server", terminal=True)
#logging.debug(f"Reading block of size {block_size} in stem server")
raw_block: bytes = await wait_for(
reader.readexactly(block_size), base_wait_timeout * 6)
if not raw_block:
break
logger.debug("Got a stem block, put into queue", terminal=True)
logging.debug("Got a stem block, put into queue")
block_queue_to_use.put(
Block(block_id, raw_block, auto_verify=True)
)

View File

@ -19,7 +19,7 @@ if TYPE_CHECKING:
from ..constants import BLOCK_MAX_SIZE, BLOCK_SIZE_LEN
from ..constants import BLOCK_STREAM_OFFSET_DIGITS
import logger
from logger import log as logging
import blockdb
from blockdb import get_blocks_after_timestamp, block_storage_observers
"""
@ -103,5 +103,5 @@ async def diffuse_blocks(reader: 'StreamReader', writer: 'StreamWriter'):
except ConnectionResetError:
pass
except Exception:
logger.warn(traceback.format_exc(), terminal=True)
logging.warn(traceback.format_exc())

View File

@ -1,71 +1,91 @@
'''
Onionr - Private P2P Communication
"""
Onionr - Private P2P Communication
This file handles all operations involving logging
'''
'''
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.
We use built in logging but with a custom formatter for colors and such
"""
import logging
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.
from filepaths import log_file
"""
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.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
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.
import sys, traceback
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 . import colors, readline, log, raw, confirm, colors, settings
colors = colors.Colors
readline = readline.readline
log = log.log
raw = raw.raw
confirm = confirm.confirm
# credit: https://stackoverflow.com/a/384076
# license: https://creativecommons.org/licenses/by-sa/4.0/
class ConsoleFormatter(logging.Formatter):
# debug: when there is info that could be useful for debugging purposes only
def debug(data: str, error = None, timestamp = True, prompt = True, terminal = False, level = settings.LEVEL_DEBUG):
if settings.get_level() <= level:
log('/', data, timestamp = timestamp, prompt = prompt, terminal = terminal)
if not error is None:
debug('Error: ' + str(error) + parse_error())
grey = "\x1b[38;20m"
green = "\x1b[38;5;82m"
yellow = "\x1b[33;20m"
red = "\x1b[31;20m"
bold_red = "\x1b[31;1m"
reset = "\x1b[0m"
format_default = "%(levelname)s - %(message)s (%(filename)s:%(lineno)d)"
format_info = "%(message)s - (%(filename)s:%(lineno)d)"
# info: when there is something to notify the user of, such as the success of a process
def info(data: str, timestamp = False, prompt = True, terminal = False, level = settings.LEVEL_INFO):
if settings.get_level() <= level:
log('+', data, colors.fg.green, timestamp = timestamp, prompt = prompt, terminal = terminal)
FORMATS = {
logging.DEBUG: grey + format_default + reset,
logging.INFO: green + format_info + reset,
logging.WARNING: yellow + format_default + reset,
logging.ERROR: red + format_default + reset,
logging.CRITICAL: bold_red + format_default + reset
}
# warn: when there is a potential for something bad to happen
def warn(data: str, error = None, timestamp = True, prompt = True, terminal = False, level = settings.LEVEL_WARN):
if not error is None:
debug('Error: ' + str(error) + parse_error())
if settings.get_level() <= level:
log('!', data, colors.fg.orange, timestamp = timestamp, prompt = prompt, terminal = terminal)
def format(self, record):
log_fmt = self.FORMATS.get(record.levelno)
formatter = logging.Formatter(log_fmt)
return formatter.format(record)
# error: when only one function, module, or process of the program encountered a problem and must stop
def error(data: str, error = None, timestamp = True, prompt = True, terminal = False, level = settings.LEVEL_ERROR):
if settings.get_level() <= level:
log('-', data, colors.fg.red, timestamp = timestamp, fd = sys.stderr, prompt = prompt, terminal = terminal)
if not error is None:
debug('Error: ' + str(error) + parse_error())
class FileFormatter(logging.Formatter):
# fatal: when the something so bad has happened that the program must stop
def fatal(data: str, error = None, timestamp=True, prompt = True, terminal = False, level = settings.LEVEL_FATAL):
if not error is None:
debug('Error: ' + str(error) + parse_error(), terminal = terminal)
if settings.get_level() <= level:
log('#', data, colors.bg.red + colors.fg.green + colors.bold, timestamp = timestamp, fd = sys.stderr, prompt = prompt, terminal = terminal)
# returns a formatted error message
def parse_error():
details = traceback.extract_tb(sys.exc_info()[2])
output = ''
format_default = "%(levelname)s - %(message)s (%(filename)s:%(lineno)d)"
format_info = "%(message)s - (%(filename)s:%(lineno)d)"
for line in details:
output += '\n ... module %s in %s:%i' % (line[2], line[0], line[1])
FORMATS = {
logging.DEBUG: format_default,
logging.INFO: format_info,
logging.WARNING: format_default,
logging.ERROR: format_default,
logging.CRITICAL: format_default
}
return output
def format(self, record):
log_fmt = self.FORMATS.get(record.levelno)
formatter = logging.Formatter(log_fmt)
return formatter.format(record)
#logging.basicConfig(level=logging.ERROR, format='%(message)s ')
log = logging.getLogger('onionr')
log.setLevel(logging.INFO)
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
ch.setFormatter(ConsoleFormatter())
def enable_file_logging():
fh = logging.FileHandler(log_file)
fh.setLevel(logging.INFO)
fh.setFormatter(FileFormatter())
log.addHandler(fh)
def disable_console_logging():
log.removeHandler(ch)
def enable_console_logging():
log.addHandler(ch)
enable_console_logging()

View File

@ -1,60 +0,0 @@
'''
Onionr - Private P2P Communication
class to access ANSI control codes
'''
'''
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 re
class Colors:
'''
This class allows you to set the color if ANSI codes are supported
'''
reset='\033[0m'
bold='\033[01m'
disable='\033[02m'
underline='\033[04m'
reverse='\033[07m'
strikethrough='\033[09m'
invisible='\033[08m'
italics='\033[3m'
class fg:
black='\033[30m'
red='\033[31m'
green='\033[32m'
orange='\033[33m'
blue='\033[34m'
purple='\033[35m'
cyan='\033[36m'
lightgrey='\033[37m'
darkgrey='\033[90m'
lightred='\033[91m'
lightgreen='\033[92m'
yellow='\033[93m'
lightblue='\033[94m'
pink='\033[95m'
lightcyan='\033[96m'
class bg:
black='\033[40m'
red='\033[41m'
green='\033[42m'
orange='\033[43m'
blue='\033[44m'
purple='\033[45m'
cyan='\033[46m'
lightgrey='\033[47m'
@staticmethod
def filter(data):
return re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]').sub('', str(data))

View File

@ -1,54 +0,0 @@
'''
Onionr - Private P2P Communication
confirm y/n cli prompt
'''
'''
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
from . import colors, settings
colors = colors.Colors
def confirm(default = 'y', message = 'Are you sure %s? '):
'''
Displays an "Are you sure" message, returns True for Y and False for N
message: The confirmation message, use %s for (y/n)
default: which to prefer-- y or n
'''
color = colors.fg.green + colors.bold
default = default.lower()
confirm = colors.bold
if default.startswith('y'):
confirm += '(Y/n)'
else:
confirm += '(y/N)'
confirm += colors.reset + color
output = colors.reset + str(color) + '... ' + colors.reset + str(message) + colors.reset
if not get_settings() & settings.USE_ANSI:
output = colors.filter(output)
sys.stdout.write(output.replace('%s', confirm))
inp = input().lower()
if 'y' in inp:
return True
if 'n' in inp:
return False
else:
return default == 'y'

View File

@ -1,38 +0,0 @@
'''
Onionr - Private P2P Communication
god log function
'''
'''
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, time
from . import colors, raw, settings
colors = colors.Colors
def log(prefix, data, color = '', timestamp=True, fd = sys.stdout, prompt = True, terminal = False):
'''
Logs the data
prefix : The prefix to the output
data : The actual data to output
color : The color to output before the data
'''
curTime = ''
if timestamp:
curTime = time.strftime("%m-%d %H:%M:%S") + ' '
output = colors.reset + str(color) + ('[' + colors.bold + str(prefix) + colors.reset + str(color) + '] ' if prompt is True else '') + curTime + str(data) + colors.reset
if not settings.get_settings() & settings.USE_ANSI:
output = colors.filter(output)
raw.raw(output, fd = fd, terminal = terminal)

View File

@ -1,54 +0,0 @@
"""Onionr - Private P2P Communication.
Output raw data to file or terminal
"""
import sys
import os
from . import settings, colors
"""
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/>.
"""
colors = colors.Colors
def raw(data, fd = sys.stdout, terminal = False):
"""
Outputs raw data to console without formatting
"""
if terminal and (settings.get_settings() & settings.OUTPUT_TO_CONSOLE):
try:
ts = fd.write('%s\n' % data)
except OSError:
pass
if settings.get_settings() & settings.OUTPUT_TO_FILE:
fdata = ''
try:
for _ in range(5):
try:
with open(settings._outputfile, 'r') as file:
fdata = file.read()
except UnicodeDecodeError:
pass
else:
break
except FileNotFoundError:
pass
fdata = fdata + '\n' + data
fdata = fdata.split('\n')
if len(fdata) >= settings.MAX_LOG_FILE_LINES:
fdata.pop(0)
fdata = '\n'.join(fdata)
with open(settings._outputfile, 'w') as file:
file.write(fdata)

View File

@ -1,37 +0,0 @@
'''
Onionr - Private P2P Communication
get a line of input from stdin
'''
'''
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
from . import colors, settings
colors = colors.Colors
def readline(message = ''):
'''
Takes in input from the console, not stored in logs
message: The message to display before taking input
'''
color = colors.fg.green + colors.bold
output = colors.reset + str(color) + '... ' + colors.reset + str(message) + colors.reset
if not settings.get_settings() & settings.USE_ANSI:
output = colors.filter(output)
sys.stdout.write(output)
return input()

View File

@ -1,89 +0,0 @@
'''
Onionr - Private P2P Communication
logger settings
'''
'''
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
from utils import identifyhome
import filepaths
data_home = os.environ.get('ONIONR_LOG_DIR', identifyhome.identify_home())
# Use the bitwise operators to merge these settings
USE_ANSI = 0b100
if os.name == 'nt':
USE_ANSI = 0b000
OUTPUT_TO_CONSOLE = 0b010
OUTPUT_TO_FILE = 0b001
LEVEL_DEBUG = 1
LEVEL_INFO = 2
LEVEL_WARN = 3
LEVEL_ERROR = 4
LEVEL_FATAL = 5
LEVEL_IMPORTANT = 6
MAX_LOG_FILE_LINES = 10000
_type = OUTPUT_TO_CONSOLE | USE_ANSI # the default settings for logging
_level = LEVEL_DEBUG # the lowest level to log
# the file to log to
_outputfile = filepaths.log_file
def set_settings(type):
'''
Set the settings for the logger using bitwise operators
'''
global _type
_type = type
def get_settings():
'''
Get settings from the logger
'''
return _type
def set_level(level):
'''
Set the lowest log level to output
'''
global _level
_level = level
def get_level()->int:
'''
Get the lowest log level currently being outputted
'''
return _level
def set_file(outputfile):
'''
Set the file to output to, if enabled
'''
global _outputfile
_outputfile = outputfile
def get_file():
'''
Get the file to output to
'''
return _outputfile

View File

@ -8,13 +8,14 @@ import sys
import platform
import signal
from threading import Thread
from logger import log as logging
from logger import enable_file_logging
import filenuke
import psutil
import config
import logger
from onionrplugins import onionrevents as events
from utils import identifyhome
@ -59,16 +60,19 @@ def delete_run_files():
_safe_remove(filepaths.pid_file)
def _show_info_messages():
version.version(verbosity=5, function=logger.info)
logger.debug('Python version %s' % platform.python_version())
version.version(verbosity=5, function=logging.info)
logging.debug('Python version %s' % platform.python_version())
if onionrvalues.DEVELOPMENT_MODE:
logger.warn('Development mode enabled', timestamp=False, terminal=True)
logging.warn('Development mode enabled')
def daemon():
"""Start Onionr's primary threads for communicator, API server, node, and LAN."""
if config.get('log.file.output', False):
enable_file_logging()
def _handle_sig_term(signum, frame):
sys.exit(0)
@ -83,8 +87,8 @@ def daemon():
security_level = config.get('general.security_level', 1)
_show_info_messages()
logger.info(
f"Onionr daemon is running under pid {os.getpid()}", terminal=True)
logging.info(
f"Onionr daemon is running under pid {os.getpid()}")
events.event('init', threaded=False)
events.event('afterinit', threaded=False)
events.event('daemon_start')
@ -117,33 +121,25 @@ def start(override: bool = False):
Error exit if there is and its not overridden
"""
if os.path.exists(filepaths.lock_file) and not override:
if os.path.exists(filepaths.restarting_indicator):
try:
os.remove(filepaths.restarting_indicator)
except FileNotFoundError:
pass
else:
return
with open(filepaths.lock_file, 'r') as lock_file:
try:
proc = psutil.Process(int(lock_file.read())).name()
except psutil.NoSuchProcess:
proc = ""
if not proc.startswith("python"):
logger.warn(
f"Detected stale run file, deleting {filepaths.lock_file}",
terminal=True)
logging.warn(
f"Detected stale run file, deleting {filepaths.lock_file}")
try:
os.remove(filepaths.lock_file)
except FileNotFoundError:
pass
start(override=True)
return
logger.fatal('Cannot start. Daemon is already running,'
logging.error('Cannot start. Daemon is already running,'
+ ' or it did not exit cleanly.\n'
+ ' (if you are sure that there is not a daemon running,'
+ f' delete {filepaths.lock_file} & try again).',
terminal=True)
)
else:
if not onionrvalues.DEVELOPMENT_MODE:
lock_file = open(filepaths.lock_file, 'w')

View File

@ -6,7 +6,7 @@ import os
from signal import SIGTERM
from filepaths import pid_file
import logger
from logger import log as logging
"""
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
@ -29,9 +29,9 @@ def kill_daemon():
with open(pid_file, 'r') as pid:
os.kill(int(pid.read()), SIGTERM)
except FileNotFoundError:
logger.error("Daemon not running/pid file missing")
logger.warn('Stopping the running daemon, if one exists...', timestamp=False,
terminal=True)
logging.error("Daemon not running/pid file missing")
logging.warn('Stopping the running daemon, if one exists...', timestamp=False,
)
kill_daemon.onionr_help = "Gracefully stops the " # type: ignore

View File

@ -5,11 +5,12 @@ Show nice logo
import os
import config
import logger
from .quotes import QUOTE
from utils.boxprint import bordered
from utils import logoheader
from utils import readstatic
import onionrvalues
"""
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
@ -25,28 +26,34 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def header():
if onionrvalues.DEVELOPMENT_MODE:
return
pink_ansi = '\033[95m'
green_ansi = '\033[92m'
reset_ansi = '\x1b[0m'
logo = readstatic.read_static('header.txt', ret_bin=False)
logo = logo.replace('P', pink_ansi).replace('G', green_ansi).replace('W', reset_ansi)
print(reset_ansi + logo)
def show_logo():
logger.raw('', terminal=True)
try:
terminal_size = os.get_terminal_size().columns
except OSError: # Generally thrown if not in terminal
terminal_size = 120
# print nice header thing :)
if config.get('general.display_header', True):
logoheader.header("")
header()
if terminal_size >= 120:
if QUOTE[1]: # If there is an author to show for the quote
logger.info(
"\u001b[33m\033[F" + bordered(QUOTE[0] + '\n -' + QUOTE[1]),
terminal=True)
print("\u001b[33m\033[F" + bordered(QUOTE[0] + '\n -' + QUOTE[1]))
else:
logger.info(
"\u001b[33m\033[F" + bordered(QUOTE[0]), terminal=True)
print("\u001b[33m\033[F" + bordered(QUOTE[0]))
else:
if QUOTE[1]:
logger.info("\u001b[33m\033[F" + QUOTE[0] + '\n -' + QUOTE[1],
terminal=True)
print("\u001b[33m\033[F" + QUOTE[0] + '\n -' + QUOTE[1])
else:
logger.info("\u001b[33m\033[F" + QUOTE[0], terminal=True)
print("\u001b[33m\033[F" + QUOTE[0])

View File

@ -1,141 +0,0 @@
"""Onionr - Private P2P Communication.
This module defines commands to show stats/details about the local node
"""
import os
import logger
from utils import sizeutils, getconsolewidth, identifyhome
import config
import onionrvalues
from filepaths import lock_file
import psutil
"""
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/>.
"""
def _is_running():
script = onionrvalues.SCRIPT_NAME
if os.path.isfile(lock_file):
for process in psutil.process_iter():
if process.name() == script:
return True
return False
def show_stats():
"""Print/log statistic info about our Onionr install."""
try:
# define stats messages here
home = identifyhome.identify_home()
messages = {
# info about local client
# This line is inaccurate if dev mode is enabled
'Onionr Daemon Status':
((logger.colors.fg.green + 'Online') \
if _is_running() \
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.db')),
'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,
'Enabled Plugins':
str(len(config.get('plugins.enabled', list()))) + ' / ' +
str(len(os.listdir(home + 'plugins/')))
}
# 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: # pylint: disable=W0703
logger.error('Failed to generate statistics table. ' +
str(e), error=e, timestamp=False, terminal=True)
def show_details():
"""Print out details.
node transport address(es)
active user ID
active user ID in mnemonic form
"""
details = {
'Data directory': identifyhome.identify_home(),
}
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 " # type: ignore
show_details.onionr_help += "for your Onionr install:"
show_stats.onionr_help = "Shows statistics for your Onionr " # type: ignore
show_stats.onionr_help += "node. Slow if Onionr is not running" # type: ignore

View File

@ -11,7 +11,7 @@ try:
except (KeyError, IndexError) as _:
pass
import logger
from logger import log as logging
import onionrexceptions
import onionrplugins
from onionrplugins import onionrpluginapi
@ -48,10 +48,6 @@ def register_plugin_commands(cmd) -> bool:
return False
def _show_term(msg: str):
logger.info(msg, terminal=True)
def register():
"""Register commands and handles help command processing."""
def get_help_message(cmd: str,
@ -80,7 +76,7 @@ def register():
try:
cmd = sys.argv[1]
except IndexError:
logger.info('Run with --help to see available commands', terminal=True)
logging.info('Run with --help to see available commands')
sys.exit(10)
is_help_cmd = False
@ -102,29 +98,28 @@ def register():
sys.argv[2]
except IndexError:
for i in arguments.get_arguments():
_show_term('%s <%s>: %s' % (PROGRAM_NAME, '/'.join(i),
logging.info('%s <%s>: %s' % (PROGRAM_NAME, '/'.join(i),
get_help_message(i[0])))
for pl in onionrplugins.get_enabled_plugins():
pl = onionrplugins.get_plugin(pl)
if hasattr(pl, 'ONIONR_COMMANDS'):
print('')
try:
_show_term('%s commands:' % (pl.plugin_name,))
logging.info('%s commands:' % (pl.plugin_name,))
except AttributeError:
_show_term('%s commands:' % (pl.__name__,))
logging.info('%s commands:' % (pl.__name__,))
for plugin_cmd in pl.ONIONR_COMMANDS:
_show_term('%s %s: %s' %
logging.info('%s %s: %s' %
(PROGRAM_NAME,
plugin_cmd,
get_help_message(plugin_cmd)),)
print('')
else:
try:
_show_term('%s %s: %s' % (PROGRAM_NAME,
logging.info('%s %s: %s' % (PROGRAM_NAME,
sys.argv[2],
get_help_message(sys.argv[2])))
except KeyError:
logger.error('%s: command does not exist.' % [sys.argv[2]],
terminal=True)
logging.error('%s: command does not exist.' % [sys.argv[2]])
sys.exit(3)
return

View File

@ -4,7 +4,7 @@ Sets CLI arguments for Onionr
"""
from typing import Callable
from .. import onionrstatistics, version, daemonlaunch
from .. import version, daemonlaunch
from .. import resetplugins # command to reinstall default plugins
@ -32,8 +32,6 @@ def get_arguments() -> dict:
dynamically modify them with plugins
"""
args = {
('details', 'info'): onionrstatistics.show_details,
('stats', 'statistics'): onionrstatistics.show_stats,
('version',): version.version,
('start', 'daemon'): daemonlaunch.start,
('stop', 'kill'): daemonlaunch.kill_daemon,

View File

@ -4,7 +4,7 @@ Try to provide recommendations for invalid Onionr commands
"""
import sys
from difflib import SequenceMatcher
import logger
from logger import log as logging
from . import arguments
"""
This program is free software: you can redistribute it and/or modify
@ -30,9 +30,9 @@ def recommend(print_default: bool = True):
for key in args.keys():
for word in key:
if SequenceMatcher(None, tried, word).ratio() >= 0.75:
logger.warn(f'{print_message} "{tried}", '
logging.warn(f'{print_message} "{tried}", '
+ f'did you mean "{word}"?',
terminal=True)
)
return
if print_default:
logger.error('%s "%s"' % (print_message, tried), terminal=True)
logging.error('%s "%s"' % (print_message, tried))

View File

@ -6,7 +6,7 @@ import os
import shutil
from utils import identifyhome
import logger
from logger import log as logging
"""
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
@ -32,7 +32,7 @@ def reset():
if os.path.exists(plugin_dir):
shutil.rmtree(plugin_dir)
logger.info('Default plugins have been reset.', terminal=True)
logging.info('Default plugins have been reset.')
reset.onionr_help = "reinstalls default Onionr plugins" # type: ignore

View File

@ -5,7 +5,7 @@ Command to show version info
import platform
from utils import identifyhome
import onionrvalues
import logger
from logger import log as logging
"""
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
@ -22,23 +22,21 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def version(verbosity=5, function=logger.info):
def version(verbosity=5, function=logging.info):
"""Display the Onionr version."""
function('Onionr v%s (%s)' % (onionrvalues.ONIONR_VERSION,
platform.machine()),
terminal=True)
platform.machine()))
if verbosity >= 1:
function(onionrvalues.ONIONR_TAGLINE, terminal=True)
function(onionrvalues.ONIONR_TAGLINE)
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)
f'{python_imp} {python_version} on {pf} {release}')
function('Onionr data dir: %s' %
identifyhome.identify_home(), terminal=True)
identifyhome.identify_home())
version.onionr_help = 'Shows environment details including ' # type: ignore

View File

@ -22,7 +22,7 @@ import traceback
from . import onionrevents as events
from .pluginapis import plugin_apis
import config, logger
import config, logging
from utils import identifyhome
# set data dir
@ -43,9 +43,9 @@ def reload(stop_event = True):
enabled_plugins = get_enabled_plugins()
if stop_event is True:
logger.debug('Reloading all plugins...')
logging.debug('Reloading all plugins...')
else:
logger.debug('Loading all plugins...')
logging.debug('Loading all plugins...')
if stop_event is True:
for plugin in enabled_plugins:
@ -56,7 +56,7 @@ def reload(stop_event = True):
return True
except:
logger.error('Failed to reload plugins.')
logging.error('Failed to reload plugins.')
return False
@ -73,8 +73,8 @@ def enable(name, start_event = True):
except ImportError as e: # Was getting import error on Gitlab CI test "data"
# NOTE: If you are experiencing issues with plugins not being enabled, it might be this resulting from an error in the module
# can happen inconsistently (especially between versions)
logger.error('Failed to enable module:', terminal=True)
logger.error(traceback.format_exc(), terminal=True)
logging.error('Failed to enable module:')
logging.error(traceback.format_exc())
return False
else:
enabled_plugins.append(name)
@ -86,8 +86,8 @@ def enable(name, start_event = True):
else:
return False
else:
logger.error('Failed to enable plugin \"%s\", disabling plugin.' % name, terminal=True)
logger.debug('Plugins folder not found: %s' % get_plugins_folder(str(name).lower()), terminal=True)
logging.error('Failed to enable plugin \"%s\", disabling plugin.' % name)
logging.debug('Plugins folder not found: %s' % get_plugins_folder(str(name).lower()))
disable(name)
return False
@ -129,9 +129,9 @@ def start(name):
return plugin
except:
logger.error('Failed to start module \"%s\".' % name)
logging.error('Failed to start module \"%s\".' % name)
else:
logger.error('Failed to start nonexistant module \"%s\".' % name)
logging.error('Failed to start nonexistant module \"%s\".' % name)
return None
@ -153,9 +153,9 @@ def stop(name):
return plugin
except:
logger.error('Failed to stop module \"%s\".' % name)
logging.error('Failed to stop module \"%s\".' % name)
else:
logger.error('Failed to stop nonexistant module \"%s\".' % name)
logging.error('Failed to stop nonexistant module \"%s\".' % name)
return None
@ -258,11 +258,11 @@ def check():
"""
if not config.is_set('plugins'):
logger.debug('Generating plugin configuration data...')
logging.debug('Generating plugin configuration data...')
config.set('plugins', {'enabled': []}, True)
if not os.path.exists(os.path.dirname(get_plugins_folder())):
logger.debug('Generating plugin data folder...')
logging.debug('Generating plugin data folder...')
try:
os.makedirs(os.path.dirname(get_plugins_folder()))
except FileExistsError:

View File

@ -7,7 +7,7 @@ from threading import Thread
import traceback
import config, logger
import config, logging
import onionrplugins as plugins
from . import onionrpluginapi as pluginapi
"""
@ -41,11 +41,11 @@ def __event_caller(event_name, data = {}):
try:
call(plugins.get_plugin(plugin), event_name, data, get_pluginapi(data))
except ModuleNotFoundError as _:
logger.warn('Disabling nonexistant plugin "%s"...' % plugin, terminal=True)
logging.warn('Disabling nonexistant plugin "%s"...' % plugin)
plugins.disable(plugin, stop_event = False)
except Exception as _:
logger.error('Event "%s" failed for plugin "%s".' % (event_name, plugin), terminal=True)
logger.error('\n' + traceback.format_exc(), terminal=True)
logging.error('Event "%s" failed for plugin "%s".' % (event_name, plugin))
logging.error('\n' + traceback.format_exc())
def event(event_name, data = {}, threaded = True):
"""Call an event on all plugins (if defined)"""

View File

@ -18,7 +18,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import onionrplugins, logger
import onionrplugins, logging
class PluginAPI:

View File

@ -20,7 +20,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
import os, shutil
import onionrplugins as plugins
import logger
from logger import log as logging
import filepaths
from utils.readstatic import get_static_dir
@ -38,9 +38,9 @@ def setup_default_plugins():
if not name in plugins.get_enabled_plugins():
plugins.enable(name)
else:
logger.error(
logging.error(
"Plugin source directory does not exist!" +
"Onionr needs plugins to be useful", terminal=True)
"Onionr needs plugins to be useful")
for name in plugins.get_enabled_plugins():
@ -50,5 +50,5 @@ def setup_default_plugins():
except FileExistsError:
pass
except Exception as e:
#logger.warn('Error enabling plugin: ' + str(e), terminal=True)
#logging.warn('Error enabling plugin: ' + str(e))
plugins.disable(name, stop_event = False)

View File

@ -8,9 +8,8 @@ import base64
import ujson as json
import config
import logger
from logger import log as logging
import onionrvalues
from logger.settings import *
from utils import readstatic
"""
This program is free software: you can redistribute it and/or modify
@ -37,42 +36,3 @@ def setup_config():
config.save()
config.reload()
settings = 0b000
if config.get('log.console.color', True):
settings = settings | USE_ANSI
if config.get('log.console.output', True):
settings = settings | OUTPUT_TO_CONSOLE
if config.get('log.file.output', True):
settings = settings | OUTPUT_TO_FILE
set_settings(settings)
verbosity = str(config.get('log.verbosity', 'default')).lower().strip()
if not verbosity in ['default', 'null', 'none', 'nil']:
map = {
str(LEVEL_DEBUG) : LEVEL_DEBUG,
'verbose' : LEVEL_DEBUG,
'debug' : LEVEL_DEBUG,
str(LEVEL_INFO) : LEVEL_INFO,
'info' : LEVEL_INFO,
'information' : LEVEL_INFO,
str(LEVEL_WARN) : LEVEL_WARN,
'warn' : LEVEL_WARN,
'warning' : LEVEL_WARN,
'warnings' : LEVEL_WARN,
str(LEVEL_ERROR) : LEVEL_ERROR,
'err' : LEVEL_ERROR,
'error' : LEVEL_ERROR,
'errors' : LEVEL_ERROR,
str(LEVEL_FATAL) : LEVEL_FATAL,
'fatal' : LEVEL_FATAL,
str(LEVEL_IMPORTANT) : LEVEL_IMPORTANT,
'silent' : LEVEL_IMPORTANT,
'quiet' : LEVEL_IMPORTANT,
'important' : LEVEL_IMPORTANT
}
if verbosity in map:
set_level(map[verbosity])
else:
logger.warn('Verbosity level %s is not valid, using default verbosity.' % verbosity)

View File

@ -6,7 +6,7 @@ from threading import Thread
from uuid import uuid4
from time import sleep
import logger
from logger import log as logging
def _onionr_thread(func: Callable,
@ -18,10 +18,10 @@ def _onionr_thread(func: Callable,
try:
func(*args, **kwargs)
except Exception as _: # noqa
logger.warn(
logging.warn(
f"Onionr thread exception in {thread_id} \n" +
traceback.format_exc(),
terminal=True)
)
sleep(sleep_secs)

View File

@ -1,15 +0,0 @@
import sys, os
from . import readstatic
import logger
import onionrvalues
def header(message = logger.colors.fg.pink + logger.colors.bold + 'Onionr' + logger.colors.reset + logger.colors.fg.pink + ' has started.'):
if onionrvalues.DEVELOPMENT_MODE:
return
header_path = readstatic.get_static_dir() + 'header.txt'
if os.path.exists(header_path) and logger.settings.get_level() <= logger.settings.LEVEL_INFO:
with open(header_path, 'rb') as file:
# only to stdout, not file or log or anything
sys.stderr.write(file.read().decode().replace('P', logger.colors.fg.pink).replace('W', logger.colors.reset + logger.colors.bold).replace('G', logger.colors.fg.green).replace('\n', logger.colors.reset + '\n').replace('B', logger.colors.bold))
if message:
logger.info(logger.colors.fg.lightgreen + '-> ' + str(message) + logger.colors.reset + logger.colors.fg.lightgreen + ' <-\n', terminal=True)

View File

@ -11,11 +11,10 @@
"file": {
"output": true,
"remove_on_exit": false
},
"verbosity": "default"
}
},
"plugins": {
"disabled": ["unixtransport", "repl", "bigbrother"],
"disabled": ["unixtransport", "repl", "bigbrother", "example"],
"enabled": []
},
"security": {

View File

@ -1,16 +0,0 @@
'''
$name plugin template file.
Generated on $date by $user.
'''
plugin_name = '$name'
def on_init(api, data = None):
'''
This event is called after Onionr is initialized, but before the command
inputted is executed. Could be called when daemon is starting or when
just the client is running.
'''
pluginapi = api

View File

@ -18,9 +18,9 @@ P ::: :::: ::::::: :::: :::: W:: :: :: ::: :: :: :: :: :::: :::::
P ::: ::::: :::::: :::: :::: W:: :: :: ::: :: :: :: :: ::: :: :::
P :::: ::::: ::::: ::: W :::: :: :: :: ::::: :: :: :: ::
P :::: :::::: :::::: ::::
P :::: :::::::::::: :::: GPB
P :::: :::::::::::: ::::
P ::::: :::::::: ::::
P ::::: :::::
P ::::::::::::::::
P :::::::

View File

@ -6,7 +6,7 @@ import sys
import os
from typing import Iterable
import logger
from logger import log as logging
"""
This program is free software: you can redistribute it and/or modify
@ -49,5 +49,5 @@ def enable_ministries(disable_hooks: Iterable = None):
def on_init(api, data=None):
enable_ministries()
logger.info(
"Big brother enabled, blocking unsafe Python code.", terminal=True)
logging.info(
"Big brother enabled, blocking unsafe Python code.")

View File

@ -4,7 +4,7 @@ Ensure sockets don't get made to non localhost
"""
import ipaddress
import logger
from logger import log as logging
from onionrexceptions import NetworkLeak
"""
This program is free software: you can redistribute it and/or modify
@ -37,12 +37,12 @@ def detect_socket_leaks(socket_event):
try:
ip_address = ipaddress.ip_address(ip_address)
except ValueError:
logger.warn(f'Conn made to {ip_address} outside of Tor/similar')
logging.warn(f'Conn made to {ip_address} outside of Tor/similar')
raise \
NetworkLeak('Conn to host/non local IP, this is a privacy issue!')
# Validate that the IP is localhost ipv4
if not ip_address.is_loopback and not ip_address.is_multicast \
and not ip_address.is_private:
logger.warn(f'Conn made to {ip_address} outside of Tor/similar')
logging.warn(f'Conn made to {ip_address} outside of Tor/similar')
raise NetworkLeak('Conn to non local IP, this is a privacy concern!')

View File

@ -3,7 +3,7 @@
Log (not block) read/write of non-user data files and non-python lib files
"""
from utils.identifyhome import identify_home
import logger
from logger import log as logging
"""
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
@ -33,4 +33,4 @@ def detect_disk_access(info):
if identify_home() not in info[0]:
if 'proc' not in info[0]: # if it is, it is onionr stats
logger.warn(f'[DISK MINISTRY] {info}')
logging.warn(f'[DISK MINISTRY] {info}')

View File

@ -5,7 +5,7 @@ Prevent eval/exec/os.system and log it
import base64
import platform
import logger
from logger import log as logging
from utils import identifyhome
from onionrexceptions import ArbitraryCodeExec
"""
@ -27,8 +27,8 @@ untrusted_exec = True
def block_system(cmd):
"""Prevent os.system except for whitelisted commands+contexts."""
logger.warn('POSSIBLE EXPLOIT DETECTED, SEE LOGS', terminal=True)
logger.warn(f'POSSIBLE EXPLOIT: shell command not in whitelist: {cmd}')
logging.warn('POSSIBLE EXPLOIT DETECTED, SEE LOGS')
logging.warn(f'POSSIBLE EXPLOIT: shell command not in whitelist: {cmd}')
raise ArbitraryCodeExec('os.system command not in whitelist')
@ -57,8 +57,8 @@ def block_exec(event, info):
if 'plugins/' in info[0].co_filename:
return
logger.warn('POSSIBLE EXPLOIT DETECTED, SEE LOGS', terminal=True)
logger.warn('POSSIBLE EXPLOIT DETECTED: ' + info[0].co_filename)
logger.warn('Prevented exec/eval. Report this with the sample below')
logger.warn(f'{event} code in base64 format: {code_b64}')
logging.warn('POSSIBLE EXPLOIT DETECTED, SEE LOGS')
logging.warn('POSSIBLE EXPLOIT DETECTED: ' + info[0].co_filename)
logging.warn('Prevented exec/eval. Report this with the sample below')
logging.warn(f'{event} code in base64 format: {code_b64}')
raise ArbitraryCodeExec("Arbitrary code (eval/exec) detected.")

View File

@ -6,14 +6,12 @@ import sys
import os
import locale
from time import sleep
import traceback
from logger import log as logging
from typing import Set, TYPE_CHECKING
from threading import Thread, local
import blockdb
from gossip.peerset import gossip_peer_set
import logger
import onionrblocks
locale.setlocale(locale.LC_ALL, '')
@ -58,5 +56,5 @@ def on_printtest_cmd(api, data=None):
def on_init(api, data=None):
logger.info(
f"Example Plugin v{PLUGIN_VERSION} enabled", terminal=True)
logging.info(
f"Example Plugin v{PLUGIN_VERSION} enabled")

View File

@ -21,6 +21,8 @@ from code import InteractiveConsole
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
# import after path insert
import logger
"""
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
@ -42,6 +44,7 @@ PLUGIN_VERSION = '0.0.0'
def on_primary_loop(event_name, data):
"""Run a REPL on the primary loop"""
logger.disable_console_logging()
header = """You are now in the Onionr REPL. Type 'exit()' to exit.
Enter repl_locals to see the (default) special locals available to you.

View File

@ -1,5 +1,5 @@
import config
import logger
from logger import log as logging
from gossip.peerset import gossip_peer_set
from getsocks import get_socks
@ -24,6 +24,6 @@ def on_announce_rec(api, data=None):
return
logger.info(f"Peer {announced} announced to us.", terminal=True)
logging.info(f"Peer {announced} announced to us.")
data['callback'](TorPeer(socks_address, socks_port, announced))

View File

@ -9,7 +9,7 @@ from typing import Callable
from gossip.peer import Peer
from gossip.peerset import gossip_peer_set
from utils.identifyhome import identify_home
import logger
from logger import log as logging
import config
from getsocks import get_socks
@ -47,7 +47,7 @@ def on_bootstrap(api, data):
except FileNotFoundError:
bootstrap_nodes = set()
except Exception as _:
logger.warn(traceback.format_exc(), terminal=True)
logging.warn(traceback.format_exc())
return
else:
return
@ -60,7 +60,7 @@ def on_bootstrap(api, data):
try:
config.reload()
except Exception:
logger.error(traceback.format_exc(), terminal=True)
logging.error(traceback.format_exc())
socks_address, socks_port = get_socks()[0]

View File

@ -1 +0,0 @@
hc5qc2vfuq2rkz4mjrrobcjgdjnsni6rovhfkbpc7huupbuiztx6wiid

View File

@ -8,13 +8,12 @@ import locale
from time import sleep
import traceback
from typing import Set, TYPE_CHECKING
import base64
from logger import log as logging
from threading import Thread
import stem
from stem.control import Controller
import logger
from utils import readstatic
import config
from filepaths import gossip_server_socket_file
@ -58,8 +57,8 @@ class OnionrTor:
def on_init(api, data=None):
logger.info(
f"Tor Transport Plugin v{PLUGIN_VERSION} enabled", terminal=True)
logging.info(
f"Tor Transport Plugin v{PLUGIN_VERSION} enabled")
def on_get_our_transport(api, data=None):
@ -75,10 +74,11 @@ def on_gossip_start(api, data: Set[Peer] = None):
starttor.start_tor()
with Controller.from_socket_file(control_socket) as controller:
controller
controller.authenticate()
logger.info(
logging.info(
"Tor socks is listening on " +
f"{controller.get_listeners('SOCKS')[0]}", terminal=True)
f"{controller.get_listeners('SOCKS')[0]}")
key = config.get('tor.key')
new_address = ''
if not key:
@ -98,12 +98,10 @@ def on_gossip_start(api, data: Set[Peer] = None):
key_content=key, key_type='ED25519-V3',
detached=True, await_publication=True)
except stem.ProtocolError:
logger.error(
logging.error(
"Could not start Tor transport. Try restarting Onionr",
terminal=True)
)
config.set('tor.key', '', savefile=True)
return
logger.info(
f'{new_address}Tor transport address {add_onion_resp.service_id}' +
'.onion',
terminal=True)
logging.info(
f'{new_address}Tor transport address {add_onion_resp.service_id}.onion')

View File

@ -1,7 +1,7 @@
import socks
from gossip.peerset import gossip_peer_set
import logger
from logger import log as logging
class HandleRevc:
@ -48,9 +48,9 @@ class TorPeer:
except KeyError:
pass
else:
logger.debug(
logging.debug(
f"Could not create socket to peer {self.transport_address}",
terminal=True)
)
raise TimeoutError
mock_recv = HandleRevc(s)
s.recv = mock_recv.recv

View File

@ -6,7 +6,7 @@ import sys
import os
import locale
from time import sleep
import traceback
from logger import log as logging
from typing import Set, TYPE_CHECKING
from threading import Thread
import shelve
@ -14,7 +14,6 @@ import shelve
import stem
from stem.control import Controller
import logger
from utils import readstatic
import config
from filepaths import gossip_server_socket_file
@ -59,10 +58,10 @@ def on_shutdown_event(api, data=None):
db[peer.transport_address] = peer
def on_init(api, data=None):
logger.info(
f"Unix Transport Plugin v{PLUGIN_VERSION} enabled", terminal=True)
logger.info(
f"Peers can connect to {gossip_server_socket_file}", terminal=True)
logging.info(
f"Unix Transport Plugin v{PLUGIN_VERSION} enabled")
logging.info(
f"Peers can connect to {gossip_server_socket_file}")
def on_get_our_transport(api, data=None):
callback_func = data['callback']

View File

@ -1,5 +1,5 @@
import config
import logger
from logger import log as logging
from gossip.server import gossip_server_socket_file
from unixpeer import UnixPeer
@ -19,6 +19,6 @@ def on_announce_rec(api, data=None):
if announced == gossip_server_socket_file:
return
logger.info(f"Peer {announced} announced to us.", terminal=True)
logging.info(f"Peer {announced} announced to us.")
data['callback'](UnixPeer(announced))

View File

@ -10,7 +10,7 @@ from gossip.server import gossip_server_socket_file
from gossip.peer import Peer
from gossip.peerset import gossip_peer_set
from utils.identifyhome import identify_home
import logger
from logger import log as logging
import config
from unixpeer import UnixPeer
@ -46,7 +46,7 @@ def on_bootstrap(api, data=None):
except FileNotFoundError:
bootstrap_nodes = set()
except Exception as e:
logger.warn(traceback.format_exc(), terminal=True)
logging.warn(traceback.format_exc())
return
else:
return

View File

@ -11,7 +11,7 @@ from threading import Thread, local
from gossip.peerset import gossip_peer_set
import logger
from logger import log as logging
import onionrplugins
@ -41,8 +41,8 @@ from wot.loadfromblocks import load_identities_from_blocks
def on_init(api, data=None):
logger.info(
f"Web of Trust Plugin v{PLUGIN_VERSION} enabled", terminal=True)
logging.info(
f"Web of Trust Plugin v{PLUGIN_VERSION} enabled")
#onionrplugins.plugin_apis['wot'] = wot_test
list(map(lambda x: identities.add(x), load_identities_from_blocks()))

View File

@ -1,4 +1,4 @@
import logger
from logger import log as logging
from nacl.signing import VerifyKey
@ -10,8 +10,8 @@ def process_identity_announce(identity_announce_payload):
# verify that this is a signature for an announce command
if identity_announce_payload[0] != WotCommand.ANNOUNCE:
logger.warn(
f'Invalid command in signature' , terminal=True)
logging.warn(
f'Invalid command in signature' )
return
iden = Identity.deserialize(identity_announce_payload[1:])
identities.add(iden)

View File

@ -1,4 +1,4 @@
import logger
from logger import log as logging
from nacl.signing import VerifyKey
@ -9,13 +9,13 @@ from wot.identity.identityset import identities
def process_identity_revoke(revoke_payload: bytes):
wot_cmd = revoke_payload[0].to_bytes(1, 'big')
if revoke_payload[0] != WotCommand.REVOKE:
logger.warn(
f'Invalid command in signature', terminal=True)
logging.warn(
f'Invalid command in signature')
return
revoked_identity = revoke_payload[1:33]
signature = revoke_payload[33:]
# raises nacl.exceptions.BadSignatureError if bad signature
VerifyKey(revoked_identity).verify(wot_cmd + revoked_identity, signature)
identities.remove(Identity(revoked_identity, "etc"))

View File

@ -2,7 +2,7 @@ import traceback
from nacl.signing import VerifyKey
import logger
from logger import log as logging
from wot.getbykey import get_identity_by_key
from wot.blockprocessingevent import WotCommand
@ -10,14 +10,14 @@ from wot.blockprocessingevent import WotCommand
def process_revoke_signature(revoke_signature_payload):
if len(revoke_signature_payload) != 129:
logger.warn(
logging.warn(
f'Signature size is invalid for revoking an identity',
terminal=True)
)
# verify that this is a signature for a trust command
if revoke_signature_payload[0] != WotCommand.REVOKE_TRUST:
logger.warn(
f'Invalid command in signature' , terminal=True)
logging.warn(
f'Invalid command in signature' )
return
# signer is first 32 bytes
signer = VerifyKey(revoke_signature_payload[1:33])

View File

@ -1,5 +1,5 @@
import traceback
import logger
from logger import log as logging
from nacl.signing import VerifyKey
@ -9,13 +9,13 @@ from wot.blockprocessingevent import WotCommand
def process_trust_signature(sig_payload: bytes):
if len(sig_payload) != 129:
logger.warn(
logging.warn(
f'Signature size is invalid for a signed identity')
return
# verify that this is a signature for a trust command
if sig_payload[0] != WotCommand.TRUST:
logger.warn(
logging.warn(
f'Invalid command in signature')
return
# signer is first 32 bytes

View File

@ -4,7 +4,7 @@ import traceback
from nacl.signing import VerifyKey
import nacl.exceptions
import logger
from logger import log as logging
import blockdb
from wot.identity import Identity, identities
@ -33,5 +33,5 @@ def load_signatures_from_blocks() -> None:
# noop if already signed
processtrustsignature.process_trust_signature(block.data)
except nacl.exceptions.BadSignatureError:
logger.warn('Bad signature in block:')
logger.warn(traceback.format_exc())
logging.warn('Bad signature in block:')
logging.warn(traceback.format_exc())