diff --git a/onionr/api.py b/onionr/api.py index 6590a258..647d7635 100755 --- a/onionr/api.py +++ b/onionr/api.py @@ -175,7 +175,7 @@ class PublicAPI: try: newNode = request.form['node'].encode() except KeyError: - logger.warn('No block specified for upload') + logger.warn('No node specified for upload') pass else: try: diff --git a/onionr/communicator.py b/onionr/communicator.py index b4e68b68..54a512ac 100755 --- a/onionr/communicator.py +++ b/onionr/communicator.py @@ -21,12 +21,16 @@ ''' import sys, os, core, config, json, requests, time, logger, threading, base64, onionr, uuid import onionrexceptions, onionrpeers, onionrevents as events, onionrplugins as plugins, onionrblockapi as block -import onionrdaemontools, onionrsockets, onionr, onionrproofs +from communicatorutils import onionrdaemontools +import onionrsockets, onionr, onionrproofs import binascii +from communicatorutils import onionrcommunicatortimers from dependencies import secrets from defusedxml import minidom from utils import networkmerger +OnionrCommunicatorTimers = onionrcommunicatortimers.OnionrCommunicatorTimers + config.reload() class OnionrCommunicatorDaemon: def __init__(self, onionrInst, proxyPort, developmentMode=config.get('general.dev_mode', False)): @@ -647,48 +651,5 @@ class OnionrCommunicatorDaemon: self.decrementThreadCount('runCheck') -class OnionrCommunicatorTimers: - def __init__(self, daemonInstance, timerFunction, frequency, makeThread=True, threadAmount=1, maxThreads=5, requiresPeer=False): - self.timerFunction = timerFunction - self.frequency = frequency - self.threadAmount = threadAmount - self.makeThread = makeThread - self.requiresPeer = requiresPeer - self.daemonInstance = daemonInstance - self.maxThreads = maxThreads - self._core = self.daemonInstance._core - - self.daemonInstance.timers.append(self) - self.count = 0 - - def processTimer(self): - - # mark how many instances of a thread we have (decremented at thread end) - try: - self.daemonInstance.threadCounts[self.timerFunction.__name__] - except KeyError: - self.daemonInstance.threadCounts[self.timerFunction.__name__] = 0 - - # execute thread if it is time, and we are not missing *required* online peer - if self.count == self.frequency and not self.daemonInstance.shutdown: - try: - if self.requiresPeer and len(self.daemonInstance.onlinePeers) == 0: - raise onionrexceptions.OnlinePeerNeeded - except onionrexceptions.OnlinePeerNeeded: - pass - else: - if self.makeThread: - for i in range(self.threadAmount): - if self.daemonInstance.threadCounts[self.timerFunction.__name__] >= self.maxThreads: - logger.debug('%s is currently using the maximum number of threads, not starting another.' % self.timerFunction.__name__) - else: - self.daemonInstance.threadCounts[self.timerFunction.__name__] += 1 - newThread = threading.Thread(target=self.timerFunction) - newThread.start() - else: - self.timerFunction() - self.count = -1 # negative 1 because its incremented at bottom - self.count += 1 - def startCommunicator(onionrInst, proxyPort): OnionrCommunicatorDaemon(onionrInst, proxyPort) \ No newline at end of file diff --git a/onionr/communicatorutils/onionrcommunicatortimers.py b/onionr/communicatorutils/onionrcommunicatortimers.py new file mode 100644 index 00000000..c15f20fc --- /dev/null +++ b/onionr/communicatorutils/onionrcommunicatortimers.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +''' + Onionr - P2P Anonymous Storage Network + + This file contains timer control for the 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 . +''' +import threading, onionrexceptions, logger +class OnionrCommunicatorTimers: + def __init__(self, daemonInstance, timerFunction, frequency, makeThread=True, threadAmount=1, maxThreads=5, requiresPeer=False): + self.timerFunction = timerFunction + self.frequency = frequency + self.threadAmount = threadAmount + self.makeThread = makeThread + self.requiresPeer = requiresPeer + self.daemonInstance = daemonInstance + self.maxThreads = maxThreads + self._core = self.daemonInstance._core + + self.daemonInstance.timers.append(self) + self.count = 0 + + def processTimer(self): + + # mark how many instances of a thread we have (decremented at thread end) + try: + self.daemonInstance.threadCounts[self.timerFunction.__name__] + except KeyError: + self.daemonInstance.threadCounts[self.timerFunction.__name__] = 0 + + # execute thread if it is time, and we are not missing *required* online peer + if self.count == self.frequency and not self.daemonInstance.shutdown: + try: + if self.requiresPeer and len(self.daemonInstance.onlinePeers) == 0: + raise onionrexceptions.OnlinePeerNeeded + except onionrexceptions.OnlinePeerNeeded: + pass + else: + if self.makeThread: + for i in range(self.threadAmount): + if self.daemonInstance.threadCounts[self.timerFunction.__name__] >= self.maxThreads: + logger.debug('%s is currently using the maximum number of threads, not starting another.' % self.timerFunction.__name__) + else: + self.daemonInstance.threadCounts[self.timerFunction.__name__] += 1 + newThread = threading.Thread(target=self.timerFunction) + newThread.start() + else: + self.timerFunction() + self.count = -1 # negative 1 because its incremented at bottom + self.count += 1 diff --git a/onionr/onionrdaemontools.py b/onionr/communicatorutils/onionrdaemontools.py similarity index 100% rename from onionr/onionrdaemontools.py rename to onionr/communicatorutils/onionrdaemontools.py diff --git a/onionr/onionrevents.py b/onionr/onionrevents.py index 0a2c48f1..3301a3ac 100755 --- a/onionr/onionrevents.py +++ b/onionr/onionrevents.py @@ -67,7 +67,6 @@ def call(plugin, event_name, data = None, pluginapi = None): return True except Exception as e: - logger.debug(str(e)) return False else: return True diff --git a/onionr/static-data/www/mail/index.html b/onionr/static-data/www/mail/index.html index 53530968..16b95db9 100755 --- a/onionr/static-data/www/mail/index.html +++ b/onionr/static-data/www/mail/index.html @@ -33,6 +33,9 @@
From: Signature:
+
+ +
diff --git a/onionr/static-data/www/mail/mail.css b/onionr/static-data/www/mail/mail.css index a8d27120..0334de30 100755 --- a/onionr/static-data/www/mail/mail.css +++ b/onionr/static-data/www/mail/mail.css @@ -87,6 +87,17 @@ input{ color: black; } +#replyBtn{ + margin-top: 1em; +} + +.primaryBtn{ + border-radius: 3px; + padding: 3px; + color: black; + width: 5%; +} + .successBtn{ background-color: #28a745; border-radius: 3px; diff --git a/onionr/static-data/www/mail/mail.js b/onionr/static-data/www/mail/mail.js index c7f266ce..71b75c6c 100755 --- a/onionr/static-data/www/mail/mail.js +++ b/onionr/static-data/www/mail/mail.js @@ -24,8 +24,27 @@ threadPlaceholder = document.getElementById('threadPlaceholder') tabBtns = document.getElementById('tabBtns') threadContent = {} myPub = httpGet('/getActivePubkey') +replyBtn = document.getElementById('replyBtn') -function openThread(bHash, sender, date, sigBool){ +function openReply(bHash){ + var inbox = document.getElementsByClassName('threadEntry') + var entry = '' + var friendName = '' + var key = '' + for(var i = 0; i < inbox.length; i++) { + if (inbox[i].getAttribute('data-hash') === bHash){ + entry = inbox[i] + } + } + if (entry.getAttribute('data-nameSet') == 'true'){ + document.getElementById('friendSelect').value = entry.getElementsByTagName('input')[0].value + } + key = entry.getAttribute('data-pubkey') + document.getElementById('draftID').value = key + setActiveTab('send message') +} + +function openThread(bHash, sender, date, sigBool, pubkey){ var messageDisplay = document.getElementById('threadDisplay') var blockContent = httpGet('/getblockbody/' + bHash) document.getElementById('fromUser').value = sender @@ -43,6 +62,9 @@ function openThread(bHash, sender, date, sigBool){ } sigEl.innerText = sigMsg overlay('messageDisplay') + replyBtn.onclick = function(){ + openReply(bHash) + } } function setActiveTab(tabName){ @@ -60,7 +82,7 @@ function setActiveTab(tabName){ } } -function loadInboxEntrys(bHash){ +function loadInboxEntries(bHash){ fetch('/getblockheader/' + bHash, { headers: { "token": webpass @@ -87,11 +109,14 @@ function loadInboxEntrys(bHash){ validSig.innerText = 'Signature Validity: Bad' validSig.style.color = 'red' } + entry.setAttribute('data-nameSet', true) if (senderInput.value == ''){ senderInput.value = resp['meta']['signer'] + entry.setAttribute('data-nameSet', false) } bHashDisplay.innerText = bHash.substring(0, 10) - entry.setAttribute('hash', bHash) + entry.setAttribute('data-hash', bHash) + entry.setAttribute('data-pubkey', resp['meta']['signer']) senderInput.readOnly = true dateStr.innerText = humanDate.toString() if (metadata['subject'] === undefined || metadata['subject'] === null) { @@ -110,7 +135,7 @@ function loadInboxEntrys(bHash){ entry.classList.add('threadEntry') entry.onclick = function(){ - openThread(entry.getAttribute('hash'), senderInput.value, dateStr.innerText, resp['meta']['validSig']) + openThread(entry.getAttribute('data-hash'), senderInput.value, dateStr.innerText, resp['meta']['validSig'], entry.getAttribute('data-pubkey')) } }.bind(bHash)) @@ -127,7 +152,7 @@ function getInbox(){ threadPlaceholder.style.display = 'none' showed = true } - loadInboxEntrys(pms[i]) + loadInboxEntries(pms[i]) } if (! showed){ threadPlaceholder.style.display = 'block' @@ -145,6 +170,9 @@ function getSentbox(){ var entry = document.createElement('div') var entryUsed; for(var k in resp) keys.push(k); + if (keys.length == 0){ + threadPart.innerHTML = "nothing to show here yet." + } for (var i = 0; i < keys.length; i++){ var entry = document.createElement('div') var obj = resp[i]; @@ -195,7 +223,6 @@ tabBtns.onclick = function(event){ setActiveTab(event.target.innerText.toLowerCase()) } - var idStrings = document.getElementsByClassName('myPub') for (var i = 0; i < idStrings.length; i++){ if (idStrings[i].tagName.toLowerCase() == 'input'){ diff --git a/onionr/static-data/www/shared/main/style.css b/onionr/static-data/www/shared/main/style.css index 65c378eb..ae4d87db 100755 --- a/onionr/static-data/www/shared/main/style.css +++ b/onionr/static-data/www/shared/main/style.css @@ -168,4 +168,8 @@ body{ .successBtn{ background-color: #4CAF50; color: black; +} + +.primaryBtn{ + background-color:#396BAC; } \ No newline at end of file diff --git a/onionr/tests/test_database_actions.py b/onionr/tests/test_database_actions.py new file mode 100644 index 00000000..76a1350c --- /dev/null +++ b/onionr/tests/test_database_actions.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +import sys, os +sys.path.append(".") +import unittest, uuid, sqlite3 +TEST_DIR = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/' +print("Test directory:", TEST_DIR) +os.environ["ONIONR_HOME"] = TEST_DIR +from urllib.request import pathname2url +import core, onionr + +c = core.Core() + +class OnionrTests(unittest.TestCase): + + def test_address_add(self): + testAddresses = ['facebookcorewwwi.onion', '56kmnycrvepfarolhnx6t2dvmldfeyg7jdymwgjb7jjzg47u2lqw2sad.onion', '5bvb5ncnfr4dlsfriwczpzcvo65kn7fnnlnt2ln7qvhzna2xaldq.b32.i2p'] + for address in testAddresses: + c.addAddress(address) + dbAddresses = c.listAdders() + for address in testAddresses: + self.assertIn(address, dbAddresses) + + invalidAddresses = [None, '', ' ', '\t', '\n', ' test ', 24, 'fake.onion', 'fake.b32.i2p'] + for address in invalidAddresses: + try: + c.addAddress(address) + except TypeError: + pass + dbAddresses = c.listAdders() + for address in invalidAddresses: + self.assertNotIn(address, dbAddresses) + + def test_address_info(self): + adder = 'nytimes3xbfgragh.onion' + c.addAddress(adder) + self.assertNotEqual(c.getAddressInfo(adder, 'success'), 1000) + c.setAddressInfo(adder, 'success', 1000) + self.assertEqual(c.getAddressInfo(adder, 'success'), 1000) + +unittest.main() \ No newline at end of file