diff --git a/nomadnet/Conversation.py b/nomadnet/Conversation.py index 5c804b6..86d26bb 100644 --- a/nomadnet/Conversation.py +++ b/nomadnet/Conversation.py @@ -873,7 +873,7 @@ class ConversationMessage: name = str(name) if name is not None else "" except Exception: name = "" - name = re.sub(r"[\x00-\x1f\x7f]", "", name) + name = re.sub(r"[\x00-\x1f\x7f-\x9f]", "", name) parts = re.split(r"[/\\]", name) name = parts[-1] if parts else "" if ":" in name: diff --git a/nomadnet/Node.py b/nomadnet/Node.py index 28c816f..622d8aa 100644 --- a/nomadnet/Node.py +++ b/nomadnet/Node.py @@ -9,6 +9,7 @@ import RNS.vendor.umsgpack as msgpack class Node: JOB_INTERVAL = 5 + SETTINGS_FLUSH_INTERVAL = 60 START_ANNOUNCE_DELAY = 6 def __init__(self, app): @@ -24,6 +25,8 @@ class Node: self.file_refresh_interval = self.app.file_refresh_interval self.job_interval = Node.JOB_INTERVAL self.should_run_jobs = True + self.settings_dirty = False + self.last_settings_flush = time.time() self.app_data = None self.name = self.app.node_name @@ -100,7 +103,8 @@ class Node: directories = [file for file in os.listdir(base_path) if os.path.isdir(os.path.join(base_path, file)) and file[:1] != "."] for file in files: - self.servedfiles.append(base_path+"/"+file) + if not file.endswith(".allowed"): + self.servedfiles.append(base_path+"/"+file) for directory in directories: self.scan_files(base_path+"/"+directory) @@ -109,51 +113,13 @@ class Node: RNS.log("Page request "+RNS.prettyhexrep(request_id)+" for: "+str(path), RNS.LOG_VERBOSE) try: self.app.peer_settings["served_page_requests"] += 1 - self.app.save_peer_settings() + self.settings_dirty = True except Exception as e: RNS.log("Could not increase served page request count", RNS.LOG_ERROR) file_path = path.replace("/page", self.app.pagespath, 1) - - allowed_path = file_path+".allowed" - request_allowed = False - - if os.path.isfile(allowed_path): - allowed_list = [] - - try: - if os.access(allowed_path, os.X_OK): - allowed_result = subprocess.run([allowed_path], stdout=subprocess.PIPE) - allowed_input = allowed_result.stdout - - else: - with open(allowed_path, "rb") as fh: - allowed_input = fh.read() - - allowed_hash_strs = allowed_input.splitlines() - - for hash_str in allowed_hash_strs: - if len(hash_str) == RNS.Identity.TRUNCATED_HASHLENGTH//8*2: - try: - allowed_hash = bytes.fromhex(hash_str.decode("utf-8")) - allowed_list.append(allowed_hash) - - except Exception as e: - RNS.log("Could not decode RNS Identity hash from: "+str(hash_str), RNS.LOG_DEBUG) - RNS.log("The contained exception was: "+str(e), RNS.LOG_DEBUG) - - except Exception as e: - RNS.log("Error while fetching list of allowed identities for request: "+str(e), RNS.LOG_ERROR) - - if hasattr(remote_identity, "hash") and remote_identity.hash in allowed_list: - request_allowed = True - else: - request_allowed = False - RNS.log("Denying request, remote identity was not in list of allowed identities", RNS.LOG_VERBOSE) - - else: - request_allowed = True + request_allowed = self.request_allowed(file_path, remote_identity) try: if request_allowed: @@ -187,18 +153,52 @@ class Node: RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR) return None + def request_allowed(self, file_path, remote_identity): + allowed_path = file_path+".allowed" + if not os.path.isfile(allowed_path): + return True + + allowed_list = [] + try: + if os.access(allowed_path, os.X_OK): + allowed_input = subprocess.run([allowed_path], stdout=subprocess.PIPE).stdout + else: + with open(allowed_path, "rb") as fh: + allowed_input = fh.read() + + for hash_str in allowed_input.splitlines(): + if len(hash_str) == RNS.Identity.TRUNCATED_HASHLENGTH//8*2: + try: + allowed_list.append(bytes.fromhex(hash_str.decode("utf-8"))) + except Exception as e: + RNS.log("Could not decode RNS Identity hash from: "+str(hash_str), RNS.LOG_DEBUG) + RNS.log("The contained exception was: "+str(e), RNS.LOG_DEBUG) + + except Exception as e: + RNS.log("Error while fetching list of allowed identities for request: "+str(e), RNS.LOG_ERROR) + + if hasattr(remote_identity, "hash") and remote_identity.hash in allowed_list: + return True + + RNS.log("Denying request, remote identity was not in list of allowed identities", RNS.LOG_VERBOSE) + return False + # TODO: Improve file handling, this will be slow for large files def serve_file(self, path, data, request_id, remote_identity, requested_at): RNS.log("File request "+RNS.prettyhexrep(request_id)+" for: "+str(path), RNS.LOG_VERBOSE) try: self.app.peer_settings["served_file_requests"] += 1 - self.app.save_peer_settings() + self.settings_dirty = True except Exception as e: RNS.log("Could not increase served file request count", RNS.LOG_ERROR) file_path = path.replace("/file", self.app.filespath, 1) file_name = path.replace("/file/", "", 1) + if not self.request_allowed(file_path, remote_identity): + RNS.log("Request denied", RNS.LOG_VERBOSE) + return DEFAULT_NOTALLOWED.encode("utf-8") + try: RNS.log("Serving file: "+file_path, RNS.LOG_VERBOSE) return [open(file_path, "rb"), {"name": file_name.encode("utf-8")}] @@ -236,13 +236,19 @@ class Node: self.register_files() self.last_file_refresh = time.time() + if self.settings_dirty and now > self.last_settings_flush + Node.SETTINGS_FLUSH_INTERVAL: + self.settings_dirty = False + self.last_settings_flush = now + try: self.app.save_peer_settings() + except Exception as e: RNS.log("Could not save peer settings: "+str(e), RNS.LOG_ERROR) + time.sleep(self.job_interval) def peer_connected(self, link): RNS.log("Peer connected to "+str(self.destination), RNS.LOG_VERBOSE) try: self.app.peer_settings["node_connects"] += 1 - self.app.save_peer_settings() + self.settings_dirty = True except Exception as e: RNS.log("Could not increase node connection count", RNS.LOG_ERROR) diff --git a/nomadnet/NomadNetworkApp.py b/nomadnet/NomadNetworkApp.py index 65bf17a..27bdaa6 100644 --- a/nomadnet/NomadNetworkApp.py +++ b/nomadnet/NomadNetworkApp.py @@ -8,6 +8,7 @@ import threading import traceback import subprocess import contextlib +import tempfile import RNS import LXMF @@ -129,6 +130,7 @@ class NomadNetworkApp: self.firstrun = False self.should_run_jobs = True self.job_interval = 5 + self.peer_settings_lock = threading.Lock() self.defer_jobs = 90 self.page_refresh_interval = 0 self.file_refresh_interval = 0 @@ -249,11 +251,13 @@ class NomadNetworkApp: RNS.log("The contained exception was: %s" % (str(e)), RNS.LOG_ERROR) nomadnet.panic() - if os.path.isfile(self.peersettingspath): + self.peer_settings = None + self.peer_settings_notice = None + for path in (self.peersettingspath, self.peersettingspath+".bak"): + if self.peer_settings != None or not os.path.isfile(path): continue try: - file = open(self.peersettingspath, "rb") - self.peer_settings = msgpack.unpackb(file.read()) - file.close() + with open(path, "rb") as file: + self.peer_settings = msgpack.unpackb(file.read()) if not "node_last_announce" in self.peer_settings: self.peer_settings["node_last_announce"] = None @@ -274,17 +278,21 @@ class NomadNetworkApp: self.peer_settings["served_file_requests"] = 0 self.peer_settings["announce_interval"] = self.announce_interval + if path != self.peersettingspath: + self.peer_settings_notice = "Peer settings were restored from the last backup.\nCheck your display name and propagation node." except Exception as e: - RNS.logdest = RNS.LOG_STDOUT - RNS.log(f"Could not load local peer settings from {self.peersettingspath}", RNS.LOG_ERROR) + RNS.log(f"Could not load local peer settings from {path}", RNS.LOG_ERROR) RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR) - RNS.log(f"This likely means that the peer settings file has become corrupt.", RNS.LOG_ERROR) - RNS.log(f"You can try deleting the file at {self.peersettingspath} and restarting nomadnet.", RNS.LOG_ERROR) - nomadnet.panic() - else: + RNS.log(f"Moving the corrupt file to {path}.corrupt", RNS.LOG_ERROR) + try: os.replace(path, path+".corrupt") + except Exception: pass + self.peer_settings = None + self.peer_settings_notice = "Peer settings were corrupt and have been reset.\nCheck your display name and propagation node." + + if self.peer_settings == None: try: - RNS.log("No peer settings file found, creating new...") + RNS.log("Creating new peer settings file...") self.peer_settings = { "display_name": "Anonymous Peer", "announce_interval": self.announce_interval, @@ -650,9 +658,16 @@ class NomadNetworkApp: return self.message_router.get_outbound_propagation_node() def save_peer_settings(self): - tmp_path = f"{self.peersettingspath}.tmp" - with open(tmp_path, "wb") as file: file.write(msgpack.packb(self.peer_settings)) - os.replace(tmp_path, self.peersettingspath) + with self.peer_settings_lock: + fd, tmp_path = tempfile.mkstemp(dir=os.path.dirname(self.peersettingspath), prefix=".peersettings.") + try: + with os.fdopen(fd, "wb") as file: file.write(msgpack.packb(self.peer_settings)) + if os.path.isfile(self.peersettingspath): os.replace(self.peersettingspath, self.peersettingspath+".bak") + os.replace(tmp_path, self.peersettingspath) + except Exception: + try: os.unlink(tmp_path) + except Exception: pass + raise def lxmf_delivery(self, message): time_string = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(message.timestamp)) diff --git a/nomadnet/RRC.py b/nomadnet/RRC.py index e764b3b..ddafa60 100644 --- a/nomadnet/RRC.py +++ b/nomadnet/RRC.py @@ -8,6 +8,7 @@ from collections import deque import RNS from nomadnet.vendor import cbor +from nomadnet.util import strip_modifiers HISTORY_DIR_NAME = "rrc_history" @@ -192,7 +193,7 @@ class RRCMessage: self.room = room self.src = src self.nick = nick - self.text = text + self.text = strip_modifiers(text) self.ts = ts self.mention = False @@ -355,10 +356,11 @@ class RRCHub: def _connect_worker(self): try: - timeout_s = 20.0 + path_timeout = self.manager.app.rns.get_medium_path_timeout() + timeout_s = max(20.0, path_timeout) if not RNS.Transport.has_path(self.hub_hash): RNS.Transport.request_path(self.hub_hash) - deadline = time.monotonic() + min(5.0, timeout_s) + deadline = time.monotonic() + max(5.0, path_timeout) while time.monotonic() < deadline: if RNS.Transport.has_path(self.hub_hash): break @@ -429,7 +431,7 @@ class RRCHub: except Exception as e: self._log("HELLO send failed: "+str(e), RNS.LOG_ERROR) attempts += 1 - self._stop_hello.wait(timeout=3.0) + self._stop_hello.wait(timeout=max(3.0, (cur_link.rtt or 0)*cur_link.traffic_timeout_factor)) if not self.welcomed and not self._stop_hello.is_set(): self._set_status(RRCHub.STATUS_FAILED, "WELCOME timeout") try: @@ -847,7 +849,7 @@ class RRCHub: parsed = _parse_room_list_notice(text) if parsed is not None: with self._lock: - self.available_rooms = parsed + self.available_rooms = {strip_modifiers(name): strip_modifiers(topic) for name, topic in parsed.items()} silent = self._silent_list_pending > 0 if silent: self._silent_list_pending -= 1 @@ -925,7 +927,7 @@ class RRCHub: if isinstance(body, dict): hub_name = body.get(B_WELCOME_HUB) if isinstance(hub_name, str): - self.hub_name = hub_name + self.hub_name = strip_modifiers(hub_name) ver = body.get(B_WELCOME_VER) if isinstance(ver, str): self.hub_version = ver @@ -1135,7 +1137,7 @@ class RRCHub: room_n = room.strip().lower() if isinstance(room, str) else None if room_n is None and isinstance(body, str) and body.strip(): with self._lock: - self.motd = body + self.motd = strip_modifiers(body) self.manager._notify_change(self) msg = RRCMessage( "notice", @@ -1273,7 +1275,7 @@ class RRCHub: return if kind == RES_KIND_MOTD: with self._lock: - self.motd = text + self.motd = strip_modifiers(text) self.manager._notify_change(self) elif self._process_notice_text(text): return diff --git a/nomadnet/ui/TextUI.py b/nomadnet/ui/TextUI.py index 50d65d1..bbaa73a 100644 --- a/nomadnet/ui/TextUI.py +++ b/nomadnet/ui/TextUI.py @@ -279,6 +279,7 @@ class TextUI: self.set_colormode(colormode) self.main_display.start() + if intro_timeout <= 0 and self.app.peer_settings_notice: self.main_display.show_notice(self.app.peer_settings_notice) self.loop.run() def set_colormode(self, colormode): @@ -297,3 +298,4 @@ class TextUI: def display_main(self, loop, user_data): self.loop.widget = self.main_display.widget + if self.app.peer_settings_notice: self.main_display.show_notice(self.app.peer_settings_notice) diff --git a/nomadnet/ui/textui/Browser.py b/nomadnet/ui/textui/Browser.py index 51685b3..9a427bd 100644 --- a/nomadnet/ui/textui/Browser.py +++ b/nomadnet/ui/textui/Browser.py @@ -11,6 +11,7 @@ import threading from threading import Lock from .MicronParser import markup_to_attrmaps, make_style, default_state from nomadnet.Directory import DirectoryEntry +from nomadnet.Conversation import ConversationMessage from nomadnet.vendor.Scrollable import * from nomadnet.util import strip_modifiers from nomadnet.util import sanitize_name @@ -825,10 +826,9 @@ class Browser: partial["pr_throttle"] = time.time()+15 RNS.log(f"Requesting path for partial: {partial_destination_hash} / {path}", RNS.LOG_EXTREME) RNS.Transport.request_path(partial_destination_hash) - pr_time = time.time()+RNS.Transport.first_hop_timeout(partial_destination_hash) + pr_time = time.time()+self.path_timeout(partial_destination_hash) while not RNS.Transport.has_path(partial_destination_hash): - now = time.time() - if now > pr_time+self.timeout: return + if time.time() > pr_time: return time.sleep(0.25) for pid in self.page_partials: @@ -853,7 +853,7 @@ class Browser: partial["link"] = None partial["link"] = RNS.Link(destination, established_callback = established, closed_callback = closed) - timeout = time.time()+self.timeout + timeout = time.time()+max(self.timeout, partial["link"].establishment_timeout) while partial["link"].status != RNS.Link.ACTIVE and time.time() < timeout: time.sleep(0.1) if partial["link"] and partial["link"].status == RNS.Link.ACTIVE and partial["request_id"] == None: @@ -1065,6 +1065,9 @@ class Browser: def set_timeout(self, timeout): self.timeout = timeout + def path_timeout(self, destination_hash): + return max(self.timeout + self.app.rns.get_first_hop_timeout(destination_hash), self.app.rns.get_medium_path_timeout()) + def download_local_file(self, path): try: file_path = self.app.filespath+path.replace("/file", "", 1) @@ -1110,10 +1113,9 @@ class Browser: self.status = Browser.PATH_REQUESTED self.update_display() - pr_time = time.time()+RNS.Transport.first_hop_timeout(self.destination_hash) + pr_time = time.time()+self.path_timeout(self.destination_hash) while not RNS.Transport.has_path(self.destination_hash): - now = time.time() - if now > pr_time+self.timeout: + if time.time() > pr_time: self.request_timeout() return @@ -1493,10 +1495,9 @@ class Browser: self.status = Browser.PATH_REQUESTED self.update_display() - pr_time = time.time()+RNS.Transport.first_hop_timeout(self.destination_hash) + pr_time = time.time()+self.path_timeout(self.destination_hash) while not RNS.Transport.has_path(self.destination_hash): - now = time.time() - if now > pr_time+self.timeout: + if time.time() > pr_time: self.request_timeout() return @@ -1738,9 +1739,13 @@ class Browser: def file_received(self, request_receipt): try: - if type(request_receipt.response) == io.BufferedReader: + if isinstance(request_receipt.response, bytes): + markup = request_receipt.response.decode("utf-8") + self.attr_maps = markup_to_attrmaps(strip_modifiers(markup), url_delegate=self, fg_color=self.page_foreground_color, bg_color=self.page_background_color) + + elif type(request_receipt.response) == io.BufferedReader: if request_receipt.metadata != None: - file_name = os.path.basename(request_receipt.metadata["name"].decode("utf-8")) + file_name = ConversationMessage.safe_attachment_name(request_receipt.metadata["name"]) file_handle = request_receipt.response file_destination = self.app.downloads_path+"/"+file_name @@ -1759,7 +1764,7 @@ class Browser: else: file_name = request_receipt.response[0] file_data = request_receipt.response[1] - file_destination_name = os.path.basename(file_name) + file_destination_name = ConversationMessage.safe_attachment_name(file_name) file_destination = self.app.downloads_path+"/"+file_destination_name counter = 0 diff --git a/nomadnet/ui/textui/Conversations.py b/nomadnet/ui/textui/Conversations.py index dec5fa6..6410abf 100644 --- a/nomadnet/ui/textui/Conversations.py +++ b/nomadnet/ui/textui/Conversations.py @@ -2809,7 +2809,7 @@ class LXMessageWidget(urwid.WidgetWrap): title_string = g["warning"]+" "+g["arrow_l"]+" "+message.get_signature_description() + "\n " + title_string if message.get_title() != "": - title_string += " | " + message.get_title() + title_string += " | " + strip_modifiers(message.get_title()) inbound_untrusted = False if not is_outbound and msg_source_hash is not None: diff --git a/nomadnet/ui/textui/Editor.py b/nomadnet/ui/textui/Editor.py index 42d8203..b22e449 100644 --- a/nomadnet/ui/textui/Editor.py +++ b/nomadnet/ui/textui/Editor.py @@ -953,18 +953,18 @@ class PageEditorDisplay(): common, restricted, total = self._folder_permissions(path) content = common or "" if not total: - state = "This folder contains no pages." + state = "This folder contains no files." elif not restricted: - state = "All %d pages here are public." % total + state = "All %d files here are public." % total elif common is not None: - state = "All %d pages here share these entries." % total + state = "All %d files here share these entries." % total else: - state = "Entries differ across pages (%d of %d restricted)." % (restricted, total) + state = "Entries differ across files (%d of %d restricted)." % (restricted, total) note = ("Allowed identity hashes per line.\n" - + state + "\nSaving applies these entries to every page in this folder and its subfolders.") + + state + "\nSaving applies these entries to every file in this folder and its subfolders.") else: content = self._read_allowed(path) - note = "Allowed identity hashes per line. Empty = public.\nApplies to this page." + note = "Allowed identity hashes per line. Empty = public.\nApplies to this page or file." title = "Permissions: " + os.path.basename(path) + ("/" if is_dir else "") self.show_dialog(PermissionsDialog(title, note, content, diff --git a/nomadnet/ui/textui/Guide.py b/nomadnet/ui/textui/Guide.py index 8cdb239..aa97121 100644 --- a/nomadnet/ui/textui/Guide.py +++ b/nomadnet/ui/textui/Guide.py @@ -498,9 +498,9 @@ By default, you can find the examples in `!~/.nomadnetwork/examples`!. If you bu >>Authenticating Users -Sometimes, you don't want everyone to be able to view certain pages or execute certain scripts. In such cases, you can use `*authentication`* to control who gets to run certain requests. +Sometimes, you don't want everyone to be able to view certain pages, download certain files or execute certain scripts. In such cases, you can use `*authentication`* to control who gets to run certain requests. -To enable authentication for any page, simply add a new file to your pages directory with ".allowed" added to the file-name of the page. If your page is named "secret_page.mu", just add a file named "secret_page.mu.allowed". +To enable authentication for any page or file, simply add a new file next to it with ".allowed" added to its file-name. If your page is named "secret_page.mu", just add a file named "secret_page.mu.allowed". The same works for files in your files directory, and the ".allowed" file itself is never served. For each user allowed to access the page, add a line to this file, containing the hash of that users primary identity. Users can find their own identity hash in the `![ Network ]`! part of the program, under `!Local Peer Info`!. If you want to allow access for three different users, your file would look like this: diff --git a/nomadnet/ui/textui/Log.py b/nomadnet/ui/textui/Log.py index 11b5efa..c301d63 100644 --- a/nomadnet/ui/textui/Log.py +++ b/nomadnet/ui/textui/Log.py @@ -4,6 +4,7 @@ import itertools import mmap import urwid import nomadnet +from nomadnet.util import strip_modifiers class LogDisplayShortcuts(): @@ -68,7 +69,7 @@ class LogTerminal(urwid.WidgetWrap): class LogTail(urwid.WidgetWrap): def __init__(self, app): self.app = app - self.log_tail = urwid.Text(tail(self.app.logfilepath, 50)) + self.log_tail = urwid.Text(strip_modifiers(tail(self.app.logfilepath, 50))) self.log = urwid.Scrollable(self.log_tail) self.log.set_scrollpos(-1) self.log_scrollbar = urwid.ScrollBar(self.log) diff --git a/nomadnet/ui/textui/Main.py b/nomadnet/ui/textui/Main.py index 63ed0f2..cf1c959 100644 --- a/nomadnet/ui/textui/Main.py +++ b/nomadnet/ui/textui/Main.py @@ -249,6 +249,12 @@ class MainDisplay(): valign="middle", height=8, min_width=20, ) + def show_notice(self, text): + def close(button=None): self.app.ui.loop.widget = self.frame + pile = urwid.Pile([urwid.Text(text, align="center"), urwid.Divider(), urwid.Button("OK", on_press=close)]) + dialog = QuitDialogLineBox(urwid.Filler(pile, urwid.TOP), title="Notice", on_cancel=close) + self.app.ui.loop.widget = urwid.Overlay(dialog, self.frame, align="center", width=64, valign="middle", height=9, min_width=20) + def do_quit(self, sender=None): logterm_pid = None if True or RNS.vendor.platformutils.is_android(): diff --git a/nomadnet/ui/textui/MicronParser.py b/nomadnet/ui/textui/MicronParser.py index 0add998..ff946c4 100644 --- a/nomadnet/ui/textui/MicronParser.py +++ b/nomadnet/ui/textui/MicronParser.py @@ -8,6 +8,7 @@ from urwid.util import is_mouse_press from urwid.text_layout import calc_coords from .ReadlineEdit import ReadlineEdit from RNS.Utilities.rngit.util import MarkdownToMicron +from nomadnet.util import STRIP_CONTROL_RE DEFAULT_FG_DARK = "ddd" DEFAULT_FG_LIGHT = "222" @@ -101,6 +102,7 @@ def ensure_selected_styles(): else: SELECTED_STYLES = STYLES_LIGHT def markup_to_attrmaps(markup, url_delegate = None, fg_color=None, bg_color=None, link_class=None, anchors=None): + markup = STRIP_CONTROL_RE.sub("", markup) global LINK_CLASS if link_class: LINK_CLASS = link_class else: LINK_CLASS = LinkableText diff --git a/nomadnet/ui/textui/Utilities.py b/nomadnet/ui/textui/Utilities.py index 771cd0b..ec0dfee 100644 --- a/nomadnet/ui/textui/Utilities.py +++ b/nomadnet/ui/textui/Utilities.py @@ -419,7 +419,7 @@ class ProbeView: def _timeout(self): try: - return DEFAULT_PROBE_TIMEOUT + self.app.rns.get_first_hop_timeout(self._dest_hash) + return max(DEFAULT_PROBE_TIMEOUT + self.app.rns.get_first_hop_timeout(self._dest_hash), self.app.rns.get_medium_path_timeout()) except Exception: return DEFAULT_PROBE_TIMEOUT @@ -639,7 +639,7 @@ class PathView: def _timeout(self): try: - return DEFAULT_PROBE_TIMEOUT + self.app.rns.get_first_hop_timeout(self._dest_hash) + return max(DEFAULT_PROBE_TIMEOUT + self.app.rns.get_first_hop_timeout(self._dest_hash), self.app.rns.get_medium_path_timeout()) except Exception: return DEFAULT_PROBE_TIMEOUT @@ -830,7 +830,7 @@ class IdentityView: self.lookup_button.original_widget.set_label("Looking up…") self._log("Identity unknown, requesting from the network …") try: - self._deadline = time.time() + DEFAULT_PROBE_TIMEOUT + self.app.rns.get_first_hop_timeout(dest_hash) + self._deadline = time.time() + max(DEFAULT_PROBE_TIMEOUT + self.app.rns.get_first_hop_timeout(dest_hash), self.app.rns.get_medium_path_timeout()) except Exception: self._deadline = time.time() + DEFAULT_PROBE_TIMEOUT self.app.ui.loop.set_alarm_in(0.25, self._await_identity) @@ -975,7 +975,7 @@ class SendFileView: def _timeout(self): try: - return DEFAULT_PROBE_TIMEOUT + self.app.rns.get_first_hop_timeout(self._dest_hash) + return max(DEFAULT_PROBE_TIMEOUT + self.app.rns.get_first_hop_timeout(self._dest_hash), self.app.rns.get_medium_path_timeout()) except Exception: return DEFAULT_PROBE_TIMEOUT @@ -1040,7 +1040,7 @@ class SendFileView: self._log("Could not establish link: %s" % str(e), "error_text") self._finish() return - self._link_deadline = time.time() + self._timeout() + self._link_deadline = time.time() + max(self._timeout(), self._link.establishment_timeout) self.app.ui.loop.set_alarm_in(0.5, self._check_link) def _check_link(self, loop, user_data): @@ -1402,7 +1402,7 @@ class SpeedTestView: return self._incoming_link = link link.set_remote_identified_callback(self._on_remote_identified) - self.app.ui.loop.set_alarm_in(8, lambda l, u: self._incoming_timeout(link)) + self.app.ui.loop.set_alarm_in(max(8, self.app.rns.get_medium_path_timeout()), lambda l, u: self._incoming_timeout(link)) def _incoming_timeout(self, link): if self._recv_link is link: @@ -1565,7 +1565,7 @@ class SpeedTestView: def _timeout(self): try: - return DEFAULT_PROBE_TIMEOUT + self.app.rns.get_first_hop_timeout(self._dest_hash) + return max(DEFAULT_PROBE_TIMEOUT + self.app.rns.get_first_hop_timeout(self._dest_hash), self.app.rns.get_medium_path_timeout()) except Exception: return DEFAULT_PROBE_TIMEOUT @@ -1594,7 +1594,7 @@ class SpeedTestView: self._log("Could not establish link: %s" % str(e), "error_text") self._finish() return - self._link_deadline = time.time() + self._timeout() + self._link_deadline = time.time() + max(self._timeout(), self._client_link.establishment_timeout) self.app.ui.loop.set_alarm_in(0.5, self._check_link) def _check_link(self, loop, user_data): diff --git a/nomadnet/util.py b/nomadnet/util.py index a7bd62c..4c3a079 100644 --- a/nomadnet/util.py +++ b/nomadnet/util.py @@ -121,8 +121,9 @@ def strip_modifiers(text): stripped = re.sub(r'[\U0001F3FB-\U0001F3FF]', '', stripped, flags=re.UNICODE) stripped = re.sub(r'[\u200D\u200C]', '', stripped) stripped = re.sub(r'\r\n?', '\n', stripped) - - return stripped.strip().replace("\x00", "") + stripped = STRIP_CONTROL_RE.sub('', stripped) + + return stripped.strip() def sanitize_name(name): if name is None: return None