mirror of
https://github.com/onionshare/onionshare.git
synced 2024-10-01 01:35:40 -04:00
Allow sending messages as well as uploading files in receive mode
This commit is contained in:
parent
470fb2bda3
commit
2acdea5229
@ -199,6 +199,18 @@ def main(cwd=None):
|
||||
default=None,
|
||||
help="Receive files: URL to receive webhook notifications",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--disable-text",
|
||||
action="store_true",
|
||||
dest="disable_text",
|
||||
help="Receive files: Disable receiving text messages",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--disable-files",
|
||||
action="store_true",
|
||||
dest="disable_files",
|
||||
help="Receive files: Disable receiving files",
|
||||
)
|
||||
# Website args
|
||||
parser.add_argument(
|
||||
"--disable_csp",
|
||||
@ -242,6 +254,8 @@ def main(cwd=None):
|
||||
autostop_sharing = not bool(args.no_autostop_sharing)
|
||||
data_dir = args.data_dir
|
||||
webhook_url = args.webhook_url
|
||||
disable_text = args.disable_text
|
||||
disable_files = args.disable_files
|
||||
disable_csp = bool(args.disable_csp)
|
||||
verbose = bool(args.verbose)
|
||||
|
||||
@ -292,6 +306,8 @@ def main(cwd=None):
|
||||
mode_settings.set("receive", "data_dir", data_dir)
|
||||
if webhook_url:
|
||||
mode_settings.set("receive", "webhook_url", webhook_url)
|
||||
mode_settings.set("receive", "disable_text", disable_text)
|
||||
mode_settings.set("receive", "disable_files", disable_files)
|
||||
if mode == "website":
|
||||
mode_settings.set("website", "disable_csp", disable_csp)
|
||||
else:
|
||||
@ -334,6 +350,11 @@ def main(cwd=None):
|
||||
if persistent_filename:
|
||||
mode_settings.set(mode, "filenames", filenames)
|
||||
|
||||
# In receive mode, you must allows either text, files, or both
|
||||
if mode == "receive" and disable_text and disable_files:
|
||||
print(f"You cannot disable both text and files")
|
||||
sys.exit()
|
||||
|
||||
# Create the Web object
|
||||
web = Web(common, False, mode_settings, mode)
|
||||
|
||||
|
@ -285,6 +285,13 @@ ul.breadcrumbs li a:link, ul.breadcrumbs li a:visited {
|
||||
margin: 0 0 20px 0;
|
||||
}
|
||||
|
||||
.upload-wrapper textarea {
|
||||
max-width: 95%;
|
||||
width: 600px;
|
||||
height: 150px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
div#uploads {
|
||||
width: 800px;
|
||||
max-width: 90%;
|
||||
|
@ -1,24 +1,35 @@
|
||||
$(function(){
|
||||
$(function () {
|
||||
// Add a flash message
|
||||
var flash = function(category, message) {
|
||||
var flash = function (category, message) {
|
||||
$('#flashes').append($('<li>').addClass(category).text(message));
|
||||
};
|
||||
|
||||
var scriptSrc = document.getElementById('receive-script').src;
|
||||
var staticImgPath = scriptSrc.substr(0, scriptSrc.lastIndexOf( '/' )+1).replace('js', 'img');
|
||||
var staticImgPath = scriptSrc.substr(0, scriptSrc.lastIndexOf('/') + 1).replace('js', 'img');
|
||||
|
||||
// Intercept submitting the form
|
||||
$('#send').submit(function(event){
|
||||
$('#send').submit(function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
// Create form data, and list of filenames
|
||||
var files = $('#file-select').get(0).files;
|
||||
var filenames = [];
|
||||
// Build the form data
|
||||
var formData = new FormData();
|
||||
for(var i = 0; i < files.length; i++) {
|
||||
var file = files[i];
|
||||
filenames.push(file.name);
|
||||
formData.append('file[]', file, file.name);
|
||||
|
||||
// Files
|
||||
var $fileSelect = $('#file-select');
|
||||
if ($fileSelect.length > 0) {
|
||||
var files = $fileSelect.get(0).files;
|
||||
var filenames = [];
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var file = files[i];
|
||||
filenames.push(file.name);
|
||||
formData.append('file[]', file, file.name);
|
||||
}
|
||||
}
|
||||
|
||||
// Text message
|
||||
var $text = $('#text');
|
||||
if ($text.length > 0) {
|
||||
formData.append("text", $text.val())
|
||||
}
|
||||
|
||||
// Reset the upload form
|
||||
@ -28,9 +39,9 @@ $(function(){
|
||||
// have access to the the XMLHttpRequest object
|
||||
var ajax = new XMLHttpRequest();
|
||||
|
||||
ajax.upload.addEventListener('progress', function(event){
|
||||
ajax.upload.addEventListener('progress', function (event) {
|
||||
// Update progress bar for this specific upload
|
||||
if(event.lengthComputable) {
|
||||
if (event.lengthComputable) {
|
||||
$('progress', ajax.$upload_div).attr({
|
||||
value: event.loaded,
|
||||
max: event.total,
|
||||
@ -39,13 +50,13 @@ $(function(){
|
||||
|
||||
// If it's finished sending all data to the first Tor node, remove cancel button
|
||||
// and update the status
|
||||
if(event.loaded == event.total) {
|
||||
if (event.loaded == event.total) {
|
||||
$('.cancel', ajax.$upload_div).remove();
|
||||
$('.upload-status', ajax.$upload_div).html('<img src="' + staticImgPath + '/ajax.gif" alt="" /> Waiting for data to finish traversing Tor network ...');
|
||||
}
|
||||
}, false);
|
||||
|
||||
ajax.addEventListener('load', function(event){
|
||||
ajax.addEventListener('load', function (event) {
|
||||
// Remove the upload div
|
||||
ajax.$upload_div.remove();
|
||||
|
||||
@ -54,38 +65,38 @@ $(function(){
|
||||
var response = JSON.parse(ajax.response);
|
||||
|
||||
// The 'new_body' response replaces the whole HTML document and ends
|
||||
if('new_body' in response) {
|
||||
if ('new_body' in response) {
|
||||
$('body').html(response['new_body']);
|
||||
return;
|
||||
}
|
||||
|
||||
// Show error flashes
|
||||
if('error_flashes' in response) {
|
||||
for(var i=0; i<response['error_flashes'].length; i++) {
|
||||
if ('error_flashes' in response) {
|
||||
for (var i = 0; i < response['error_flashes'].length; i++) {
|
||||
flash('error', response['error_flashes'][i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Show info flashes
|
||||
if('info_flashes' in response) {
|
||||
for(var i=0; i<response['info_flashes'].length; i++) {
|
||||
if ('info_flashes' in response) {
|
||||
for (var i = 0; i < response['info_flashes'].length; i++) {
|
||||
flash('info', response['info_flashes'][i]);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
flash('error', 'Invalid response from server: '+data);
|
||||
} catch (e) {
|
||||
flash('error', 'Invalid response from server: ' + data);
|
||||
}
|
||||
}, false);
|
||||
|
||||
ajax.addEventListener('error', function(event){
|
||||
flash('error', 'Error uploading: '+filenames.join(', '));
|
||||
ajax.addEventListener('error', function (event) {
|
||||
flash('error', 'Error uploading: ' + filenames.join(', '));
|
||||
|
||||
// Remove the upload div
|
||||
ajax.$upload_div.remove()
|
||||
}, false);
|
||||
|
||||
ajax.addEventListener('abort', function(event){
|
||||
flash('error', 'Upload aborted: '+filenames.join(', '));
|
||||
ajax.addEventListener('abort', function (event) {
|
||||
flash('error', 'Upload aborted: ' + filenames.join(', '));
|
||||
}, false);
|
||||
|
||||
// Make the upload div
|
||||
@ -114,7 +125,7 @@ $(function(){
|
||||
)
|
||||
.append($progress);
|
||||
|
||||
$cancel_button.click(function(){
|
||||
$cancel_button.click(function () {
|
||||
// Abort the upload, and remove the upload div
|
||||
ajax.abort();
|
||||
$upload_div.remove()
|
||||
|
@ -1,46 +1,64 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>OnionShare</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon">
|
||||
<link rel="stylesheet" rel="subresource" type="text/css" href="{{ static_url_path }}/css/style.css" media="all">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="clearfix">
|
||||
<img class="logo" src="{{ static_url_path }}/img/logo.png" title="OnionShare">
|
||||
<h1>OnionShare</h1>
|
||||
</header>
|
||||
<head>
|
||||
<title>OnionShare</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon">
|
||||
<link rel="stylesheet" rel="subresource" type="text/css" href="{{ static_url_path }}/css/style.css" media="all">
|
||||
</head>
|
||||
|
||||
<div class="upload-wrapper">
|
||||
<p><img class="logo" src="{{ static_url_path }}/img/logo_large.png" title="OnionShare"></p>
|
||||
<body>
|
||||
|
||||
<p class="upload-header">Send Files</p>
|
||||
<p class="upload-description">Select the files you want to send, then click "Send Files"...</p>
|
||||
<header class="clearfix">
|
||||
<img class="logo" src="{{ static_url_path }}/img/logo.png" title="OnionShare">
|
||||
<h1>OnionShare</h1>
|
||||
</header>
|
||||
|
||||
<div id="uploads"></div>
|
||||
<div class="upload-wrapper">
|
||||
<p><img class="logo" src="{{ static_url_path }}/img/logo_large.png" title="OnionShare"></p>
|
||||
|
||||
<div>
|
||||
<ul id="flashes" class="flashes">
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<li class="{{ category }}">{{ message }}</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</ul>
|
||||
</div>
|
||||
{% if not disable_text and not disable_files %}
|
||||
<p class="upload-header">Submit Files or Messages</p>
|
||||
<p class="upload-description">You can submit files, a message, or both</p>
|
||||
{% endif %}
|
||||
{% if not disable_text and disable_files %}
|
||||
<p class="upload-header">Submit Messages</p>
|
||||
<p class="upload-description">You can submit a message</p>
|
||||
{% endif %}
|
||||
{% if disable_text and not disable_files %}
|
||||
<p class="upload-header">Submit Files</p>
|
||||
<p class="upload-description">You can submit files</p>
|
||||
{% endif %}
|
||||
|
||||
<form id="send" method="post" enctype="multipart/form-data" action="/upload">
|
||||
<p><input type="file" id="file-select" name="file[]" multiple /></p>
|
||||
<p><button type="submit" id="send-button" class="button">Send Files</button></p>
|
||||
</form>
|
||||
<div id="uploads"></div>
|
||||
|
||||
<div>
|
||||
<ul id="flashes" class="flashes">
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<li class="{{ category }}">{{ message }}</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</ul>
|
||||
</div>
|
||||
<script src="{{ static_url_path }}/js/jquery-3.5.1.min.js"></script>
|
||||
<script async src="{{ static_url_path }}/js/receive.js" id="receive-script"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<form id="send" method="post" enctype="multipart/form-data" action="/upload">
|
||||
{% if not disable_files %}
|
||||
<p><input type="file" id="file-select" name="file[]" multiple /></p>
|
||||
{% endif %}
|
||||
{% if not disable_text %}
|
||||
<p><textarea id="text" name="text" placeholder="Write a message"></textarea></p>
|
||||
{% endif %}
|
||||
<p><button type="submit" id="send-button" class="button">Submit</button></p>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<script src="{{ static_url_path }}/js/jquery-3.5.1.min.js"></script>
|
||||
<script async src="{{ static_url_path }}/js/receive.js" id="receive-script"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -64,7 +64,10 @@ class ReceiveModeWeb:
|
||||
self.web.add_request(self.web.REQUEST_LOAD, request.path)
|
||||
r = make_response(
|
||||
render_template(
|
||||
"receive.html", static_url_path=self.web.static_url_path
|
||||
"receive.html",
|
||||
static_url_path=self.web.static_url_path,
|
||||
disable_text=self.web.settings.get("receive", "disable_text"),
|
||||
disable_files=self.web.settings.get("receive", "disable_files"),
|
||||
)
|
||||
)
|
||||
return self.web.add_security_headers(r)
|
||||
@ -75,44 +78,88 @@ class ReceiveModeWeb:
|
||||
Handle the upload files POST request, though at this point, the files have
|
||||
already been uploaded and saved to their correct locations.
|
||||
"""
|
||||
files = request.files.getlist("file[]")
|
||||
filenames = []
|
||||
for f in files:
|
||||
if f.filename != "":
|
||||
filename = secure_filename(f.filename)
|
||||
filenames.append(filename)
|
||||
local_path = os.path.join(request.receive_mode_dir, filename)
|
||||
basename = os.path.basename(local_path)
|
||||
text_received = False
|
||||
if not self.web.settings.get("receive", "disable_text"):
|
||||
text_message = request.form.get("text")
|
||||
if text_message:
|
||||
if text_message.strip() != "":
|
||||
text_received = True
|
||||
filename = "message.txt"
|
||||
local_path = os.path.join(request.receive_mode_dir, filename)
|
||||
|
||||
# Tell the GUI the receive mode directory for this file
|
||||
self.web.add_request(
|
||||
self.web.REQUEST_UPLOAD_SET_DIR,
|
||||
request.path,
|
||||
{
|
||||
"id": request.history_id,
|
||||
"filename": basename,
|
||||
"dir": request.receive_mode_dir,
|
||||
},
|
||||
)
|
||||
with open(local_path, "w") as f:
|
||||
f.write(text_message)
|
||||
|
||||
self.common.log(
|
||||
"ReceiveModeWeb",
|
||||
"define_routes",
|
||||
f"/upload, uploaded {f.filename}, saving to {local_path}",
|
||||
)
|
||||
print(f"\nReceived: {local_path}")
|
||||
basename = os.path.basename(local_path)
|
||||
|
||||
# TODO: possibly change this
|
||||
self.web.add_request(
|
||||
self.web.REQUEST_UPLOAD_SET_DIR,
|
||||
request.path,
|
||||
{
|
||||
"id": request.history_id,
|
||||
"filename": basename,
|
||||
"dir": request.receive_mode_dir,
|
||||
},
|
||||
)
|
||||
|
||||
self.common.log(
|
||||
"ReceiveModeWeb",
|
||||
"define_routes",
|
||||
f"/upload, sent text message, saving to {local_path}",
|
||||
)
|
||||
print(f"\nReceived: {local_path}")
|
||||
|
||||
files_received = 0
|
||||
if not self.web.settings.get("receive", "disable_files"):
|
||||
files = request.files.getlist("file[]")
|
||||
|
||||
filenames = []
|
||||
for f in files:
|
||||
if f.filename != "":
|
||||
filename = secure_filename(f.filename)
|
||||
filenames.append(filename)
|
||||
local_path = os.path.join(request.receive_mode_dir, filename)
|
||||
basename = os.path.basename(local_path)
|
||||
|
||||
# Tell the GUI the receive mode directory for this file
|
||||
self.web.add_request(
|
||||
self.web.REQUEST_UPLOAD_SET_DIR,
|
||||
request.path,
|
||||
{
|
||||
"id": request.history_id,
|
||||
"filename": basename,
|
||||
"dir": request.receive_mode_dir,
|
||||
},
|
||||
)
|
||||
|
||||
self.common.log(
|
||||
"ReceiveModeWeb",
|
||||
"define_routes",
|
||||
f"/upload, uploaded {f.filename}, saving to {local_path}",
|
||||
)
|
||||
print(f"\nReceived: {local_path}")
|
||||
|
||||
files_received = len(filenames)
|
||||
|
||||
# Send webhook if configured
|
||||
if (
|
||||
self.web.settings.get("receive", "webhook_url")
|
||||
self.web.settings.get("receive", "webhook_url") is not None
|
||||
and not request.upload_error
|
||||
and len(files) > 0
|
||||
and (text_received or files_received)
|
||||
):
|
||||
if len(files) == 1:
|
||||
file_msg = "1 file"
|
||||
else:
|
||||
file_msg = f"{len(files)} files"
|
||||
self.send_webhook_notification(f"{file_msg} uploaded to OnionShare")
|
||||
msg = ""
|
||||
if files_received > 0:
|
||||
if files_received == 1:
|
||||
msg += "1 file"
|
||||
else:
|
||||
msg += f"{files_received} files"
|
||||
if text_received:
|
||||
if msg == "":
|
||||
msg = "A text message"
|
||||
else:
|
||||
msg += " and a text message"
|
||||
self.send_webhook_notification(f"{msg} submitted to OnionShare")
|
||||
|
||||
if request.upload_error:
|
||||
self.common.log(
|
||||
@ -140,21 +187,27 @@ class ReceiveModeWeb:
|
||||
if ajax:
|
||||
info_flashes = []
|
||||
|
||||
if len(filenames) == 0:
|
||||
msg = "No files uploaded"
|
||||
if ajax:
|
||||
info_flashes.append(msg)
|
||||
else:
|
||||
flash(msg, "info")
|
||||
else:
|
||||
msg = "Sent "
|
||||
if files_received > 0:
|
||||
files_msg = ""
|
||||
for filename in filenames:
|
||||
msg += f"{filename}, "
|
||||
msg = msg.rstrip(", ")
|
||||
if ajax:
|
||||
info_flashes.append(msg)
|
||||
files_msg += f"{filename}, "
|
||||
files_msg = files_msg.rstrip(", ")
|
||||
|
||||
if text_received:
|
||||
if files_received > 0:
|
||||
msg = f"Message submitted, uploaded {files_msg}"
|
||||
else:
|
||||
flash(msg, "info")
|
||||
msg = "Message submitted"
|
||||
else:
|
||||
if files_received > 0:
|
||||
msg = f"Uploaded {files_msg}"
|
||||
else:
|
||||
msg = "Nothing submitted"
|
||||
|
||||
if ajax:
|
||||
info_flashes.append(msg)
|
||||
else:
|
||||
flash(msg, "info")
|
||||
|
||||
if self.can_upload:
|
||||
if ajax:
|
||||
|
Loading…
Reference in New Issue
Block a user