Remove unused interface

Add all options
Bugs fixed
This commit is contained in:
lsw 2022-02-02 23:08:25 +01:00
parent c421933780
commit 8abd2b2b41
11 changed files with 424 additions and 121 deletions

114
ca.crt
View File

@ -1,68 +1,68 @@
-----BEGIN CERTIFICATE-----
MIIGATCCA+mgAwIBAgIUKx8oo/wc8VCjZI4ueEY4vlp3KKQwDQYJKoZIhvcNAQEL
MIIF9TCCA92gAwIBAgIUQaJLS561XqG19oy1TnVL7da4P8YwDQYJKoZIhvcNAQEL
BQAwcTELMAkGA1UEBhMCQkUxDjAMBgNVBAgMBUxJRUdFMRMwEQYDVQQKDApJTGlr
ZVN3aWxhMRYwFAYDVQQLDA1DeWJlclNlY3VyaXR5MSUwIwYDVQQDDBxUcnVzdFN3
aWxhIENlcnRpZmljYXQgUmFjaW5lMB4XDTIyMDIwMTE5MzU0NVoXDTMxMTIxMTE5
MzU0NVowgYYxCzAJBgNVBAYTAkJFMQ4wDAYDVQQIDAVMSUVHRTEOMAwGA1UEBwwF
aWxhIENlcnRpZmljYXQgUmFjaW5lMB4XDTIyMDIwMjE0NDc0MloXDTMxMTIxMjE0
NDc0MlowgZIxCzAJBgNVBAYTAkJFMQ4wDAYDVQQIDAVMSUVHRTEOMAwGA1UEBwwF
TElFR0UxEzARBgNVBAoMCklMaWtlU3dpbGExFjAUBgNVBAsMDUN5YmVyU2VjdXJp
dHkxKjAoBgNVBAMMIUxhYm8yMDIyIENlcnRpZmljYXQgSW50ZXJtZWRpYWlyZTCC
AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANeG9SlV1fhXjfj9sVcnzO8q
HqYt/2+j9qQSA7479Y/ZMd+3bZ3V7KAwgrwrrnOeAynCplbcHaWfPwSYrAixZ3Lz
7Kj/Opy5C1P3fOuFrrSFjqRPn+ssvhvgtQzQgqN6lYFPzW0q4gIvHcQaaTSyWtmP
8zdFbJmzklPaGugZ9WLeOTMtetg3Nf0vTcIoC8mlfSwXUJUxxXXwlHyO/9TuRtya
2aFiuGHuk4Oh2aqthkXTz309xTzGAcjRDzlzjAi7Z5GtyD0Npcdr3GVNTXzIneLc
u1FtVC0dsLINg9r/SiphAIBVFoc1psbSVW9Tuy9vaIlSkbJlFXRvEcIh/uzKP6Wy
2or1pXg3IoJkDG6jLUid4Nlfwfwopm0vrFbefN/7flbICm4ADcrlgXC9fwRrgUzK
fa1dGOVe12s6oHJ/RuPbE7QdaJtgAu+i1VWLSmr/MxXWJGMQDljmy91FAZmjk9V8
tlDL1/qKoH6j6iA31l4IZ23buDRuaFcY1iS8L+QNNcRB+qFmU8zlmVCjeHMUoPfD
EVh25WagiHYcV2Pt1lqWJYjl53HYZI2coYo+hngwVAVFX90Sp7Ah5cDUp2AAeIU/
nHB31GAciQ5xflz8ApNTw3G8wBXYVHL7f98K1SKrdnhHE+Rzc58r1b7LRvJhiHIE
5x1DdhNYruRU7D3DyVF/AgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgEN
BB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSNGyiz
5FCsuBl98u51IuTlrx+DwzAfBgNVHSMEGDAWgBQOFchEMlX2QrcgELQGbqwxgIy6
czANBgkqhkiG9w0BAQsFAAOCAgEAWuUVIm4lDD0wvKA0eYCwQf+iknt4/XsA3nId
06P9DMsFvVE9CGVFUbHRftiL45e6cVM2+KrwPOjpeu7DES+xtDSH9TBpYP8WsW6k
YeJiw/C3Lhl8YdMEjHV927UMGPXaj4foFeh5ls8XPeEkruG7zriYLm2qBxY8XQR0
8sIHvyg9Aucp+d+trR8pcT7A9AszIn4OncUymPNwfN1qSpAQyDye3caqOQyKXAUB
1RUnaUm06tPAvFGvSKVwIhTNgFEsvGujnNuBrCOT7soXJtuv5GgHS4A9nD6Y5DdV
ihKYRAC6XIsQwgRHUeKQYNtNPkvdE8PqSx3jW/UKhlDBDKy7KN7FXiMPoIxxKlOl
IRSYvNXZHnkspgOxYDs+YtC+0IUtdormSodQekbjY4jPjW685AWRDN5zVjK2FUaY
ZHYFc9HGOuS7okMODjjl+9QIZAlhc5WlWwsrVnsKAvN7yNemF943LZaOQCZIDKVS
KpRtjgB5pt6uh0FkLanKWzGP1xyqAlQnEUJB8WzqCHgEkTA5eapfyw1VR9CBvr55
6LXd9gX0RrIE3h3WUvTSEVjAymmIkfRBuVoGPUgZT5VRvMqKeQAXovE0K8m9tRtP
cGjz8ce8WERiTXB5dQuq6G6DUQulMatw5qbOjOCxw3bKUKN+rbHLSTie2iQ8bnr3
JBVmbAQ=
dHkxNjA0BgNVBAMMLUxhYm8yMDIyIERldmVsb3BtZW50IENlcnRpZmljYXQgSW50
ZXJtZWRpYWlyZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOIkDI64
cT6RN2hwTh81+Di5CqPJevY9ulR3nyR/bdI/UEvZ1KBZ6SDZjO2gWwyTdSaeTHGO
xKDpd6IYuqnqPU1XzCM2i4nqm9Fdyk3gKjlJxearIa52Nz2hTiM5D48UN9wfzAZH
8qjijRDfZ6+6Jzj+FloWWfuGUSPZlEufghrGxB4QccHT2YWYDoNNaY6qUXH+rRrN
kQtq8X080IIHj5At0wfd35ZPV7qIet7WawrcSeNTzVRwFw++2GkjWeICZvazQwYO
oo9QoTd844cGYMvfIEK4ZUjiaBux5QBYfUC12HZSVP4aKIUP6swDj02ec4QeB5A1
kzTDQffmPhYKh7BlUuf/WWtRVvoSUVsjvjnRquVTTQMU4WTE/nXIyjqHsZxn7xzM
jFWkdMuV6BYycWCJ+smTPqIRYZsFM/UrMz9+PgDSOWUfhU4e8kaQuuSGP/SuOUq3
PsFhlaop+b5+kpGD9J4CwM+uHJ2GlNj8P6bqtzdk5f35/IghagEIjagiCjZsOAuA
VdDUxQ6aqxKDr9VFy4C4U7lu8qWht7eXjEoa511YSDsgs0PmpjutjEvS9qky9lUq
3T9FkHsDLfH2zjp/7KykTRCmGr7IIcSblTDJaBh/LjMMdbY3PKP9McDusanHg0/U
bgWrguqJEjSoTRUKRPMcyXr77xKQhfMGaUTfAgMBAAGjYzBhMB0GA1UdDgQWBBRt
CVdNN96jLKZC5o6Ww+t6FqL74jAfBgNVHSMEGDAWgBSgLzmYK4ju6ocXHm5J3MlH
lN+4YDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0B
AQsFAAOCAgEAT7WOIyY3Kdd2QK5h0/bs8xvGU1HJ7dtwAhSlgHdJ3OC6Zc2o4998
y6el4QrpCd8pNMzBbZcQiNLsywP8Xe7MiVuzUjNB9Y75+Ml9qMxsACyQlO6GQ1sN
pyE8mZitEYeW+YvTK864rWUYWMCVKHM0hWymK2QVlA17g07ZhaJ6OPsK8Fa/OkNL
9MXghgqitpGY8aXy8sd0uipz0NcgNzEvmgYv1S1zL6RxEuZ2hdknm+vlW8cN9Efj
lvZXBGGg6TrFLkY5g5sCgf2bxFeiULOLMGSF/wkj4XPXhqt6BH635jLA3UUVdapq
fhgVIp/qWmz7ouJN7E+jVfVK9AfJAqb33CjJSn5n0plJSO+OfwARlhZPRpH2kXOe
6Sl0NXLSBOHk8ruufQrTLl10c9SYxjbfDSHQCVJ8VTv9/HtE4+nG/I3KNAIo/WMK
8hbskzDe31tRz5V0uv0J/plrW8pNbqRqXTbvT4NQc5WYBKZSJ5RaTPA+P6ZEWoWn
TOYKq3MiRqTRE8eeD52LKMnw8/du8jWqgG/bc6ti7DpZf+aUNF6ru9DmzEJYksOc
c+n7Sz2ijCB2G4sSchnL+ueXIzqWSbrPiTVoWjjiBux1ryqMVg6rtFPJ7gvVgOda
4++FIs2P9AYceoyBuRHlGZGNuGNfxu2NH/pjLvqqaKxUMyCBkcONIxI=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFwzCCA6ugAwIBAgIUKx8oo/wc8VCjZI4ueEY4vlp3KKMwDQYJKoZIhvcNAQEL
MIIF0zCCA7ugAwIBAgIUQaJLS561XqG19oy1TnVL7da4P8UwDQYJKoZIhvcNAQEL
BQAwcTELMAkGA1UEBhMCQkUxDjAMBgNVBAgMBUxJRUdFMRMwEQYDVQQKDApJTGlr
ZVN3aWxhMRYwFAYDVQQLDA1DeWJlclNlY3VyaXR5MSUwIwYDVQQDDBxUcnVzdFN3
aWxhIENlcnRpZmljYXQgUmFjaW5lMB4XDTIyMDIwMTE5MzI0NloXDTI1MDEzMTE5
MzI0NlowcTELMAkGA1UEBhMCQkUxDjAMBgNVBAgMBUxJRUdFMRMwEQYDVQQKDApJ
aWxhIENlcnRpZmljYXQgUmFjaW5lMB4XDTIyMDIwMjE0NDQzN1oXDTI1MDIwMTE0
NDQzN1owcTELMAkGA1UEBhMCQkUxDjAMBgNVBAgMBUxJRUdFMRMwEQYDVQQKDApJ
TGlrZVN3aWxhMRYwFAYDVQQLDA1DeWJlclNlY3VyaXR5MSUwIwYDVQQDDBxUcnVz
dFN3aWxhIENlcnRpZmljYXQgUmFjaW5lMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
MIICCgKCAgEAqNTJ9/KsR+LyOGgxE67sx1SGqo7obEH80oj+q6Vcair4/xI2sb0V
kQaQxrAwvg4LwsZ+jpJmUt+2sCfxIF2PwHNAnBuNYa/fW4Y/LFS9N4OIdOiLvjJ6
Meuwjkv3M5n9DZ0cf0UukhhCBkOYn6BZ8rXy4udYM/5uJhfDgJbymrzc6h/83bFI
1v+vR08HSnjwnkAs6GGdPvJD5HgZZcHM+RCahlSJ+bRuu8hQNIa8oLiIdhN+3rzi
qO+FwGfZO671Ad3sgeK9NKrWR3ciN76sS7u4pn8mkb33E5vD5dkI3x1fyTJbtVzB
f7jakMJUVmU/eIoIT+8b4OVOEQG4Hkqp6spbzOAyj39tD12I2nVvQ1mWzAuMG3uI
GiRiEXOhIhCGSQIIpA0yMHed4wqLxVsCoN9BwRh7Q9jgo9nubvQlv071ttZMh2fC
CBL5ID1bSWYMWkchnhjpCJCbN4QMWgKVHwKAA2jnYmvBPBkLFR0ptLJLRdlxnIVw
iXv/LUwvj78W3RbJmVz6F9CFdS9NXAjLdDi+eL57//EmIwFCyIv7j3pOk0PvQS5p
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
UHNJ9snS7g==
-----END CERTIFICATE-----

