added sound notification support and forward secery setting finished
parent
23782dcb8f
commit
aea4815fbd
|
@ -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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
'''
|
"""
|
||||||
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 = Blueprint('insertblock', __name__)
|
||||||
|
|
||||||
|
|
||||||
@ib.route('/insertblock', methods=['POST'])
|
@ib.route('/insertblock', methods=['POST'])
|
||||||
def client_api_insert_block():
|
def client_api_insert_block():
|
||||||
encrypt = False
|
encrypt: bool = False
|
||||||
bData = request.get_json(force=True)
|
insert_data: JSONSerializable = request.get_json(force=True)
|
||||||
message = bData['message']
|
message = insert_data['message']
|
||||||
message_hash = bytesconverter.bytes_to_str(hashers.sha3_hash(message))
|
message_hash = bytesconverter.bytes_to_str(hashers.sha3_hash(message))
|
||||||
|
|
||||||
# Detect if message (block body) is not specified
|
# Detect if message (block body) is not specified
|
||||||
|
@ -37,40 +40,48 @@ def client_api_insert_block():
|
||||||
return 'failure due to unspecified message', 400
|
return 'failure due to unspecified message', 400
|
||||||
|
|
||||||
# Detect if block with same message is already being inserted
|
# 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
|
return 'failure due to duplicate insert', 400
|
||||||
else:
|
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'
|
encrypt_type = ''
|
||||||
encryptType = ''
|
|
||||||
sign = True
|
sign = True
|
||||||
meta = {}
|
meta = {}
|
||||||
to = ''
|
to = ''
|
||||||
try:
|
try:
|
||||||
if bData['encrypt']:
|
if insert_data['encrypt']:
|
||||||
to = bData['to'].strip()
|
to = insert_data['to'].strip()
|
||||||
if "-" in to:
|
if "-" in to:
|
||||||
to = mnemonickeys.get_base32(to)
|
to = mnemonickeys.get_base32(to)
|
||||||
encrypt = True
|
encrypt_type = 'asym'
|
||||||
encryptType = 'asym'
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
if not bData['sign']:
|
if not insert_data['sign']:
|
||||||
sign = False
|
sign = False
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
bType = bData['type']
|
bType = insert_data['type']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
bType = 'bin'
|
bType = 'bin'
|
||||||
try:
|
try:
|
||||||
meta = json.loads(bData['meta'])
|
meta = json.loads(insert_data['meta'])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
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(
|
threading.Thread(
|
||||||
target=onionrblocks.insert, args=(message,),
|
target=onionrblocks.insert, args=(message,),
|
||||||
kwargs={'header': bType, 'encryptType': encryptType,
|
kwargs={'header': bType, 'encryptType': encrypt_type,
|
||||||
'sign':sign, 'asymPeer': to, 'meta': meta, 'disableForward': bData['forward']}).start()
|
'sign': sign, 'asymPeer': to, 'meta': meta,
|
||||||
|
'disableForward': disable_forward_secrecy}).start()
|
||||||
return Response('success')
|
return Response('success')
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
Desktop notification wrapper
|
Desktop notification wrapper
|
||||||
"""
|
"""
|
||||||
|
from subprocess import Popen
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import simplenotifications as simplenotify
|
import simplenotifications as simplenotify
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -9,6 +11,7 @@ except ImportError:
|
||||||
else:
|
else:
|
||||||
notifications_enabled = True
|
notifications_enabled = True
|
||||||
|
|
||||||
|
from utils.readstatic import get_static_dir
|
||||||
import config
|
import config
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -29,9 +32,18 @@ import config
|
||||||
if not config.get('general.show_notifications', True):
|
if not config.get('general.show_notifications', True):
|
||||||
notifications_enabled = False
|
notifications_enabled = False
|
||||||
|
|
||||||
|
notification_sound_file = get_static_dir() + "sounds/notification1.mp3"
|
||||||
|
|
||||||
def notify(title: str = "Onionr", message: str = ""):
|
def notify(title: str = "Onionr", message: str = ""):
|
||||||
"""Cross platform method to show a notification."""
|
"""Cross platform method to show a notification."""
|
||||||
if not notifications_enabled:
|
if not notifications_enabled:
|
||||||
return
|
return
|
||||||
simplenotify.notify(title, message)
|
simplenotify.notify(title, message)
|
||||||
|
|
||||||
|
|
||||||
|
def notification_with_sound(sound = '', **kwargs):
|
||||||
|
try:
|
||||||
|
Popen(["mpv", notification_sound_file])
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
notify(**kwargs)
|
||||||
|
|
|
@ -132,7 +132,7 @@ def insert_block(data: Union[str, bytes], header: str = 'txt',
|
||||||
|
|
||||||
if encryptType == 'asym':
|
if encryptType == 'asym':
|
||||||
meta['rply'] = createTime # Duplicate the time in encrypted messages to prevent replays
|
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:
|
try:
|
||||||
forwardEncrypted = onionrusers.OnionrUser(asymPeer).forwardEncrypt(data)
|
forwardEncrypted = onionrusers.OnionrUser(asymPeer).forwardEncrypt(data)
|
||||||
data = forwardEncrypted[0]
|
data = forwardEncrypted[0]
|
||||||
|
@ -140,9 +140,8 @@ def insert_block(data: Union[str, bytes], header: str = 'txt',
|
||||||
expire = forwardEncrypted[2] # Expire time of key. no sense keeping block after that
|
expire = forwardEncrypted[2] # Expire time of key. no sense keeping block after that
|
||||||
except onionrexceptions.InvalidPubkey:
|
except onionrexceptions.InvalidPubkey:
|
||||||
pass
|
pass
|
||||||
#onionrusers.OnionrUser(self, asymPeer).generateForwardKey()
|
if not disableForward:
|
||||||
fsKey = onionrusers.OnionrUser(asymPeer).generateForwardKey()
|
fsKey = onionrusers.OnionrUser(asymPeer).generateForwardKey()
|
||||||
#fsKey = onionrusers.OnionrUser(self, asymPeer).getGeneratedForwardKeys().reverse()
|
|
||||||
meta['newFSKey'] = fsKey
|
meta['newFSKey'] = fsKey
|
||||||
jsonMeta = json.dumps(meta)
|
jsonMeta = json.dumps(meta)
|
||||||
plaintextMeta = jsonMeta
|
plaintextMeta = jsonMeta
|
||||||
|
@ -196,6 +195,8 @@ def insert_block(data: Union[str, bytes], header: str = 'txt',
|
||||||
logger.error(allocationReachedMessage)
|
logger.error(allocationReachedMessage)
|
||||||
retData = False
|
retData = False
|
||||||
else:
|
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
|
# Tell the api server through localCommand to wait for the daemon to upload this block to make statistical analysis more difficult
|
||||||
spawn(
|
spawn(
|
||||||
localcommand.local_command,
|
localcommand.local_command,
|
||||||
|
|
|
@ -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",
|
("Like a black hole, NSA pulls in every signal that comes near, but no electron is ever allowed to escape",
|
||||||
"James Bamford"),
|
"James Bamford"),
|
||||||
("Freedom of the press is guaranteed only to those who own one",
|
("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)
|
shuffle(QUOTES)
|
||||||
QUOTE = QUOTES[0]
|
QUOTE = QUOTES[0]
|
||||||
|
|
|
@ -72,7 +72,8 @@ def open_home():
|
||||||
'Onionr seems to not be running (could not get api host)',
|
'Onionr seems to not be running (could not get api host)',
|
||||||
terminal=True)
|
terminal=True)
|
||||||
else:
|
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()
|
url = get_url()
|
||||||
logger.info(
|
logger.info(
|
||||||
'If Onionr does not open automatically, use this URL: ' + url,
|
'If Onionr does not open automatically, use this URL: ' + url,
|
||||||
|
|
|
@ -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
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -20,9 +19,12 @@
|
||||||
|
|
||||||
from typing import Union
|
from typing import Union
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
def get_static_dir()->str:
|
def get_static_dir()->str:
|
||||||
return os.path.dirname(os.path.realpath(__file__)) + '/../../static-data/'
|
return os.path.dirname(os.path.realpath(__file__)) + '/../../static-data/'
|
||||||
|
|
||||||
|
|
||||||
def read_static(file:str, ret_bin:bool=False)->Union[str, bytes]:
|
def read_static(file:str, ret_bin:bool=False)->Union[str, bytes]:
|
||||||
static_file = get_static_dir() + file
|
static_file = get_static_dir() + file
|
||||||
|
|
||||||
|
|
|
@ -70,4 +70,4 @@ def on_processblocks(api, data=None):
|
||||||
signer = signer[:5]
|
signer = signer[:5]
|
||||||
|
|
||||||
if data['block'].decrypted:
|
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']))
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
<script defer src="/shared/main/apicheck.js"></script>
|
<script defer src="/shared/main/apicheck.js"></script>
|
||||||
<script defer src="/shared/misc.js"></script>
|
<script defer src="/shared/misc.js"></script>
|
||||||
<script defer src="/mail/sethumanreadable.js"></script>
|
<script defer src="/mail/sethumanreadable.js"></script>
|
||||||
|
<script defer src="/mail/loadsettings.js"></script>
|
||||||
<script defer src="/mail/mail.js"></script>
|
<script defer src="/mail/mail.js"></script>
|
||||||
<script defer src="/mail/sendmail.js"></script>
|
<script defer src="/mail/sendmail.js"></script>
|
||||||
<script defer src="/mail/closesettings.js"></script>
|
<script defer src="/mail/closesettings.js"></script>
|
||||||
|
@ -141,7 +142,8 @@
|
||||||
<section class="modal-card-body">
|
<section class="modal-card-body">
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
Use forward secrecy
|
<div>Ask senders to use forward-secrecy</div>
|
||||||
|
<small>Only turn off if you use multiple devices with 1 ID or have Onionr data erasure on exit enabled.</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-2">
|
<div class="column is-2">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
|
|
|
@ -24,7 +24,9 @@ subject = document.getElementById('draftSubject')
|
||||||
friendPicker = document.getElementById('friendSelect')
|
friendPicker = document.getElementById('friendSelect')
|
||||||
|
|
||||||
function sendMail(toData, message, subject){
|
function sendMail(toData, message, subject){
|
||||||
|
|
||||||
postData = {'message': message, 'to': toData, 'type': 'pm', 'encrypt': true, 'meta': JSON.stringify({'subject': subject})}
|
postData = {'message': message, 'to': toData, 'type': 'pm', 'encrypt': true, 'meta': JSON.stringify({'subject': subject})}
|
||||||
|
postData.forward = document.getElementById('forwardSecrecySetting').checked
|
||||||
postData = JSON.stringify(postData)
|
postData = JSON.stringify(postData)
|
||||||
sendForm.style.display = 'none'
|
sendForm.style.display = 'none'
|
||||||
fetch('/insertblock', {
|
fetch('/insertblock', {
|
||||||
|
|
|
@ -28,6 +28,7 @@ document.getElementById('forwardSecrecySetting').onchange = function(e){
|
||||||
}})
|
}})
|
||||||
.then((resp) => resp.text())
|
.then((resp) => resp.text())
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
|
mailSettings['forwardSecrecy'] = document.getElementById('forwardSecrecySetting').checked
|
||||||
PNotify.success({
|
PNotify.success({
|
||||||
text: 'Successfully toggled default forward secrecy'
|
text: 'Successfully toggled default forward secrecy'
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue