* refactored blockmetadata

* be more careful with block type length
+ work on chat
This commit is contained in:
Kevin Froman 2019-08-09 15:07:32 -05:00
parent 8c7319048d
commit 7c02f6fff1
15 changed files with 203 additions and 125 deletions

View File

@ -27,6 +27,8 @@ API_VERSION = '0' # increments of 1; only change when something fundamental abou
MIN_PY_VERSION = 6 MIN_PY_VERSION = 6
DEVELOPMENT_MODE = True DEVELOPMENT_MODE = True
MAX_BLOCK_TYPE_LENGTH = 15
platform = platform.system() platform = platform.system()
if platform == 'Windows': if platform == 'Windows':
SCRIPT_NAME = 'run-windows.bat' SCRIPT_NAME = 'run-windows.bat'

View File

@ -54,7 +54,7 @@ class ClientAPISecurity:
def after_req(resp): def after_req(resp):
# Security headers # Security headers
resp = httpheaders.set_default_onionr_http_headers(resp) resp = httpheaders.set_default_onionr_http_headers(resp)
if request.endpoint == 'site': if request.endpoint == 'siteapi.site':
resp.headers['Content-Security-Policy'] = "default-src 'none'; style-src data: 'unsafe-inline'; img-src data:" resp.headers['Content-Security-Policy'] = "default-src 'none'; style-src data: 'unsafe-inline'; img-src data:"
else: else:
resp.headers['Content-Security-Policy'] = "default-src 'none'; script-src 'self'; object-src 'none'; style-src 'self'; img-src 'self'; media-src 'none'; frame-src 'none'; font-src 'none'; connect-src 'self'" resp.headers['Content-Security-Policy'] = "default-src 'none'; script-src 'self'; object-src 'none'; style-src 'self'; img-src 'self'; media-src 'none'; frame-src 'none'; font-src 'none'; connect-src 'self'"

View File

@ -42,11 +42,11 @@ def add_file(singleBlock=False, blockType='bin'):
logger.info('Adding file... this might take a long time.', terminal=True) logger.info('Adding file... this might take a long time.', terminal=True)
try: try:
with open(filename, 'rb') as singleFile: with open(filename, 'rb') as singleFile:
blockhash = insert.insert_block(base64.b64encode(singleFile.read()), header=blockType) blockhash = insert(base64.b64encode(singleFile.read()), header=blockType)
if len(blockhash) > 0: if len(blockhash) > 0:
logger.info('File %s saved in block %s' % (filename, blockhash), terminal=True) logger.info('File %s saved in block %s' % (filename, blockhash), terminal=True)
except: except Exception as e:
logger.error('Failed to save file in block.', timestamp = False, terminal=True) logger.error('Failed to save file in block ' + str(e), timestamp = False, terminal=True)
else: else:
logger.error('%s add-file <filename>' % sys.argv[0], timestamp = False, terminal=True) logger.error('%s add-file <filename>' % sys.argv[0], timestamp = False, terminal=True)

View File

@ -0,0 +1,24 @@
'''
Onionr - Private P2P Communication
Module to work with block metadata
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
from . import hasblock, fromdata, process
has_block = hasblock.has_block
process_block_metadata = process.process_block_metadata
get_block_metadata_from_data = fromdata.get_block_metadata_from_data

View File

@ -0,0 +1,49 @@
'''
Onionr - Private P2P Communication
Return a useful tuple of (metadata (header), meta, and data) by accepting raw block data
'''
'''
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 json
def get_block_metadata_from_data(block_data):
'''
accepts block contents as string, returns a tuple of
metadata, meta (meta being internal metadata, which will be
returned as an encrypted base64 string if it is encrypted, dict if not).
'''
meta = {}
metadata = {}
data = block_data
try:
block_data = block_data.encode()
except AttributeError:
pass
try:
metadata = json.loads(block_data[:block_data.find(b'\n')].decode())
except json.decoder.JSONDecodeError:
pass
else:
data = block_data[block_data.find(b'\n'):].decode()
if not metadata['encryptType'] in ('asym', 'sym'):
try:
meta = json.loads(metadata['meta'])
except KeyError:
pass
meta = metadata['meta']
return (metadata, meta, data)

View File

