Ressenger/ressenger.py

208 lines
7.0 KiB
Python
Executable File

#!/usr/bin/python3
import sys, pathlib, re, subprocess
import ressenger_initialisation, ressenger_client, ressenger_common, ressenger_cryptography, ressenger_exceptions, ressenger_server
from PySide6.QtUiTools import QUiLoader
from PySide6.QtWidgets import QApplication, QListWidget, QTextBrowser, QTextEdit, QPushButton, QFileDialog, QMessageBox, QDialog, QVBoxLayout, QLineEdit, QLabel
from PySide6.QtCore import QFile, QIODevice, Qt
_B32_RE = re.compile(r'^[a-z2-7]{52}\.b32\.i2p\.?$', re.IGNORECASE)
def is_i2p_b32_address(s: str) -> bool:
if not isinstance(s, str):
return False
s = s.strip()
return bool(_B32_RE.fullmatch(s))
def parseArguments():
flag1=False
args={}
for i1 in range(len(sys.argv)):
if flag1:
if sys.argv[i1].startswith("--"):
args[sys.argv[i1-1][2:]]=None
else:
args[sys.argv[i1-1][2:]]=sys.argv[i1]
flag1=False
elif sys.argv[i1].startswith("--"):
flag1=True
if flag1:
args[sys.argv[-1][2:]]=None
return args
def message_box_2a(title, text):
dlg = QMessageBox()
dlg.setWindowTitle(title)
dlg.setText(text)
dlg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
dlg.setDefaultButton(QMessageBox.Ok)
return dlg.exec()
def message_box_2b(title, text):
dlg = QMessageBox()
dlg.setWindowTitle(title)
dlg.setText(text)
dlg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
dlg.setDefaultButton(QMessageBox.Yes)
return dlg.exec()
def message_box_1(title, text):
dlg = QMessageBox()
dlg.setWindowTitle(title)
dlg.setText(text)
dlg.setStandardButtons(QMessageBox.Ok)
dlg.setDefaultButton(QMessageBox.Ok)
return dlg.exec()
def initialise_user(profile):
ui_path = 'Initialise.ui'
in_ui_file = QFile(ui_path)
if not in_ui_file.open(QIODevice.ReadOnly):
print(f"Cannot open {ui_path}: {in_ui_file.errorString()}")
return None
loader = QUiLoader()
loaded_widget = loader.load(in_ui_file)
in_ui_file.close()
if not loaded_widget:
print(loader.errorString())
return None
app = QApplication.instance()
if app is None:
print("No QApplication instance.")
return None
if isinstance(loaded_widget, QDialog):
if not hasattr(app, "_aux_windows"):
app._aux_windows = []
app._aux_windows.append(loaded_widget)
result = loaded_widget.exec()
return loaded_widget
container = QDialog()
layout = QVBoxLayout(container)
layout.addWidget(loaded_widget)
container.setLayout(layout)
container.setWindowTitle(loaded_widget.windowTitle() or "Initialise")
if not hasattr(app, "_aux_windows"):
app._aux_windows = []
app._aux_windows.append(container)
btn_cancel = loaded_widget.findChild(QPushButton, "pushButton_11")
btn_ok = loaded_widget.findChild(QPushButton, "pushButton_12")
username = loaded_widget.findChild(QLabel, "label_27")
nickname = loaded_widget.findChild(QLineEdit, "lineEdit_13")
port = loaded_widget.findChild(QLineEdit, "lineEdit_16")
b32addr = loaded_widget.findChild(QLineEdit, "lineEdit_15")
passwd = loaded_widget.findChild(QLineEdit, "lineEdit_14")
username.setText(profile)
succeed=False
def call_initialise():
nonlocal succeed
try:
ressenger_initialisation.initialise(password=passwd.text(), b32address=b32addr.text(), username=profile, port=int(port.text()), nick=nickname.text())
message_box_1('Suceess', 'Profile has been created successfully.')
succeed=True
return True
except FileExistsError as e:
if message_box_2b('Alert', f'{str(e)}\nDo you want to force the creation of the profile? Conflicting files will be overwritten.')==QMessageBox.Yes:
ressenger_initialisation.initialise(password=passwd.text(), b32address=b32addr.text(), username=profile, port=int(port.text()), nick=nickname.text(), force=True)
message_box_1('Suceess', 'Profile has been created successfully.')
succeed=True
return True
return False
def proceed():
if nickname.text()=='':
message_box_1('Error', 'Nickname should not be empty!')
elif not port.text().isdigit():
message_box_1('Error', 'Invalid port number!')
elif not (int(port.text())<=49151 and int(port.text())>=1024):
message_box_1('Error', 'Port number should be between 1024 and 49151!')
elif not is_i2p_b32_address(b32addr.text()):
message_box_1('Error', 'Invalid I2P Base32 address!')
elif len(passwd.text())<8:
message_box_1('Error', 'Password should be at least 8 characters long!')
else:
if len(passwd.text())<20:
if message_box_2b('Alert', 'Password is suggested to be at least 20 characters long.\nDo you want to go back to set a longer password?')==QMessageBox.Yes:
pass
else:
if call_initialise():
container.reject()
else:
if call_initialise():
container.reject()
btn_cancel.clicked.connect(container.reject)
btn_ok.clicked.connect(proceed)
container.exec()
if not succeed:
exit()
if __name__ == "__main__":
args=parseArguments()
if 'help' in args.keys():
print(f'''Usage: {sys.argv[0]} [OPTIONS] ...
List of options:
--profile [PROFILE]
Start Ressenger with the profile [PROFILE].
--help
Display this help and exit.
''')
exit()
profile='default'
if 'profile' in args.keys():
profile=args['profile']
app = QApplication(sys.argv)
if profile.startswith("cache_"):
message_box_1('Error', 'Invalid profile name.')
exit()
if profile.startswith("lock_"):
message_box_1('Error', 'Invalid profile name.')
exit()
user_path=pathlib.Path(f'~/.ressenger/{profile}').expanduser()
if not user_path.exists():
if message_box_2a('Create a profile?',f'The Ressenger profile does not exist.\nWould you like to create one now?')==QMessageBox.Ok:
initialise_user(profile)
else:
exit()
ui_file_name = "MainWindow.ui"
ui_file = QFile(ui_file_name)
if not ui_file.open(QIODevice.ReadOnly):
print(f"Cannot open {ui_file_name}: {ui_file.errorString()}")
sys.exit(-1)
loader = QUiLoader()
window = loader.load(ui_file)
ui_file.close()
list_widget = window.findChild(QListWidget, "listWidget")
text_browser = window.findChild(QTextBrowser, "textBrowser")
text_edit = window.findChild(QTextEdit, "textEdit")
btn_fingerprint = window.findChild(QPushButton, "pushButton")
btn_file = window.findChild(QPushButton, "pushButton_2")
btn_send = window.findChild(QPushButton, "pushButton_3")
if not window:
print(loader.errorString())
sys.exit(-1)
window.show()
sys.exit(app.exec())