* Added full utf-8 support via base85

* removed connection established message, apps can send that themselves (yam util does)
This commit is contained in:
Kevin Froman 2020-04-30 14:44:31 -05:00
parent 0dd9c1e9ac
commit e658da13be
7 changed files with 77 additions and 20 deletions

View File

@ -2,6 +2,12 @@
This project uses Semantic Versioning This project uses Semantic Versioning
## 2.0.0
* Added full utf-8 support via base85
* removed connection established message, apps can send that themselves (yam util does)
## 1.2.0 ## 1.2.0
* finished basic client tests * finished basic client tests

View File

@ -7,7 +7,7 @@ with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f:
packages = find_packages(exclude=['contrib', 'docs', 'tests']) packages = find_packages(exclude=['contrib', 'docs', 'tests'])
setup(name='youandme', setup(name='youandme',
version='1.2.0', version='2.0.0',
description='Simple private data sharing via bytearrays, Tor tunneling and metadata paranoia', description='Simple private data sharing via bytearrays, Tor tunneling and metadata paranoia',
long_description=long_description, long_description=long_description,
long_description_content_type='text/markdown', long_description_content_type='text/markdown',

View File

@ -19,6 +19,7 @@ except ModuleNotFoundError:
from youandme.commands import terminator from youandme.commands import terminator
from youandme.server import server from youandme.server import server
from youandme.client import client from youandme.client import client
from youandme.stream import encode_and_send, decoded_recv_stream
class Connection: class Connection:
@ -82,7 +83,7 @@ def connector(host, send_data, recv_data,
def chat(mode, send_data, recv_data, alpha): def chat(mode, send_data, recv_data, alpha):
print("A notice will be shown when connection is established," + print("A notice will be shown when connection is established, " +
"but messages may be typed now.") "but messages may be typed now.")
display_buffer = [] display_buffer = []
@ -94,17 +95,32 @@ def chat(mode, send_data, recv_data, alpha):
print(_Address.address) print(_Address.address)
def display_new(): def display_new():
for message in get_messages buffer = []
while True:
try:
for message in decoded_recv_stream(recv_data, 0.5):
if alpha:
for c in message:
c = c.decode('utf-8')
if c not in printable:
continue
if len(buffer) < 1000:
buffer.append(c)
print("\033[1;33m" + "".join(buffer) + "\033[0m")
else:
print("\033[1;33m" + message.decode('utf-8') + "\033[0m")
except ValueError:
pass
Thread(target=display_new, daemon=True).start() Thread(target=display_new, daemon=True).start()
def make_message(): def make_message():
while True: while True:
new = input("\033[0m").encode('utf-8') # nosec new = input("\033[0m").encode('utf-8') # nosec
for b in new: encode_and_send(send_data, new)
send_data.append(b)
send_data.append(ord(b"\n"))
Thread(target=make_message, daemon=True).start() Thread(target=make_message, daemon=True).start()
encode_and_send(send_data, "Connection established")
while True: while True:
try: try:
if not Connection.connected: if not Connection.connected:

View File

@ -4,7 +4,6 @@ from time import sleep
import socks import socks
from .commands import garbage_character from .commands import garbage_character
from .commands import WELCOME_MESSAGE
def client(delay: int, hs_id: str, socks_port, send_data: bytearray, recv_data: bytearray, connection: "Connection"): def client(delay: int, hs_id: str, socks_port, send_data: bytearray, recv_data: bytearray, connection: "Connection"):
@ -16,8 +15,6 @@ def client(delay: int, hs_id: str, socks_port, send_data: bytearray, recv_data:
hs_id += '.onion' hs_id += '.onion'
def send_loop(): def send_loop():
for i in WELCOME_MESSAGE:
send_data.append(ord(i))
while True: while True:
to_send = None to_send = None
if send_data: if send_data:

View File

@ -7,7 +7,6 @@ if typing.TYPE_CHECKING:
from stem.control import Controller from stem.control import Controller
from.commands import garbage_character from.commands import garbage_character
from.commands import WELCOME_MESSAGE
def server(delay: int, controller: 'Controller', socket_conn, send_data: bytearray, recv_data: bytearray, connection: "Connection"): def server(delay: int, controller: 'Controller', socket_conn, send_data: bytearray, recv_data: bytearray, connection: "Connection"):
@ -28,7 +27,6 @@ def server(delay: int, controller: 'Controller', socket_conn, send_data: bytearr
socket_conn.sendall(chr(char).encode('utf-8')) socket_conn.sendall(chr(char).encode('utf-8'))
except OSError: except OSError:
connection.connected = False connection.connected = False
first_rec = True
with socket_conn: with socket_conn:
Thread(target=send_loop, daemon=True).start() Thread(target=send_loop, daemon=True).start()
while True: while True:
@ -38,10 +36,7 @@ def server(delay: int, controller: 'Controller', socket_conn, send_data: bytearr
connection.connected = False connection.connected = False
break break
if not data: break if not data: break
if first_rec:
for i in WELCOME_MESSAGE:
send_data.append(ord(i))
first_rec = False
if data != garbage_character and data: if data != garbage_character and data:
for i in data: for i in data:
recv_data.append(i) recv_data.append(i)

View File

@ -1,19 +1,33 @@
from base64 import b85encode, b85decode from base64 import b85encode, b85decode
from time import sleep from time import sleep
import sys
from typing import Union
from youandme.commands import terminator from youandme.commands import terminator
_b85alphabet = (b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" _b85alphabet = bytearray(b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
b"abcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~") b"abcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~")
def decoded_recv_stream(raw_stream: bytearray, delay_seconds: int, max_buffer_size=) -> bytes: def decoded_recv_stream(raw_stream: bytearray, delay_seconds: int) -> bytes:
while True: while True:
for byte in raw_stream: for byte in raw_stream:
if byte == terminator: if byte == terminator:
yield b85decode(raw_stream[:len(raw_stream) - 1]) raw_stream.pop()
yield b85decode(raw_stream)
raw_stream.clear() raw_stream.clear()
continue continue
if byte not in _b85alphabet:
raise ValueError('Not valid base85 encoding')
sleep(delay_seconds) sleep(delay_seconds)
def encode_and_send(send_stream: bytearray, data: Union[bytes, str]):
try:
data = data.encode('utf-8')
except AttributeError:
pass
encoded = b85encode(data)
for c in encoded:
send_stream.append(c)
send_stream.append(terminator)

View File

@ -14,6 +14,7 @@ def add_encoded_to_bytes_array_valid(message, array: bytearray):
array.append(m) array.append(m)
array.append(terminator) array.append(terminator)
class TestStream(unittest.TestCase): class TestStream(unittest.TestCase):
def test_stream_get(self): def test_stream_get(self):
@ -27,8 +28,36 @@ class TestStream(unittest.TestCase):
c = 0 c = 0
for message in stream.decoded_recv_stream(recv_data, 1): for message in stream.decoded_recv_stream(recv_data, 1):
self.assertEqual(message.decode('utf-8'), data) self.assertEqual(message.decode('utf-8'), data)
self.assertNotIn(terminator, message)
break break
def test_stream_send(self):
send_data = bytearray()
recv_data = bytearray()
data = "hello world"
data_bytes = data.encode('utf-8')
encoded = b85encode(data_bytes)
stream.encode_and_send(send_data, data)
for i in send_data:
if i != terminator:
self.assertIn(chr(i).encode('utf-8'), encoded)
self.assertEqual(data_bytes, b85decode(send_data[:len(send_data) - 1]))
def test_stream_send_has_terminator(self):
send_data = bytearray()
recv_data = bytearray()
data = "hello world"
data_bytes = data.encode('utf-8')
encoded = b85encode(data_bytes)
stream.encode_and_send(send_data, data)
self.assertEqual(send_data.pop(), terminator)
unittest.main() unittest.main()