View File

@ -1,16 +1,135 @@
from controller.IAppController import *
from net.UnicastConnection import *
from model.Protocol import *
import traceback
import os.path
class AppController(IAppController):
class AppController:
def __init__(self, parser):
self.parser = parser
self.connection = UnicastConnection()
self.window_controller = None
def ssl_ca_path(self, ca_path):
self.connection.set_ca_path(ca_path)
def set_window_controller(self, window_controller):
self.window_controller = window_controller
def on_sign(self, host, port, login, passw, tls, register=False):
print("[AppController::on_sign]")
try:
if not self.connection.is_connected:
print("[AppController::on_sign] connecting ... calling UnicastConnection::connect")
self.connect(host, port, tls)
if not register:
message = self.parser.build_SIGNIN(login, passw)
else:
message = self.parser.build_SIGNUP(login, passw)
self.connection.send_message(message)
line = self.connection.read_line()
message_id = self.parser.parse(line, False)
if message_id == Protocol.PARSE_SIGNOK:
self.window_controller.switch_connected_mode()
self.show_message("Connection done", False)
elif message_id == Protocol.PARSE_SIGNERROR:
self.show_message("Error during SIGN_IN / SIGN_UP", True)
self.on_filelist()
except Exception as ex:
print(ex)
traceback.print_exc()
def get_filename_size_from_item(self, item):
tokens = item.split('!')
if len(tokens) == 2:
return (tokens[0],tokens[1])
else:
return None
def on_filelist(self):
print("[AppController::on_filelist]")
try:
if self.connection.is_connected:
message = self.parser.build_FILELIST()
self.connection.send_message(message)
line = self.connection.read_line()
message_id = self.parser.parse(line, False)
if message_id == Protocol.PARSE_FILES:
tokens = self.parser.parse_FILES(line)
if len(tokens) == 1:
self.window_controller.clear_all_file_on_window()
allfiles = tokens[0].split()
for f in allfiles:
(filename, filesize) = self.get_filename_size_from_item(f)
self.window_controller.add_file_on_window([filename, filesize])
except Exception as ex:
print(ex)
traceback.print_exc()
def on_quit(self):
pass
# if self.connection.is_connected:
# self.connection.send_message(self.parser.buildEXIT())
# if self.client_thread != None:
# self.client_thread.stop_loop()
if self.connection.is_connected:
self.connection.send_message(self.parser.build_SIGNOUT())
def on_fileupload(self, filepath):
if os.path.isfile(filepath):
size = os.path.getsize(filepath)
print(f"[AppController::on_fileupload] file={filepath}; size={size}")
message = self.parser.build_SAVEFILE(os.path.basename(filepath), size)
self.connection.send_message(message)
self.connection.send_file(filepath)
line = self.connection.read_line()
message_id = self.parser.parse(line, False)
if message_id == Protocol.PARSE_SAVEFILEOK:
self.show_message("File saved", False)
self.on_filelist()
elif message_id == Protocol.PARSE_SAVEFILEERROR:
self.show_message("Error during saving file !", True)
else:
self.show_message(f"Error: file {filepath} not found !", True)
def on_filedownload(self, filename, savepath):
if os.path.isdir(savepath):
print(f"[AppController::on_filedownload] file={filename}; path={savepath}")
message = self.parser.build_GETFILE(filename)
self.connection.send_message(message)
line = self.connection.read_line()
message_id = self.parser.parse(line, False)
if message_id == Protocol.PARSE_GETFILEOK:
tokens = self.parser.parse_GETFILEOK(line)
if len(tokens) == 2:
self.connection.receive_file(tokens[0], savepath, int(tokens[1]))
self.show_message("File downloaded !", False)
else:
self.show_message(f"Bad file information\n{tokens}")
elif message_id == Protocol.PARSE_GETFILEERROR:
self.show_message(f"Cannot download the file", True)
else:
self.show_message(f"Error: directory {savepath} not found !", True)
def on_filedelete(self, filename):
print(f"[AppController::on_filedelete] file={filename}")
message = self.parser.build_REMOVEFILE(filename)
self.connection.send_message(message)
line = self.connection.read_line()
message_id = self.parser.parse(line, False)
if message_id == Protocol.PARSE_REMOVEFILEOK:
self.show_message("File deleted successfully !", False)
self.on_filelist()
elif message_id == Protocol.PARSE_REMOVEFILEERROR:
self.show_message("Error while erasing file.", True)
def show_message(self,message, is_error):
self.window_controller.show_message(message, is_error)
def connect(self, host, port, tls):
try:
self.connection.connect(host, port, tls)
if tls and UnicastConnection.STRICT_SSL_VALIDATION:
self.show_message(self.connection.ssl_info, False)
elif tls and not UnicastConnection.STRICT_SSL_VALIDATION:
self.show_message("SSL/TLS enabled, but certificate NOT checked !", False)
else:
self.show_message("No SSL connection", False)
except Exception as ex:
self.show_message(f"Error during connection !\n{ex}", True)
self.connection = UnicastConnection()