@ -0,0 +1,42 @@
'''
Onionr - Private P2P Communication
Returns a bool if a block is in the block metadata db or not
'''
'''
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 sqlite3
from coredb import dbfiles
import onionrexceptions
from .. import stringvalidators
def has_block(hash: str) -> bool:
'''
Check for new block in the block meta db
'''
conn = sqlite3.connect(dbfiles.block_meta_db)
c = conn.cursor()
if not stringvalidators.validate_hash(hash):
raise onionrexceptions.InvalidHexHash("Invalid hash")
for result in c.execute("SELECT COUNT() FROM hashes WHERE hash = ?", (hash,)):
if result[0] >= 1:
conn.commit()
conn.close()
return True
else:
conn.commit()
conn.close()
return False
return False

View File

@ -1,7 +1,7 @@
''' '''
Onionr - Private P2P Communication Onionr - Private P2P Communication
Module to fetch block metadata from raw block data and process it Process block metadata with relevant actions
''' '''
''' '''
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -17,45 +17,19 @@
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, sqlite3
import logger, onionrevents
from onionrusers import onionrusers
from etc import onionrvalues from etc import onionrvalues
import onionrblockapi import onionrblockapi
from . import epoch, stringvalidators, bytesconverter from .. import epoch, bytesconverter
from coredb import dbfiles, blockmetadb from coredb import blockmetadb
def get_block_metadata_from_data(blockData): import logger
''' import onionrevents
accepts block contents as string, returns a tuple of
metadata, meta (meta being internal metadata, which will be
returned as an encrypted base64 string if it is encrypted, dict if not).
'''
meta = {}
metadata = {}
data = blockData
try:
blockData = blockData.encode()
except AttributeError:
pass
try: def process_block_metadata(blockHash: str):
metadata = json.loads(blockData[:blockData.find(b'\n')].decode())
except json.decoder.JSONDecodeError:
pass
else:
data = blockData[blockData.find(b'\n'):].decode()
if not metadata['encryptType'] in ('asym', 'sym'):
try:
meta = json.loads(metadata['meta'])
except KeyError:
pass
meta = metadata['meta']
return (metadata, meta, data)
def process_block_metadata(blockHash):
''' '''
Read metadata from a block and cache it to the block database Read metadata from a block and cache it to the block database
blockHash -> sha3_256 hex formatted hash of Onionr block
''' '''
curTime = epoch.get_rounded_epoch(roundS=60) curTime = epoch.get_rounded_epoch(roundS=60)
myBlock = onionrblockapi.Block(blockHash) myBlock = onionrblockapi.Block(blockHash)
@ -67,10 +41,13 @@ def process_block_metadata(blockHash):
signer = bytesconverter.bytes_to_str(myBlock.signer) signer = bytesconverter.bytes_to_str(myBlock.signer)
valid = myBlock.verifySig() valid = myBlock.verifySig()
if myBlock.getMetadata('newFSKey') is not None: if myBlock.getMetadata('newFSKey') is not None:
onionrusers.OnionrUser(signer).addForwardKey(myBlock.getMetadata('newFSKey')) try:
onionrusers.OnionrUser(signer).addForwardKey(myBlock.getMetadata('newFSKey'))
except onionrexceptions.InvalidPubkey:
logger.warn('%s has invalid forward secrecy key to add: %s' % (signer, myBlock.getMetadata('newFSKey')))
try: try:
if len(blockType) <= 10: if len(blockType) <= onionrvalues.MAX_BLOCK_TYPE_LENGTH:
blockmetadb.update_block_info(blockHash, 'dataType', blockType) blockmetadb.update_block_info(blockHash, 'dataType', blockType)
except TypeError: except TypeError:
logger.warn("Missing block information") logger.warn("Missing block information")
@ -83,27 +60,4 @@ def process_block_metadata(blockHash):
expireTime = onionrvalues.OnionrValues().default_expire + curTime expireTime = onionrvalues.OnionrValues().default_expire + curTime
finally: finally:
blockmetadb.update_block_info(blockHash, 'expire', expireTime) blockmetadb.update_block_info(blockHash, 'expire', expireTime)
if not blockType is None:
blockmetadb.update_block_info(blockHash, 'dataType', blockType)
onionrevents.event('processblocks', data = {'block': myBlock, 'type': blockType, 'signer': signer, 'validSig': valid}) onionrevents.event('processblocks', data = {'block': myBlock, 'type': blockType, 'signer': signer, 'validSig': valid})
else:
pass
def has_block(hash):
'''
Check for new block in the list
'''
conn = sqlite3.connect(dbfiles.block_meta_db)
c = conn.cursor()
if not stringvalidators.validate_hash(hash):
raise Exception("Invalid hash")
for result in c.execute("SELECT COUNT() FROM hashes WHERE hash = ?", (hash,)):
if result[0] >= 1:
conn.commit()
conn.close()
return True
else:
conn.commit()
conn.close()
return False
return False

View File

@ -68,3 +68,6 @@ def get_messages(peer):
existing = list(existing) existing = list(existing)
key_store.delete('r' + peer) key_store.delete('r' + peer)
return Response(json.dumps(existing)) return Response(json.dumps(existing))
#@flask_blueprint.route('/chatapi/connect/<peer>')
#def create_connection(peer)

View File

@ -36,58 +36,3 @@ def exit_with_error(text=''):
if text != '': if text != '':
logger.error(text) logger.error(text)
sys.exit(1) sys.exit(1)
class Chat:
def __init__(self, pluginapi):
self.peer = None
self.transport = None
self.shutdown = False
self.pluginapi = pluginapi
def _sender_loop(self):
print('Enter a message to send, with ctrl-d or -s on a new line.')
print('-c on a new line or ctrl-c stops')
message = ''
while not self.shutdown:
try:
message += input()
if message == '-s':
raise EOFError
elif message == '-c':
raise KeyboardInterrupt
else:
message += '\n'
except EOFError:
message = json.dumps({'m': message, 't': epoch.get_epoch()})
print(basicrequests.do_post_request(self.pluginapi.onionr, 'http://%s/chat/sendto' % (self.transport,), port=self.socks, data=message))
message = ''
except KeyboardInterrupt:
self.shutdown = True
def create(self):
try:
peer = sys.argv[2]
if not stringvalidators.validate_pub_key(peer):
exit_with_error('Invalid public key specified')
except IndexError:
exit_with_error('You must specify a peer public key')
self.peer = peer
# Ask peer for transport address by creating block for them
peer_transport_address = bootstrapservice.bootstrap_client_service(peer)
self.transport = peer_transport_address
self.socks = config.get('tor.socksport')
print('connected with', peer, 'on', peer_transport_address)
if basicrequests.do_get_request('http://%s/ping' % (peer_transport_address,), ignoreAPI=True, port=self.socks) == 'pong!':
print('connected', peer_transport_address)
threading.Thread(target=self._sender_loop).start()
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
chat = Chat(pluginapi)
return

View File

@ -60,9 +60,9 @@ def list_sentbox():
deleted = kv.get('deleted_mail') deleted = kv.get('deleted_mail')
if deleted is None: if deleted is None:
deleted = [] deleted = []
for x in list_copy: for sent in list_copy:
if x['hash'] in deleted: if sent['hash'] in deleted:
sentbox_list.remove(x) sentbox_list.remove(sent)
continue continue
x['name'] = contactmanager.ContactManager(x['peer'], saveUser=False).get_info('name') sent['name'] = contactmanager.ContactManager(sent['peer'], saveUser=False).get_info('name')
return json.dumps(sentbox_list) return json.dumps(sentbox_list)

View File

@ -0,0 +1,5 @@
{
"name" : "searchengine",
"version" : "0.0.0",
"author" : "0gitnick"
}

View File

@ -0,0 +1,24 @@
'''
Onionr - Private P2P Communication
Search engine plugin for Onionr, to search for
'''
'''
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/>.
'''
plugin_name = 'searchengine'

View File

@ -14,6 +14,7 @@
<link rel="stylesheet" href="/chat/css/convos.css"> <link rel="stylesheet" href="/chat/css/convos.css">
<script defer src='/shared/navbar.js'></script> <script defer src='/shared/navbar.js'></script>
<script defer src='/shared/misc.js'></script> <script defer src='/shared/misc.js'></script>
<script defer src='/chat/messages/js'></script>
<script defer src='/chat/js/message-feed.js'></script> <script defer src='/chat/js/message-feed.js'></script>
<script defer src='/chat/js/main.js'></script> <script defer src='/chat/js/main.js'></script>
</head> </head>

View File

@ -17,5 +17,8 @@
along with this program. If not, see <https://www.gnu.org/licenses/> along with this program. If not, see <https://www.gnu.org/licenses/>
*/ */
let MessageCache = class { let MessageCache = class {
constructor(user) {
this.user = user
this.cache = [] // array of Messages
}
} }

View File

@ -0,0 +1,26 @@
/*
Onionr - Private P2P Communication
Onionr chat message objects
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/>
*/
let Message = class {
constructor(text, to, time){
this.text = text // string
this.to = to // bool. False = not outgoing
this.time = time // epoch int
}
}