From 8f1e7ac224e54f57e43321bba2c2f9fdb5143bb0 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Mon, 8 Nov 2021 14:49:37 +1100 Subject: Set the path QLabel of the HistoryItem to plain text format --- desktop/src/onionshare/tab/mode/history.py | 1 + 1 file changed, 1 insertion(+) diff --git a/desktop/src/onionshare/tab/mode/history.py b/desktop/src/onionshare/tab/mode/history.py index 091905f7..4e8fcf8e 100644 --- a/desktop/src/onionshare/tab/mode/history.py +++ b/desktop/src/onionshare/tab/mode/history.py @@ -481,6 +481,7 @@ class IndividualFileHistoryItem(HistoryItem): self.common.gui.css["history_individual_file_timestamp_label"] ) self.path_label = QtWidgets.QLabel(self.path) + self.path_label.setTextFormat(QtCore.Qt.PlainText) self.path_label.setStyleSheet(self.common.gui.css["history_default_label"]) self.status_code_label = QtWidgets.QLabel() -- cgit v1.2.3-54-g00ecf From 096178a9e6133fd6ca9d95a00a67bba75ccab377 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Tue, 9 Nov 2021 12:30:48 +1100 Subject: Use microseconds for Receive Mode dir/file names --- cli/onionshare_cli/web/receive_mode.py | 2 +- desktop/tests/test_gui_receive.py | 32 +++++++++++++++++--------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/cli/onionshare_cli/web/receive_mode.py b/cli/onionshare_cli/web/receive_mode.py index 6b106d37..07964952 100644 --- a/cli/onionshare_cli/web/receive_mode.py +++ b/cli/onionshare_cli/web/receive_mode.py @@ -378,7 +378,7 @@ class ReceiveModeRequest(Request): # Figure out what files should be saved now = datetime.now() date_dir = now.strftime("%Y-%m-%d") - time_dir = now.strftime("%H%M%S") + time_dir = now.strftime("%H%M%S%f") self.receive_mode_dir = os.path.join( self.web.settings.get("receive", "data_dir"), date_dir, time_dir ) diff --git a/desktop/tests/test_gui_receive.py b/desktop/tests/test_gui_receive.py index ca69c957..423b63a0 100644 --- a/desktop/tests/test_gui_receive.py +++ b/desktop/tests/test_gui_receive.py @@ -1,3 +1,4 @@ +import glob import pytest import os import requests @@ -35,17 +36,17 @@ class TestReceive(GuiBaseTest): now = datetime.now() for _ in range(10): date_dir = now.strftime("%Y-%m-%d") - if identical_files_at_once: - time_dir = now.strftime("%H%M%S-1") - else: - time_dir = now.strftime("%H%M%S") + time_dir = now.strftime("%H%M%S") receive_mode_dir = os.path.join( tab.settings.get("receive", "data_dir"), date_dir, time_dir ) - expected_filename = os.path.join(receive_mode_dir, expected_basename) - if os.path.exists(expected_filename): - exists = True - break + # The directories have microseconds in the name, so we need + # to use globbing against directory names containing the same + # second in order to try to find the file. + for path in glob.glob(receive_mode_dir + "*"): + if os.path.exists(os.path.join(path, expected_basename)): + exists = True + break now = now - timedelta(seconds=1) self.assertTrue(exists) @@ -83,17 +84,18 @@ class TestReceive(GuiBaseTest): for _ in range(10): date_dir = now.strftime("%Y-%m-%d") time_dir = now.strftime("%H%M%S") - expected_filename = os.path.join( + expected_estimated_filename = os.path.join( tab.settings.get("receive", "data_dir"), date_dir, - f"{time_dir}-message.txt", + f"{time_dir}*-message.txt", ) - if os.path.exists(expected_filename): - with open(expected_filename) as f: - assert f.read() == message + for path in glob.glob(expected_estimated_filename): + if os.path.exists(path): + with open(path) as f: + assert f.read() == message - exists = True - break + exists = True + break now = now - timedelta(seconds=1) self.assertTrue(exists) -- cgit v1.2.3-54-g00ecf From f4ade1ba8d9529893c6a84e4d335f31722eb59c8 Mon Sep 17 00:00:00 2001 From: Saptak S Date: Sun, 14 Nov 2021 20:58:21 +0530 Subject: Removed room from chat - Uses the global room instead of adding and leaving room for users - Removes the joining event and triggers connection status from server as soon as a connection event is received in server side --- cli/onionshare_cli/mode_settings.py | 2 +- cli/onionshare_cli/resources/static/js/chat.js | 14 ++++-------- cli/onionshare_cli/web/chat_mode.py | 30 ++++++++++++-------------- 3 files changed, 19 insertions(+), 27 deletions(-) diff --git a/cli/onionshare_cli/mode_settings.py b/cli/onionshare_cli/mode_settings.py index 47ff1c63..9254685f 100644 --- a/cli/onionshare_cli/mode_settings.py +++ b/cli/onionshare_cli/mode_settings.py @@ -56,7 +56,7 @@ class ModeSettings: "disable_files": False, }, "website": {"disable_csp": False, "filenames": []}, - "chat": {"room": "default"}, + "chat": {}, } self._settings = {} diff --git a/cli/onionshare_cli/resources/static/js/chat.js b/cli/onionshare_cli/resources/static/js/chat.js index de64c094..78eaa7bc 100644 --- a/cli/onionshare_cli/resources/static/js/chat.js +++ b/cli/onionshare_cli/resources/static/js/chat.js @@ -11,29 +11,23 @@ $(function () { // Store current username received from app context var current_username = $('#username').val(); - // On browser connect, emit a socket event to be added to - // room and assigned random username - socket.on('connect', function () { - socket.emit('joined', {}); - }); - // Triggered on any status change by any user, such as some // user joined, or changed username, or left, etc. socket.on('status', function (data) { - addMessageToRoom(data, current_username, 'status'); + addMessageToPanel(data, current_username, 'status'); console.log(data, current_username); }); // Triggered when message is received from a user. Even when sent // by self, it get triggered after the server sends back the emit. socket.on('message', function (data) { - addMessageToRoom(data, current_username, 'chat'); + addMessageToPanel(data, current_username, 'chat'); console.log(data, current_username); }); // Triggered when disconnected either by server stop or timeout socket.on('disconnect', function (data) { - addMessageToRoom({ 'msg': 'The chat server is disconnected.' }, current_username, 'status'); + addMessageToPanel({ 'msg': 'The chat server is disconnected.' }, current_username, 'status'); }) socket.on('connect_error', function (error) { console.log("error"); @@ -66,7 +60,7 @@ $(function () { }); }); -var addMessageToRoom = function (data, current_username, messageType) { +var addMessageToPanel = function (data, current_username, messageType) { var scrollDiff = getScrollDiffBefore(); if (messageType === 'status') { addStatusMessage(data.msg); diff --git a/cli/onionshare_cli/web/chat_mode.py b/cli/onionshare_cli/web/chat_mode.py index e92ce385..b8053e0c 100644 --- a/cli/onionshare_cli/web/chat_mode.py +++ b/cli/onionshare_cli/web/chat_mode.py @@ -19,7 +19,7 @@ along with this program. If not, see . """ from flask import request, render_template, make_response, jsonify, session -from flask_socketio import emit, join_room, leave_room +from flask_socketio import emit class ChatModeWeb: @@ -33,7 +33,7 @@ class ChatModeWeb: self.web = web - # This tracks users in the room + # This tracks users in the server self.connected_users = [] # This tracks the history id @@ -61,7 +61,6 @@ class ChatModeWeb: if session.get("name") else self.common.build_username() ) - session["room"] = self.web.settings.default_settings["chat"]["room"] self.web.add_request( request.path, {"id": history_id, "status_code": 200}, @@ -111,12 +110,11 @@ class ChatModeWeb: ) return r - @self.web.socketio.on("joined", namespace="/chat") - def joined(message): + @self.web.socketio.on("connect", namespace="/chat") + def server_connect(): """Sent by clients when they enter a room. A status message is broadcast to all people in the room.""" self.connected_users.append(session.get("name")) - join_room(session.get("room")) emit( "status", { @@ -125,23 +123,23 @@ class ChatModeWeb: "connected_users": self.connected_users, "user": session.get("name"), }, - room=session.get("room"), + broadcast=True, ) @self.web.socketio.on("text", namespace="/chat") def text(message): """Sent by a client when the user entered a new message. - The message is sent to all people in the room.""" + The message is sent to all people in the server.""" emit( "message", {"username": session.get("name"), "msg": message["msg"]}, - room=session.get("room"), + broadcast=True, ) @self.web.socketio.on("update_username", namespace="/chat") def update_username(message): """Sent by a client when the user updates their username. - The message is sent to all people in the room.""" + The message is sent to all people in the server.""" current_name = session.get("name") if message.get("username", ""): session["name"] = message["username"] @@ -158,20 +156,20 @@ class ChatModeWeb: "old_name": current_name, "new_name": session.get("name"), }, - room=session.get("room"), + broadcast=True, ) @self.web.socketio.on("disconnect", namespace="/chat") def disconnect(): - """Sent by clients when they disconnect from a room. - A status message is broadcast to all people in the room.""" - self.connected_users.remove(session.get("name")) - leave_room(session.get("room")) + """Sent by clients when they disconnect. + A status message is broadcast to all people in the server.""" + if session.get("name") in self.connected_users: + self.connected_users.remove(session.get("name")) emit( "status", { "msg": "{} has left the room.".format(session.get("name")), "connected_users": self.connected_users, }, - room=session.get("room"), + broadcast=True, ) -- cgit v1.2.3-54-g00ecf From 2a7c3d68671bf4a85d3c67f9e710e6a6228bb81a Mon Sep 17 00:00:00 2001 From: Saptak S Date: Sun, 14 Nov 2021 21:06:47 +0530 Subject: Renames message event to chat_message --- cli/onionshare_cli/resources/static/js/chat.js | 2 +- cli/onionshare_cli/web/chat_mode.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/onionshare_cli/resources/static/js/chat.js b/cli/onionshare_cli/resources/static/js/chat.js index 78eaa7bc..2be55488 100644 --- a/cli/onionshare_cli/resources/static/js/chat.js +++ b/cli/onionshare_cli/resources/static/js/chat.js @@ -20,7 +20,7 @@ $(function () { // Triggered when message is received from a user. Even when sent // by self, it get triggered after the server sends back the emit. - socket.on('message', function (data) { + socket.on('chat_message', function (data) { addMessageToPanel(data, current_username, 'chat'); console.log(data, current_username); }); diff --git a/cli/onionshare_cli/web/chat_mode.py b/cli/onionshare_cli/web/chat_mode.py index b8053e0c..5f2e30f5 100644 --- a/cli/onionshare_cli/web/chat_mode.py +++ b/cli/onionshare_cli/web/chat_mode.py @@ -131,7 +131,7 @@ class ChatModeWeb: """Sent by a client when the user entered a new message. The message is sent to all people in the server.""" emit( - "message", + "chat_message", {"username": session.get("name"), "msg": message["msg"]}, broadcast=True, ) -- cgit v1.2.3-54-g00ecf From 6429392a405c2812a04ad4c7653d885e7595e255 Mon Sep 17 00:00:00 2001 From: Saptak S Date: Sun, 14 Nov 2021 23:28:17 +0530 Subject: Adds username validation for socketio event handler as well --- cli/onionshare_cli/resources/static/js/chat.js | 2 ++ cli/onionshare_cli/web/chat_mode.py | 44 +++++++++++++++----------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/cli/onionshare_cli/resources/static/js/chat.js b/cli/onionshare_cli/resources/static/js/chat.js index 2be55488..5f290be8 100644 --- a/cli/onionshare_cli/resources/static/js/chat.js +++ b/cli/onionshare_cli/resources/static/js/chat.js @@ -93,6 +93,8 @@ var updateUsername = function (socket) { console.log(response); if (response.success && response.username == username) { socket.emit('update_username', { username: username }); + } else { + addStatusMessage("Failed to updated username.") } }); return username; diff --git a/cli/onionshare_cli/web/chat_mode.py b/cli/onionshare_cli/web/chat_mode.py index 5f2e30f5..7965b722 100644 --- a/cli/onionshare_cli/web/chat_mode.py +++ b/cli/onionshare_cli/web/chat_mode.py @@ -47,6 +47,13 @@ class ChatModeWeb: self.define_routes() + def validate_username(self, username): + return ( + username + and username not in self.connected_users + and len(username) < 128 + ) + def define_routes(self): """ The web app routes for chatting @@ -78,11 +85,7 @@ class ChatModeWeb: def update_session_username(): history_id = self.cur_history_id data = request.get_json() - if ( - data.get("username", "") - and data.get("username", "") not in self.connected_users - and len(data.get("username", "")) < 128 - ): + if self.validate_username(data.get("username", "")): session["name"] = data.get("username", session.get("name")) self.web.add_request( request.path, @@ -141,23 +144,28 @@ class ChatModeWeb: """Sent by a client when the user updates their username. The message is sent to all people in the server.""" current_name = session.get("name") - if message.get("username", ""): + if self.validate_username(message.get("username", "")): session["name"] = message["username"] self.connected_users[ self.connected_users.index(current_name) ] = session.get("name") - emit( - "status", - { - "msg": "{} has updated their username to: {}".format( - current_name, session.get("name") - ), - "connected_users": self.connected_users, - "old_name": current_name, - "new_name": session.get("name"), - }, - broadcast=True, - ) + emit( + "status", + { + "msg": "{} has updated their username to: {}".format( + current_name, session.get("name") + ), + "connected_users": self.connected_users, + "old_name": current_name, + "new_name": session.get("name"), + }, + broadcast=True, + ) + else: + emit( + "status", + {"msg": "Failed to update username."}, + ) @self.web.socketio.on("disconnect", namespace="/chat") def disconnect(): -- cgit v1.2.3-54-g00ecf From b9d9f1491648ec76c1fe48f71afdb53a139e6206 Mon Sep 17 00:00:00 2001 From: Saptak S Date: Sun, 14 Nov 2021 23:44:16 +0530 Subject: Refuses connection if another session is already active --- cli/onionshare_cli/web/chat_mode.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/cli/onionshare_cli/web/chat_mode.py b/cli/onionshare_cli/web/chat_mode.py index 7965b722..b7ccbeb9 100644 --- a/cli/onionshare_cli/web/chat_mode.py +++ b/cli/onionshare_cli/web/chat_mode.py @@ -19,7 +19,7 @@ along with this program. If not, see . """ from flask import request, render_template, make_response, jsonify, session -from flask_socketio import emit +from flask_socketio import emit, ConnectionRefusedError class ChatModeWeb: @@ -117,17 +117,20 @@ class ChatModeWeb: def server_connect(): """Sent by clients when they enter a room. A status message is broadcast to all people in the room.""" - self.connected_users.append(session.get("name")) - emit( - "status", - { - "username": session.get("name"), - "msg": "{} has joined.".format(session.get("name")), - "connected_users": self.connected_users, - "user": session.get("name"), - }, - broadcast=True, - ) + if self.validate_username(session.get("name")): + self.connected_users.append(session.get("name")) + emit( + "status", + { + "username": session.get("name"), + "msg": "{} has joined.".format(session.get("name")), + "connected_users": self.connected_users, + "user": session.get("name"), + }, + broadcast=True, + ) + else: + raise ConnectionRefusedError('You are active from another session!') @self.web.socketio.on("text", namespace="/chat") def text(message): -- cgit v1.2.3-54-g00ecf From 8ec28da4fe1ff8264acd99b7e3e4e03e2322dc87 Mon Sep 17 00:00:00 2001 From: Saptak S Date: Mon, 15 Nov 2021 19:53:02 +0530 Subject: Fixes typo --- cli/onionshare_cli/resources/static/js/chat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/onionshare_cli/resources/static/js/chat.js b/cli/onionshare_cli/resources/static/js/chat.js index 5f290be8..5beb022f 100644 --- a/cli/onionshare_cli/resources/static/js/chat.js +++ b/cli/onionshare_cli/resources/static/js/chat.js @@ -94,7 +94,7 @@ var updateUsername = function (socket) { if (response.success && response.username == username) { socket.emit('update_username', { username: username }); } else { - addStatusMessage("Failed to updated username.") + addStatusMessage("Failed to update username.") } }); return username; -- cgit v1.2.3-54-g00ecf From 2a68b5bce11f9b5aba7887c96eeb439e74269dad Mon Sep 17 00:00:00 2001 From: Saptak S Date: Fri, 19 Nov 2021 15:25:10 +0530 Subject: Removes invisible whitespace characters from username in chat --- cli/onionshare_cli/resources/static/js/chat.js | 2 +- cli/onionshare_cli/web/chat_mode.py | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/cli/onionshare_cli/resources/static/js/chat.js b/cli/onionshare_cli/resources/static/js/chat.js index 5beb022f..a221106c 100644 --- a/cli/onionshare_cli/resources/static/js/chat.js +++ b/cli/onionshare_cli/resources/static/js/chat.js @@ -9,7 +9,7 @@ $(function () { ); // Store current username received from app context - var current_username = $('#username').val(); + var current_username = $('#username').val().trim(); // Triggered on any status change by any user, such as some // user joined, or changed username, or left, etc. diff --git a/cli/onionshare_cli/web/chat_mode.py b/cli/onionshare_cli/web/chat_mode.py index b7ccbeb9..3eda2867 100644 --- a/cli/onionshare_cli/web/chat_mode.py +++ b/cli/onionshare_cli/web/chat_mode.py @@ -48,6 +48,7 @@ class ChatModeWeb: self.define_routes() def validate_username(self, username): + username = username.strip() return ( username and username not in self.connected_users @@ -85,8 +86,9 @@ class ChatModeWeb: def update_session_username(): history_id = self.cur_history_id data = request.get_json() - if self.validate_username(data.get("username", "")): - session["name"] = data.get("username", session.get("name")) + username = data.get("username", session.get("name")).strip() + if self.validate_username(username): + session["name"] = username self.web.add_request( request.path, {"id": history_id, "status_code": 200}, @@ -147,8 +149,9 @@ class ChatModeWeb: """Sent by a client when the user updates their username. The message is sent to all people in the server.""" current_name = session.get("name") - if self.validate_username(message.get("username", "")): - session["name"] = message["username"] + new_name = message.get("username", "").strip() + if self.validate_username(new_name): + session["name"] = new_name self.connected_users[ self.connected_users.index(current_name) ] = session.get("name") -- cgit v1.2.3-54-g00ecf From 98f6f3b7d7cb390ea9536bf5fd2e4743be9b9fd4 Mon Sep 17 00:00:00 2001 From: Saptak S Date: Tue, 30 Nov 2021 01:19:29 +0530 Subject: Checks if username is ASCII string else throw an error --- cli/onionshare_cli/resources/static/js/chat.js | 12 +++++++++++- cli/onionshare_cli/web/chat_mode.py | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/cli/onionshare_cli/resources/static/js/chat.js b/cli/onionshare_cli/resources/static/js/chat.js index a221106c..21f00ca6 100644 --- a/cli/onionshare_cli/resources/static/js/chat.js +++ b/cli/onionshare_cli/resources/static/js/chat.js @@ -82,7 +82,7 @@ var emitMessage = function (socket) { var updateUsername = function (socket) { var username = $('#username').val(); - if (!checkUsernameExists(username) && !checkUsernameTooLong(username)) { + if (!checkUsernameExists(username) && !checkUsernameTooLong(username) && !checkUsernameAscii(username)) { $.ajax({ method: 'POST', url: `http://${document.domain}:${location.port}/update-session-username`, @@ -117,6 +117,16 @@ var createUserListHTML = function (connected_users, current_user) { return userListHTML; } +var checkUsernameAscii = function (username) { + // ASCII characters have code points in the range U+0000-U+007F. + $('#username-error').text(''); + if (!/^[\u0000-\u007f]*$/.test(username)) { + $('#username-error').text('Non-ASCII usernames are not supported.'); + return true; + } + return false; +} + var checkUsernameExists = function (username) { $('#username-error').text(''); var userMatches = $('#user-list li').filter(function () { diff --git a/cli/onionshare_cli/web/chat_mode.py b/cli/onionshare_cli/web/chat_mode.py index 3eda2867..f6aead45 100644 --- a/cli/onionshare_cli/web/chat_mode.py +++ b/cli/onionshare_cli/web/chat_mode.py @@ -51,6 +51,7 @@ class ChatModeWeb: username = username.strip() return ( username + and username.isascii() and username not in self.connected_users and len(username) < 128 ) -- cgit v1.2.3-54-g00ecf