View File

@ -1,2 +0,0 @@
class IAppController:
pass

View File

@ -1,2 +0,0 @@
class IEventHandler:
pass

View File

@ -1,10 +1,45 @@
from controller.IMainWindowController import *
class MainWindowController(IEventHandler):
class MainWindowController:
def __init__(self, parser, app_controller):
self.parser = parser
self.app_controller = app_controller
self.app_controller.set_window_controller(self)
self.window = None
def on_quit(self):
self.app_controller.on_quit()
pass
pass
def on_signin(self, host, port, login, passw, tls):
print("[MainWindowController::on_signin] calling AppController::on_sign")
self.app_controller.on_sign(host, port, login, passw, tls)
def on_signup(self, host, port, login, passw, tls):
self.app_controller.on_sign(host, port, login, passw, tls, True)
def on_refreshlist(self):
self.app_controller.on_filelist()
def on_fileupload(self, filepath):
self.app_controller.on_fileupload(filepath)
def on_filedownload(self, filename, savepath):
self.app_controller.on_filedownload(filename, savepath)
def on_filedelete(self, filename):
self.app_controller.on_filedelete(filename)
def show_message(self, message, is_error):
self.window.show_message(message, is_error)
def switch_connected_mode(self):
self.window.connected_mode()
def register_window(self, window):
self.window = window
def clear_all_file_on_window(self):
self.window.remove_all_from_treeview()
def add_file_on_window(self, fileinfo):
self.window.add_file_in_treeview(fileinfo)

