mirror of
https://github.com/onionshare/onionshare.git
synced 2024-10-01 01:35:40 -04:00
Merge branch 'ros-fixes' into release-2.5
This commit is contained in:
commit
c8ea770223
@ -55,12 +55,8 @@ class ModeSettings:
|
|||||||
"disable_text": False,
|
"disable_text": False,
|
||||||
"disable_files": False,
|
"disable_files": False,
|
||||||
},
|
},
|
||||||
"website": {
|
"website": {"disable_csp": False, "custom_csp": None, "filenames": []},
|
||||||
"disable_csp": False,
|
"chat": {},
|
||||||
"custom_csp": None,
|
|
||||||
"filenames": []
|
|
||||||
},
|
|
||||||
"chat": {"room": "default"},
|
|
||||||
}
|
}
|
||||||
self._settings = {}
|
self._settings = {}
|
||||||
|
|
||||||
|
@ -9,31 +9,25 @@ $(function () {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Store current username received from app context
|
// Store current username received from app context
|
||||||
var current_username = $('#username').val();
|
var current_username = $('#username').val().trim();
|
||||||
|
|
||||||
// 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
|
// Triggered on any status change by any user, such as some
|
||||||
// user joined, or changed username, or left, etc.
|
// user joined, or changed username, or left, etc.
|
||||||
socket.on('status', function (data) {
|
socket.on('status', function (data) {
|
||||||
addMessageToRoom(data, current_username, 'status');
|
addMessageToPanel(data, current_username, 'status');
|
||||||
console.log(data, current_username);
|
console.log(data, current_username);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Triggered when message is received from a user. Even when sent
|
// Triggered when message is received from a user. Even when sent
|
||||||
// by self, it get triggered after the server sends back the emit.
|
// by self, it get triggered after the server sends back the emit.
|
||||||
socket.on('message', function (data) {
|
socket.on('chat_message', function (data) {
|
||||||
addMessageToRoom(data, current_username, 'chat');
|
addMessageToPanel(data, current_username, 'chat');
|
||||||
console.log(data, current_username);
|
console.log(data, current_username);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Triggered when disconnected either by server stop or timeout
|
// Triggered when disconnected either by server stop or timeout
|
||||||
socket.on('disconnect', function (data) {
|
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) {
|
socket.on('connect_error', function (error) {
|
||||||
console.log("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();
|
var scrollDiff = getScrollDiffBefore();
|
||||||
if (messageType === 'status') {
|
if (messageType === 'status') {
|
||||||
addStatusMessage(data.msg);
|
addStatusMessage(data.msg);
|
||||||
@ -88,7 +82,7 @@ var emitMessage = function (socket) {
|
|||||||
|
|
||||||
var updateUsername = function (socket) {
|
var updateUsername = function (socket) {
|
||||||
var username = $('#username').val();
|
var username = $('#username').val();
|
||||||
if (!checkUsernameExists(username) && !checkUsernameTooLong(username)) {
|
if (!checkUsernameExists(username) && !checkUsernameTooLong(username) && !checkUsernameAscii(username)) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: `http://${document.domain}:${location.port}/update-session-username`,
|
url: `http://${document.domain}:${location.port}/update-session-username`,
|
||||||
@ -99,6 +93,8 @@ var updateUsername = function (socket) {
|
|||||||
console.log(response);
|
console.log(response);
|
||||||
if (response.success && response.username == username) {
|
if (response.success && response.username == username) {
|
||||||
socket.emit('update_username', { username: username });
|
socket.emit('update_username', { username: username });
|
||||||
|
} else {
|
||||||
|
addStatusMessage("Failed to update username.")
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return username;
|
return username;
|
||||||
@ -121,6 +117,16 @@ var createUserListHTML = function (connected_users, current_user) {
|
|||||||
return userListHTML;
|
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) {
|
var checkUsernameExists = function (username) {
|
||||||
$('#username-error').text('');
|
$('#username-error').text('');
|
||||||
var userMatches = $('#user-list li').filter(function () {
|
var userMatches = $('#user-list li').filter(function () {
|
||||||
|
@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from flask import request, render_template, make_response, jsonify, session
|
from flask import request, render_template, make_response, jsonify, session
|
||||||
from flask_socketio import emit, join_room, leave_room
|
from flask_socketio import emit, ConnectionRefusedError
|
||||||
|
|
||||||
|
|
||||||
class ChatModeWeb:
|
class ChatModeWeb:
|
||||||
@ -33,7 +33,7 @@ class ChatModeWeb:
|
|||||||
|
|
||||||
self.web = web
|
self.web = web
|
||||||
|
|
||||||
# This tracks users in the room
|
# This tracks users in the server
|
||||||
self.connected_users = []
|
self.connected_users = []
|
||||||
|
|
||||||
# This tracks the history id
|
# This tracks the history id
|
||||||
@ -47,6 +47,15 @@ class ChatModeWeb:
|
|||||||
|
|
||||||
self.define_routes()
|
self.define_routes()
|
||||||
|
|
||||||
|
def validate_username(self, username):
|
||||||
|
username = username.strip()
|
||||||
|
return (
|
||||||
|
username
|
||||||
|
and username.isascii()
|
||||||
|
and username not in self.connected_users
|
||||||
|
and len(username) < 128
|
||||||
|
)
|
||||||
|
|
||||||
def define_routes(self):
|
def define_routes(self):
|
||||||
"""
|
"""
|
||||||
The web app routes for chatting
|
The web app routes for chatting
|
||||||
@ -61,7 +70,6 @@ class ChatModeWeb:
|
|||||||
if session.get("name")
|
if session.get("name")
|
||||||
else self.common.build_username()
|
else self.common.build_username()
|
||||||
)
|
)
|
||||||
session["room"] = self.web.settings.default_settings["chat"]["room"]
|
|
||||||
self.web.add_request(
|
self.web.add_request(
|
||||||
request.path,
|
request.path,
|
||||||
{"id": history_id, "status_code": 200},
|
{"id": history_id, "status_code": 200},
|
||||||
@ -79,12 +87,9 @@ class ChatModeWeb:
|
|||||||
def update_session_username():
|
def update_session_username():
|
||||||
history_id = self.cur_history_id
|
history_id = self.cur_history_id
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
if (
|
username = data.get("username", session.get("name")).strip()
|
||||||
data.get("username", "")
|
if self.validate_username(username):
|
||||||
and data.get("username", "") not in self.connected_users
|
session["name"] = username
|
||||||
and len(data.get("username", "")) < 128
|
|
||||||
):
|
|
||||||
session["name"] = data.get("username", session.get("name"))
|
|
||||||
self.web.add_request(
|
self.web.add_request(
|
||||||
request.path,
|
request.path,
|
||||||
{"id": history_id, "status_code": 200},
|
{"id": history_id, "status_code": 200},
|
||||||
@ -111,67 +116,75 @@ class ChatModeWeb:
|
|||||||
)
|
)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
@self.web.socketio.on("joined", namespace="/chat")
|
@self.web.socketio.on("connect", namespace="/chat")
|
||||||
def joined(message):
|
def server_connect():
|
||||||
"""Sent by clients when they enter a room.
|
"""Sent by clients when they enter a room.
|
||||||
A status message is broadcast to all people in the room."""
|
A status message is broadcast to all people in the room."""
|
||||||
self.connected_users.append(session.get("name"))
|
if self.validate_username(session.get("name")):
|
||||||
join_room(session.get("room"))
|
self.connected_users.append(session.get("name"))
|
||||||
emit(
|
emit(
|
||||||
"status",
|
"status",
|
||||||
{
|
{
|
||||||
"username": session.get("name"),
|
"username": session.get("name"),
|
||||||
"msg": "{} has joined.".format(session.get("name")),
|
"msg": "{} has joined.".format(session.get("name")),
|
||||||
"connected_users": self.connected_users,
|
"connected_users": self.connected_users,
|
||||||
"user": session.get("name"),
|
"user": session.get("name"),
|
||||||
},
|
},
|
||||||
room=session.get("room"),
|
broadcast=True,
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
raise ConnectionRefusedError('You are active from another session!')
|
||||||
|
|
||||||
@self.web.socketio.on("text", namespace="/chat")
|
@self.web.socketio.on("text", namespace="/chat")
|
||||||
def text(message):
|
def text(message):
|
||||||
"""Sent by a client when the user entered a new 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(
|
emit(
|
||||||
"message",
|
"chat_message",
|
||||||
{"username": session.get("name"), "msg": message["msg"]},
|
{"username": session.get("name"), "msg": message["msg"]},
|
||||||
room=session.get("room"),
|
broadcast=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@self.web.socketio.on("update_username", namespace="/chat")
|
@self.web.socketio.on("update_username", namespace="/chat")
|
||||||
def update_username(message):
|
def update_username(message):
|
||||||
"""Sent by a client when the user updates their username.
|
"""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")
|
current_name = session.get("name")
|
||||||
if message.get("username", ""):
|
new_name = message.get("username", "").strip()
|
||||||
session["name"] = message["username"]
|
if self.validate_username(new_name):
|
||||||
|
session["name"] = new_name
|
||||||
self.connected_users[
|
self.connected_users[
|
||||||
self.connected_users.index(current_name)
|
self.connected_users.index(current_name)
|
||||||
] = session.get("name")
|
] = session.get("name")
|
||||||
emit(
|
emit(
|
||||||
"status",
|
"status",
|
||||||
{
|
{
|
||||||
"msg": "{} has updated their username to: {}".format(
|
"msg": "{} has updated their username to: {}".format(
|
||||||
current_name, session.get("name")
|
current_name, session.get("name")
|
||||||
),
|
),
|
||||||
"connected_users": self.connected_users,
|
"connected_users": self.connected_users,
|
||||||
"old_name": current_name,
|
"old_name": current_name,
|
||||||
"new_name": session.get("name"),
|
"new_name": session.get("name"),
|
||||||
},
|
},
|
||||||
room=session.get("room"),
|
broadcast=True,
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
emit(
|
||||||
|
"status",
|
||||||
|
{"msg": "Failed to update username."},
|
||||||
|
)
|
||||||
|
|
||||||
@self.web.socketio.on("disconnect", namespace="/chat")
|
@self.web.socketio.on("disconnect", namespace="/chat")
|
||||||
def disconnect():
|
def disconnect():
|
||||||
"""Sent by clients when they disconnect from a room.
|
"""Sent by clients when they disconnect.
|
||||||
A status message is broadcast to all people in the room."""
|
A status message is broadcast to all people in the server."""
|
||||||
self.connected_users.remove(session.get("name"))
|
if session.get("name") in self.connected_users:
|
||||||
leave_room(session.get("room"))
|
self.connected_users.remove(session.get("name"))
|
||||||
emit(
|
emit(
|
||||||
"status",
|
"status",
|
||||||
{
|
{
|
||||||
"msg": "{} has left the room.".format(session.get("name")),
|
"msg": "{} has left the room.".format(session.get("name")),
|
||||||
"connected_users": self.connected_users,
|
"connected_users": self.connected_users,
|
||||||
},
|
},
|
||||||
room=session.get("room"),
|
broadcast=True,
|
||||||
)
|
)
|
||||||
|
@ -378,7 +378,7 @@ class ReceiveModeRequest(Request):
|
|||||||
# Figure out what files should be saved
|
# Figure out what files should be saved
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
date_dir = now.strftime("%Y-%m-%d")
|
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.receive_mode_dir = os.path.join(
|
||||||
self.web.settings.get("receive", "data_dir"), date_dir, time_dir
|
self.web.settings.get("receive", "data_dir"), date_dir, time_dir
|
||||||
)
|
)
|
||||||
|
@ -481,6 +481,7 @@ class IndividualFileHistoryItem(HistoryItem):
|
|||||||
self.common.gui.css["history_individual_file_timestamp_label"]
|
self.common.gui.css["history_individual_file_timestamp_label"]
|
||||||
)
|
)
|
||||||
self.path_label = QtWidgets.QLabel(self.path)
|
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.path_label.setStyleSheet(self.common.gui.css["history_default_label"])
|
||||||
self.status_code_label = QtWidgets.QLabel()
|
self.status_code_label = QtWidgets.QLabel()
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import glob
|
||||||
import pytest
|
import pytest
|
||||||
import os
|
import os
|
||||||
import requests
|
import requests
|
||||||
@ -35,17 +36,17 @@ class TestReceive(GuiBaseTest):
|
|||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
for _ in range(10):
|
for _ in range(10):
|
||||||
date_dir = now.strftime("%Y-%m-%d")
|
date_dir = now.strftime("%Y-%m-%d")
|
||||||
if identical_files_at_once:
|
time_dir = now.strftime("%H%M%S")
|
||||||
time_dir = now.strftime("%H%M%S-1")
|
|
||||||
else:
|
|
||||||
time_dir = now.strftime("%H%M%S")
|
|
||||||
receive_mode_dir = os.path.join(
|
receive_mode_dir = os.path.join(
|
||||||
tab.settings.get("receive", "data_dir"), date_dir, time_dir
|
tab.settings.get("receive", "data_dir"), date_dir, time_dir
|
||||||
)
|
)
|
||||||
expected_filename = os.path.join(receive_mode_dir, expected_basename)
|
# The directories have microseconds in the name, so we need
|
||||||
if os.path.exists(expected_filename):
|
# to use globbing against directory names containing the same
|
||||||
exists = True
|
# second in order to try to find the file.
|
||||||
break
|
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)
|
now = now - timedelta(seconds=1)
|
||||||
|
|
||||||
self.assertTrue(exists)
|
self.assertTrue(exists)
|
||||||
@ -83,17 +84,18 @@ class TestReceive(GuiBaseTest):
|
|||||||
for _ in range(10):
|
for _ in range(10):
|
||||||
date_dir = now.strftime("%Y-%m-%d")
|
date_dir = now.strftime("%Y-%m-%d")
|
||||||
time_dir = now.strftime("%H%M%S")
|
time_dir = now.strftime("%H%M%S")
|
||||||
expected_filename = os.path.join(
|
expected_estimated_filename = os.path.join(
|
||||||
tab.settings.get("receive", "data_dir"),
|
tab.settings.get("receive", "data_dir"),
|
||||||
date_dir,
|
date_dir,
|
||||||
f"{time_dir}-message.txt",
|
f"{time_dir}*-message.txt",
|
||||||
)
|
)
|
||||||
if os.path.exists(expected_filename):
|
for path in glob.glob(expected_estimated_filename):
|
||||||
with open(expected_filename) as f:
|
if os.path.exists(path):
|
||||||
assert f.read() == message
|
with open(path) as f:
|
||||||
|
assert f.read() == message
|
||||||
|
|
||||||
exists = True
|
exists = True
|
||||||
break
|
break
|
||||||
now = now - timedelta(seconds=1)
|
now = now - timedelta(seconds=1)
|
||||||
|
|
||||||
self.assertTrue(exists)
|
self.assertTrue(exists)
|
||||||
|
Loading…
Reference in New Issue
Block a user