From aea4815fbdfa8b50e88a8d3919b7ad7ef2ca82f1 Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Mon, 17 Feb 2020 06:13:57 -0600 Subject: [PATCH] added sound notification support and forward secery setting finished --- requirements-notifications.in | 2 +- src/httpapi/insertblock.py | 69 +++++++++++++---------- src/notifier/__init__.py | 12 ++++ src/onionrblocks/insert/main.py | 11 ++-- src/onionrcommands/daemonlaunch/quotes.py | 4 +- src/onionrcommands/openwebinterface.py | 3 +- src/utils/readstatic.py | 8 ++- static-data/default-plugins/pms/main.py | 2 +- static-data/www/mail/index.html | 4 +- static-data/www/mail/sendmail.js | 2 + static-data/www/mail/settings.js | 1 + 11 files changed, 76 insertions(+), 42 deletions(-) diff --git a/requirements-notifications.in b/requirements-notifications.in index 3f3a4b23..41e4a69f 100644 --- a/requirements-notifications.in +++ b/requirements-notifications.in @@ -1 +1 @@ -simplenotifications==0.2.18 +simplenotifications==0.2.18 \ No newline at end of file diff --git a/src/httpapi/insertblock.py b/src/httpapi/insertblock.py index dbbe22ef..230a627e 100644 --- a/src/httpapi/insertblock.py +++ b/src/httpapi/insertblock.py @@ -1,9 +1,17 @@ -''' - Onionr - Private P2P Communication +"""Onionr - Private P2P Communication. - Create blocks with the client api server -''' -''' +Create blocks with the client api server +""" +import json +import threading + +from flask import Blueprint, Response, request, g +import onionrblocks +from onionrcrypto import hashers +from onionrutils import bytesconverter +from onionrutils import mnemonickeys +from onionrtypes import JSONSerializable +""" 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 @@ -16,20 +24,15 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . -''' -import json, threading -from flask import Blueprint, Response, request, g -import onionrblocks -from onionrcrypto import hashers -from onionrutils import bytesconverter -from onionrutils import mnemonickeys +""" ib = Blueprint('insertblock', __name__) + @ib.route('/insertblock', methods=['POST']) def client_api_insert_block(): - encrypt = False - bData = request.get_json(force=True) - message = bData['message'] + encrypt: bool = False + insert_data: JSONSerializable = request.get_json(force=True) + message = insert_data['message'] message_hash = bytesconverter.bytes_to_str(hashers.sha3_hash(message)) # Detect if message (block body) is not specified @@ -37,40 +40,48 @@ def client_api_insert_block(): return 'failure due to unspecified message', 400 # Detect if block with same message is already being inserted - if message_hash in g.too_many.get_by_string("OnionrCommunicatorDaemon").generating_blocks: + if message_hash in g.too_many.get_by_string( + "OnionrCommunicatorDaemon").generating_blocks: return 'failure due to duplicate insert', 400 else: - g.too_many.get_by_string("OnionrCommunicatorDaemon").generating_blocks.append(message_hash) + g.too_many.get_by_string( + "OnionrCommunicatorDaemon").generating_blocks.append(message_hash) - subject = 'temp' - encryptType = '' + encrypt_type = '' sign = True meta = {} to = '' try: - if bData['encrypt']: - to = bData['to'].strip() + if insert_data['encrypt']: + to = insert_data['to'].strip() if "-" in to: to = mnemonickeys.get_base32(to) - encrypt = True - encryptType = 'asym' + encrypt_type = 'asym' except KeyError: pass try: - if not bData['sign']: + if not insert_data['sign']: sign = False except KeyError: pass try: - bType = bData['type'] + bType = insert_data['type'] except KeyError: bType = 'bin' try: - meta = json.loads(bData['meta']) + meta = json.loads(insert_data['meta']) except KeyError: pass + + try: + # The setting in the UI is for if forward secrecy is enabled, not disabled + disable_forward_secrecy = not insert_data['forward'] + except KeyError: + disable_forward_secrecy = False + threading.Thread( target=onionrblocks.insert, args=(message,), - kwargs={'header': bType, 'encryptType': encryptType, - 'sign':sign, 'asymPeer': to, 'meta': meta, 'disableForward': bData['forward']}).start() - return Response('success') \ No newline at end of file + kwargs={'header': bType, 'encryptType': encrypt_type, + 'sign': sign, 'asymPeer': to, 'meta': meta, + 'disableForward': disable_forward_secrecy}).start() + return Response('success') diff --git a/src/notifier/__init__.py b/src/notifier/__init__.py index c316370f..345350b7 100644 --- a/src/notifier/__init__.py +++ b/src/notifier/__init__.py @@ -2,6 +2,8 @@ Desktop notification wrapper """ +from subprocess import Popen + try: import simplenotifications as simplenotify except ImportError: @@ -9,6 +11,7 @@ except ImportError: else: notifications_enabled = True +from utils.readstatic import get_static_dir import config """ @@ -29,9 +32,18 @@ import config if not config.get('general.show_notifications', True): notifications_enabled = False +notification_sound_file = get_static_dir() + "sounds/notification1.mp3" def notify(title: str = "Onionr", message: str = ""): """Cross platform method to show a notification.""" if not notifications_enabled: return simplenotify.notify(title, message) + + +def notification_with_sound(sound = '', **kwargs): + try: + Popen(["mpv", notification_sound_file]) + except FileNotFoundError: + pass + notify(**kwargs) diff --git a/src/onionrblocks/insert/main.py b/src/onionrblocks/insert/main.py index d60d5f68..004f881c 100644 --- a/src/onionrblocks/insert/main.py +++ b/src/onionrblocks/insert/main.py @@ -132,7 +132,7 @@ def insert_block(data: Union[str, bytes], header: str = 'txt', if encryptType == 'asym': meta['rply'] = createTime # Duplicate the time in encrypted messages to prevent replays - if not disableForward and sign and asymPeer != our_pub_key: + if sign and asymPeer != our_pub_key: try: forwardEncrypted = onionrusers.OnionrUser(asymPeer).forwardEncrypt(data) data = forwardEncrypted[0] @@ -140,10 +140,9 @@ def insert_block(data: Union[str, bytes], header: str = 'txt', expire = forwardEncrypted[2] # Expire time of key. no sense keeping block after that except onionrexceptions.InvalidPubkey: pass - #onionrusers.OnionrUser(self, asymPeer).generateForwardKey() - fsKey = onionrusers.OnionrUser(asymPeer).generateForwardKey() - #fsKey = onionrusers.OnionrUser(self, asymPeer).getGeneratedForwardKeys().reverse() - meta['newFSKey'] = fsKey + if not disableForward: + fsKey = onionrusers.OnionrUser(asymPeer).generateForwardKey() + meta['newFSKey'] = fsKey jsonMeta = json.dumps(meta) plaintextMeta = jsonMeta if sign: @@ -196,6 +195,8 @@ def insert_block(data: Union[str, bytes], header: str = 'txt', logger.error(allocationReachedMessage) retData = False else: + if disableForward: + logger.warn(f'{retData} asym encrypted block created w/o forward secrecy') # Tell the api server through localCommand to wait for the daemon to upload this block to make statistical analysis more difficult spawn( localcommand.local_command, diff --git a/src/onionrcommands/daemonlaunch/quotes.py b/src/onionrcommands/daemonlaunch/quotes.py index 48457e7b..099afc33 100644 --- a/src/onionrcommands/daemonlaunch/quotes.py +++ b/src/onionrcommands/daemonlaunch/quotes.py @@ -17,7 +17,9 @@ QUOTES = [ ("Like a black hole, NSA pulls in every signal that comes near, but no electron is ever allowed to escape", "James Bamford"), ("Freedom of the press is guaranteed only to those who own one", - "A. J. Liebling") + "A. J. Liebling"), + ("We kill people based on metadata", + "Authoritarians") ] shuffle(QUOTES) QUOTE = QUOTES[0] diff --git a/src/onionrcommands/openwebinterface.py b/src/onionrcommands/openwebinterface.py index f2fddb1b..7f55bb73 100755 --- a/src/onionrcommands/openwebinterface.py +++ b/src/onionrcommands/openwebinterface.py @@ -72,7 +72,8 @@ def open_home(): 'Onionr seems to not be running (could not get api host)', terminal=True) else: - _wait_for_ui_to_be_ready() + _wait_for_ui_to_be_ready() # wait for Tor/transports to start + sleep(3) # Sleep a little longer to wait for web UI to init some vars it needs url = get_url() logger.info( 'If Onionr does not open automatically, use this URL: ' + url, diff --git a/src/utils/readstatic.py b/src/utils/readstatic.py index d9343be7..44b0b5ea 100644 --- a/src/utils/readstatic.py +++ b/src/utils/readstatic.py @@ -1,7 +1,6 @@ -""" - Onionr - Private P2P Communication +"""Onionr - Private P2P Communication. - module to get static directory and read static data files +get static directory and read static data files """ """ This program is free software: you can redistribute it and/or modify @@ -20,9 +19,12 @@ from typing import Union import os + + def get_static_dir()->str: return os.path.dirname(os.path.realpath(__file__)) + '/../../static-data/' + def read_static(file:str, ret_bin:bool=False)->Union[str, bytes]: static_file = get_static_dir() + file diff --git a/static-data/default-plugins/pms/main.py b/static-data/default-plugins/pms/main.py index ca1ae569..20fa87b4 100755 --- a/static-data/default-plugins/pms/main.py +++ b/static-data/default-plugins/pms/main.py @@ -70,4 +70,4 @@ def on_processblocks(api, data=None): signer = signer[:5] if data['block'].decrypted: - notifier.notify(title="Onionr Mail - New Message", message="From: %s\n\nSubject: %s" % (signer, metadata['subject'])) + notifier.notification_with_sound(title="Onionr Mail - New Message", message="From: %s\n\nSubject: %s" % (signer, metadata['subject'])) diff --git a/static-data/www/mail/index.html b/static-data/www/mail/index.html index d762e6bb..62164c50 100755 --- a/static-data/www/mail/index.html +++ b/static-data/www/mail/index.html @@ -18,6 +18,7 @@ + @@ -141,7 +142,8 @@