View File

@ -1,2 +0,0 @@
class IMainWindow:
pass

View File

@ -1,11 +1,12 @@
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
from gui.IMainWindow import *
from tkinter import filedialog
class MainWindow(IMainWindow):
class MainWindow:
def __init__(self, controller):
self.controller = controller
self.controller.register_window(self)
self.root = tk.Tk()
self.root.title("SecCon - © Louis SWINNEN 2022")
self.root.config(bd=5)
@ -81,9 +82,9 @@ class MainWindow(IMainWindow):
bottom_pane = ttk.Frame(self.root, padding=(5, 0, 5, 0))
bottom_pane.columnconfigure(1, weight=1)
self.bt_filelist = ttk.Button(bottom_pane, text="Refresh list", command=self.file_list)
self.bt_filelist = ttk.Button(bottom_pane, text="Refresh list", command=self.refresh_list)
self.bt_filelist.grid(row=0, column=0, padx=10, pady=2,sticky=tk.E)
self.bt_savefile = ttk.Button(bottom_pane, text="Upload file", command=self.save_file)
self.bt_savefile = ttk.Button(bottom_pane, text="Upload file", command=self.upload_file)
self.bt_savefile.grid(row=0, column=1, padx=10, pady=2,sticky=tk.E)
self.bt_getfile = ttk.Button(bottom_pane, text="Download file", command=self.get_file)
self.bt_getfile.grid(row=0, column=2, padx=10, pady=2,sticky=tk.E)
@ -120,25 +121,84 @@ class MainWindow(IMainWindow):
self.bt_removefile.state(["!disabled"])
def sign_in(self):
pass
def sign_up(self):
pass
if self.check_before_signin():
print("[MainWindow] Calling MainWindowController::on_signin()")
self.controller.on_signin(self.host.get(), int(self.port.get()), self.login.get(), self.passw.get(), self.tls.get())
else:
self.show_message("All fields are mandatory!\nPort is numeric (1025-65535)", True)
def save_file(self):
def sign_up(self):
if self.check_before_signin():
print("[MainWindow] Calling MainWindowController::on_signup()")
self.controller.on_signup(self.host.get(), int(self.port.get()), self.login.get(), self.passw.get(), self.tls.get())
else:
self.show_message("All fields are mandatory!\nPort is numeric (1025-65535)", True)
def check_before_signin(self):
try:
host = self.host.get()
port = int(self.port.get())
login = self.login.get()
passw = self.passw.get()
tls = self.tls.get()
if(not(host and host.strip())) or port <= 1024 or port >= 65536 or not (login and login.strip()) or not(passw and passw.strip()):
return False
else:
return True
except ValueError:
return False
def show_message(self, message, is_error):
if is_error:
messagebox.showerror("Error", message)
else:
messagebox.showinfo("Information", message)
def show_select_file_dialog(self):
filepath = filedialog.askopenfilename()
return filepath
def show_save_directory_dialog(self):
filedir = filedialog.askdirectory()
return filedir
def upload_file(self):
path = self.show_select_file_dialog()
self.controller.on_fileupload(path)
pass
def get_file(self):
pass
current_item = self.tv_files.focus()
selected_file = self.tv_files.item(current_item)['values']
if selected_file is None or selected_file == '':
self.show_message("No file selected !", True)
else:
path = self.show_save_directory_dialog()
if path is None or path == '':
self.show_message("No directory selected !", True)
else:
self.controller.on_filedownload(selected_file[0], path)
def remove_file(self):
pass
current_item = self.tv_files.focus()
selected_file = self.tv_files.item(current_item)['values']
if selected_file is None or selected_file == '':
self.show_message("No file selected !", True)
else:
self.controller.on_filedelete(selected_file[0])
def file_list(self):
pass
def refresh_list(self):
self.controller.on_refreshlist()
def about(self):
pass
def quit(self):
self.root.destroy()
self.controller.on_quit()
self.controller.on_quit()
def remove_all_from_treeview(self):
self.tv_files.delete(*self.tv_files.get_children())
def add_file_in_treeview(self, fileinfo):
self.tv_files.insert('', tk.END, values = fileinfo)

19
main.py
View File

@ -2,10 +2,25 @@ from gui.MainWindow import *
from controller.MainWindowController import *
from controller.AppController import *
from model.Protocol import *
import sys
import os.path
if __name__ == '__main__':
parser = Protocol()
app_controller = AppController(parser)
event_handler = MainWindowController(parser, app_controller)
window = MainWindow(event_handler)
window_controller = MainWindowController(parser, app_controller)
window = MainWindow(window_controller)
if os.path.isfile('./ca.crt'):
print("[main] Found ca.crt")
app_controller.ssl_ca_path('./ca.crt')
if len(sys.argv) > 1:
window.host.set(sys.argv[1])
if len(sys.argv) > 2:
window.port.set(int(sys.argv[2]))
if len(sys.argv) > 3:
window.login.set(sys.argv[3])
if len(sys.argv) > 4:
window.passw.set(sys.argv[4])
if len(sys.argv) > 5:
window.tls.set(sys.argv[5] == 'tls')
window.start_main_loop()

View File

@ -1,30 +0,0 @@
class IProtocol:
def build_SIGNIN(self, login, password):
pass
def build_SIGNUP(self, login, password):
pass
def build_FILELIST(self):
pass
def build_SAVEFILE(self, filename, size):
pass
def build_GETFILE(self, filename):
pass
def build_REMOVEFILE(self, filename):
pass
def build_SIGNOUT(self):
pass
def parse(self, line, debug_enabled):
pass
def parse_FILES(self, line):
pass
def parse_GETFILEOK(self, line):
pass

View File

@ -1,7 +1,6 @@
from model.IProtocol import *
import re
class Protocol(IProtocol):
class Protocol:
RX_DIGIT = r"[0-9]"
RX_SIZE = r"(" + RX_DIGIT + "{1,10})"
RX_LINE = r"(\\x0d\\x0a){0,1}"

111
net/UnicastConnection.py Normal file
View File

@ -0,0 +1,111 @@
import socket
import ssl
import time
class UnicastConnection:
STRICT_SSL_VALIDATION = True
BUFFER_SIZE=8000
def __init__(self, sock=None):
if sock is None:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
else:
self.sock = sock
self.is_connected = False
self.is_tls = False
self.ssock = None
self.ca_path = None
self.ssl_info = None
def set_ca_path(self, ca_path):
self.ca_path = ca_path
def connect(self, host, port, tls):
print("[UnicastConnection::connect]")
self.is_tls = tls
if self.is_tls:
print("[UnicastConnection::connect] Attempting SSL/TLS connection")
context = ssl.create_default_context()
if UnicastConnection.STRICT_SSL_VALIDATION:
if self.ca_path:
print("[UnicastConnection::connect] loading CA.CRT")
context.load_verify_locations(self.ca_path)
else:
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
self.ssock = context.wrap_socket(self.sock, server_hostname=host)
self.ssock.connect((host,port))
certinfo = self.ssock.getpeercert()
if certinfo:
cert_subject = dict(x[0] for x in certinfo['subject'])
cert_issuer = dict(x[0] for x in certinfo['issuer'])
print(cert_subject['commonName'])
print(cert_issuer['commonName'])
self.ssl_info = f"Certificate Informatinon:\nCN={cert_subject['commonName']}\nIssuer={cert_issuer['commonName']}\nTLS version: {self.ssock.version()}"
self.is_connected = True
else:
print("[UnicastConnection::connect] Attemping unencypted connection")
self.sock.connect((host, port))
self.is_connected = True
def read_line(self):
print("[UnicastConnection::read_line] begin")
if self.is_tls:
line = self.ssock.recv(1000)
else:
line = self.sock.recv(1000)
message = line.decode('utf-8')
print(f"[UnicastConnection::read_line] Received: '{message}'")
return message
def send_message(self, message):
print(f"[UnicastConnection::send_message] sending message '{message}'")
if self.is_tls:
self.ssock.sendall(message.encode('utf-8'))
else:
self.sock.sendall(message.encode('utf-8'))
def send_file(self, filepath):
time.sleep(1)
self.nextrun = True
f = open(filepath, "rb")
while self.nextrun:
l = f.read(self.BUFFER_SIZE)
while (l):
if self.is_tls:
self.ssock.send(l)
else:
self.sock.send(l)
l = f.read(self.BUFFER_SIZE)
if not l:
f.close()
self.nextrun = True
break
def receive_file(self, filename, savepath, filesize):
self.nextrun = True
remaining = filesize
with open(f"{savepath}/{filename}", 'wb') as f:
while remaining > 0 and self.nextrun:
if self.is_tls:
data = self.ssock.recv(self.BUFFER_SIZE)
else:
data = self.sock.recv(self.BUFFER_SIZE)
if not data:
f.close()
self.nextrun = False
break
f.write(data)
remaining = remaining - len(data)
print(f"Received = {len(data)} - Remaining = {remaining} / {filesize}")
time.sleep(1)
def get_certificate_info(self):
return self.ssl_info
def close(self):
self.sock.close()