summaryrefslogtreecommitdiff
path: root/onionshare/web/receive_mode.py
diff options
context:
space:
mode:
Diffstat (limited to 'onionshare/web/receive_mode.py')
-rw-r--r--onionshare/web/receive_mode.py284
1 files changed, 187 insertions, 97 deletions
diff --git a/onionshare/web/receive_mode.py b/onionshare/web/receive_mode.py
index 83040683..90f000b9 100644
--- a/onionshare/web/receive_mode.py
+++ b/onionshare/web/receive_mode.py
@@ -12,9 +12,10 @@ class ReceiveModeWeb:
"""
All of the web logic for receive mode
"""
+
def __init__(self, common, web):
self.common = common
- self.common.log('ReceiveModeWeb', '__init__')
+ self.common.log("ReceiveModeWeb", "__init__")
self.web = web
@@ -30,59 +31,84 @@ class ReceiveModeWeb:
"""
The web app routes for receiving files
"""
+
@self.web.app.route("/")
def index():
history_id = self.cur_history_id
self.cur_history_id += 1
- self.web.add_request(self.web.REQUEST_INDIVIDUAL_FILE_STARTED, '{}'.format(request.path), {
- 'id': history_id,
- 'status_code': 200
- })
+ self.web.add_request(
+ self.web.REQUEST_INDIVIDUAL_FILE_STARTED,
+ "{}".format(request.path),
+ {"id": history_id, "status_code": 200},
+ )
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))
+ r = make_response(
+ render_template(
+ "receive.html", static_url_path=self.web.static_url_path
+ )
+ )
return self.web.add_security_headers(r)
- @self.web.app.route("/upload", methods=['POST'])
+ @self.web.app.route("/upload", methods=["POST"])
def upload(ajax=False):
"""
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[]')
+ files = request.files.getlist("file[]")
filenames = []
for f in files:
- if f.filename != '':
+ 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', '/upload, uploaded {}, saving to {}'.format(f.filename, local_path))
- print('\n' + "Received: {}".format(local_path))
+ 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",
+ "/upload, uploaded {}, saving to {}".format(
+ f.filename, local_path
+ ),
+ )
+ print("\n" + "Received: {}".format(local_path))
if request.upload_error:
- self.common.log('ReceiveModeWeb', 'define_routes', '/upload, there was an upload error')
-
- self.web.add_request(self.web.REQUEST_ERROR_DATA_DIR_CANNOT_CREATE, request.path, {
- "receive_mode_dir": request.receive_mode_dir
- })
- print("Could not create OnionShare data folder: {}".format(request.receive_mode_dir))
-
- msg = 'Error uploading, please inform the OnionShare user'
+ self.common.log(
+ "ReceiveModeWeb",
+ "define_routes",
+ "/upload, there was an upload error",
+ )
+
+ self.web.add_request(
+ self.web.REQUEST_ERROR_DATA_DIR_CANNOT_CREATE,
+ request.path,
+ {"receive_mode_dir": request.receive_mode_dir},
+ )
+ print(
+ "Could not create OnionShare data folder: {}".format(
+ request.receive_mode_dir
+ )
+ )
+
+ msg = "Error uploading, please inform the OnionShare user"
if ajax:
return json.dumps({"error_flashes": [msg]})
else:
- flash(msg, 'error')
- return redirect('/')
+ flash(msg, "error")
+ return redirect("/")
# Note that flash strings are in English, and not translated, on purpose,
# to avoid leaking the locale of the OnionShare user
@@ -90,37 +116,45 @@ class ReceiveModeWeb:
info_flashes = []
if len(filenames) == 0:
- msg = 'No files uploaded'
+ msg = "No files uploaded"
if ajax:
info_flashes.append(msg)
else:
- flash(msg, 'info')
+ flash(msg, "info")
else:
- msg = 'Sent '
+ msg = "Sent "
for filename in filenames:
- msg += '{}, '.format(filename)
- msg = msg.rstrip(', ')
+ msg += "{}, ".format(filename)
+ msg = msg.rstrip(", ")
if ajax:
info_flashes.append(msg)
else:
- flash(msg, 'info')
+ flash(msg, "info")
if self.can_upload:
if ajax:
return json.dumps({"info_flashes": info_flashes})
else:
- return redirect('/')
+ return redirect("/")
else:
if ajax:
- return json.dumps({
- "new_body": render_template('thankyou.html', static_url_path=self.web.static_url_path)
- })
+ return json.dumps(
+ {
+ "new_body": render_template(
+ "thankyou.html",
+ static_url_path=self.web.static_url_path,
+ )
+ }
+ )
else:
# It was the last upload and the timer ran out
- r = make_response(render_template('thankyou.html'), static_url_path=self.web.static_url_path)
+ r = make_response(
+ render_template("thankyou.html"),
+ static_url_path=self.web.static_url_path,
+ )
return self.web.add_security_headers(r)
- @self.web.app.route("/upload-ajax", methods=['POST'])
+ @self.web.app.route("/upload-ajax", methods=["POST"])
def upload_ajax_public():
if not self.can_upload:
return self.web.error403()
@@ -132,13 +166,14 @@ class ReceiveModeWSGIMiddleware(object):
Custom WSGI middleware in order to attach the Web object to environ, so
ReceiveModeRequest can access it.
"""
+
def __init__(self, app, web):
self.app = app
self.web = web
def __call__(self, environ, start_response):
- environ['web'] = self.web
- environ['stop_q'] = self.web.stop_q
+ environ["web"] = self.web
+ environ["stop_q"] = self.web.stop_q
return self.app(environ, start_response)
@@ -148,6 +183,7 @@ class ReceiveModeFile(object):
written to it, in order to track the progress of uploads. It starts out with
a .part file extension, and when it's complete it removes that extension.
"""
+
def __init__(self, request, filename, write_func, close_func):
self.onionshare_request = request
self.onionshare_filename = filename
@@ -155,24 +191,44 @@ class ReceiveModeFile(object):
self.onionshare_close_func = close_func
self.filename = os.path.join(self.onionshare_request.receive_mode_dir, filename)
- self.filename_in_progress = '{}.part'.format(self.filename)
+ self.filename_in_progress = "{}.part".format(self.filename)
# Open the file
self.upload_error = False
try:
- self.f = open(self.filename_in_progress, 'wb+')
+ self.f = open(self.filename_in_progress, "wb+")
except:
# This will only happen if someone is messing with the data dir while
# OnionShare is running, but if it does make sure to throw an error
self.upload_error = True
- self.f = tempfile.TemporaryFile('wb+')
+ self.f = tempfile.TemporaryFile("wb+")
# Make all the file-like methods and attributes actually access the
# TemporaryFile, except for write
- attrs = ['closed', 'detach', 'fileno', 'flush', 'isatty', 'mode',
- 'name', 'peek', 'raw', 'read', 'read1', 'readable', 'readinto',
- 'readinto1', 'readline', 'readlines', 'seek', 'seekable', 'tell',
- 'truncate', 'writable', 'writelines']
+ attrs = [
+ "closed",
+ "detach",
+ "fileno",
+ "flush",
+ "isatty",
+ "mode",
+ "name",
+ "peek",
+ "raw",
+ "read",
+ "read1",
+ "readable",
+ "readinto",
+ "readinto1",
+ "readline",
+ "readlines",
+ "seek",
+ "seekable",
+ "tell",
+ "truncate",
+ "writable",
+ "writelines",
+ ]
for attr in attrs:
setattr(self, attr, getattr(self.f, attr))
@@ -214,20 +270,21 @@ class ReceiveModeRequest(Request):
A custom flask Request object that keeps track of how much data has been
uploaded for each file, for receive mode.
"""
+
def __init__(self, environ, populate_request=True, shallow=False):
super(ReceiveModeRequest, self).__init__(environ, populate_request, shallow)
- self.web = environ['web']
- self.stop_q = environ['stop_q']
+ self.web = environ["web"]
+ self.stop_q = environ["stop_q"]
- self.web.common.log('ReceiveModeRequest', '__init__')
+ self.web.common.log("ReceiveModeRequest", "__init__")
# Prevent running the close() method more than once
self.closed = False
# Is this a valid upload request?
self.upload_request = False
- if self.method == 'POST':
- if self.path == '/upload' or self.path == '/upload-ajax':
+ if self.method == "POST":
+ if self.path == "/upload" or self.path == "/upload-ajax":
self.upload_request = True
if self.upload_request:
@@ -238,7 +295,9 @@ class ReceiveModeRequest(Request):
now = datetime.now()
date_dir = now.strftime("%Y-%m-%d")
time_dir = now.strftime("%H.%M.%S")
- self.receive_mode_dir = os.path.join(self.web.common.settings.get('data_dir'), date_dir, time_dir)
+ self.receive_mode_dir = os.path.join(
+ self.web.common.settings.get("data_dir"), date_dir, time_dir
+ )
# Create that directory, which shouldn't exist yet
try:
@@ -250,7 +309,7 @@ class ReceiveModeRequest(Request):
# Keep going until we find a directory name that's available
i = 1
while True:
- new_receive_mode_dir = '{}-{}'.format(self.receive_mode_dir, i)
+ new_receive_mode_dir = "{}-{}".format(self.receive_mode_dir, i)
try:
os.makedirs(new_receive_mode_dir, 0o700, exist_ok=False)
self.receive_mode_dir = new_receive_mode_dir
@@ -260,15 +319,29 @@ class ReceiveModeRequest(Request):
i += 1
# Failsafe
if i == 100:
- self.web.common.log('ReceiveModeRequest', '__init__', 'Error finding available receive mode directory')
+ self.web.common.log(
+ "ReceiveModeRequest",
+ "__init__",
+ "Error finding available receive mode directory",
+ )
self.upload_error = True
break
except PermissionError:
- self.web.add_request(self.web.REQUEST_ERROR_DATA_DIR_CANNOT_CREATE, request.path, {
- "receive_mode_dir": self.receive_mode_dir
- })
- print("Could not create OnionShare data folder: {}".format(self.receive_mode_dir))
- self.web.common.log('ReceiveModeRequest', '__init__', 'Permission denied creating receive mode directory')
+ self.web.add_request(
+ self.web.REQUEST_ERROR_DATA_DIR_CANNOT_CREATE,
+ request.path,
+ {"receive_mode_dir": self.receive_mode_dir},
+ )
+ print(
+ "Could not create OnionShare data folder: {}".format(
+ self.receive_mode_dir
+ )
+ )
+ self.web.common.log(
+ "ReceiveModeRequest",
+ "__init__",
+ "Permission denied creating receive mode directory",
+ )
self.upload_error = True
# If there's an error so far, finish early
@@ -285,23 +358,29 @@ class ReceiveModeRequest(Request):
self.history_id = self.web.receive_mode.cur_history_id
self.web.receive_mode.cur_history_id += 1
- # Figure out the content length
+ # Figure out the content length
try:
- self.content_length = int(self.headers['Content-Length'])
+ self.content_length = int(self.headers["Content-Length"])
except:
self.content_length = 0
- print("{}: {}".format(
- datetime.now().strftime("%b %d, %I:%M%p"),
- strings._("receive_mode_upload_starting").format(self.web.common.human_readable_filesize(self.content_length))
- ))
+ print(
+ "{}: {}".format(
+ datetime.now().strftime("%b %d, %I:%M%p"),
+ strings._("receive_mode_upload_starting").format(
+ self.web.common.human_readable_filesize(self.content_length)
+ ),
+ )
+ )
# Don't tell the GUI that a request has started until we start receiving files
self.told_gui_about_request = False
self.previous_file = None
- def _get_file_stream(self, total_content_length, content_type, filename=None, content_length=None):
+ def _get_file_stream(
+ self, total_content_length, content_type, filename=None, content_length=None
+ ):
"""
This gets called for each file that gets uploaded, and returns an file-like
writable stream.
@@ -309,24 +388,26 @@ class ReceiveModeRequest(Request):
if self.upload_request:
if not self.told_gui_about_request:
# Tell the GUI about the request
- self.web.add_request(self.web.REQUEST_STARTED, self.path, {
- 'id': self.history_id,
- 'content_length': self.content_length
- })
+ self.web.add_request(
+ self.web.REQUEST_STARTED,
+ self.path,
+ {"id": self.history_id, "content_length": self.content_length},
+ )
self.web.receive_mode.uploads_in_progress.append(self.history_id)
self.told_gui_about_request = True
self.filename = secure_filename(filename)
- self.progress[self.filename] = {
- 'uploaded_bytes': 0,
- 'complete': False
- }
+ self.progress[self.filename] = {"uploaded_bytes": 0, "complete": False}
- f = ReceiveModeFile(self, self.filename, self.file_write_func, self.file_close_func)
+ f = ReceiveModeFile(
+ self, self.filename, self.file_write_func, self.file_close_func
+ )
if f.upload_error:
- self.web.common.log('ReceiveModeRequest', '_get_file_stream', 'Error creating file')
+ self.web.common.log(
+ "ReceiveModeRequest", "_get_file_stream", "Error creating file"
+ )
self.upload_error = True
return f
@@ -341,22 +422,25 @@ class ReceiveModeRequest(Request):
return
self.closed = True
- self.web.common.log('ReceiveModeRequest', 'close')
+ self.web.common.log("ReceiveModeRequest", "close")
try:
if self.told_gui_about_request:
history_id = self.history_id
- if not self.web.stop_q.empty() or not self.progress[self.filename]['complete']:
+ if (
+ not self.web.stop_q.empty()
+ or not self.progress[self.filename]["complete"]
+ ):
# Inform the GUI that the upload has canceled
- self.web.add_request(self.web.REQUEST_UPLOAD_CANCELED, self.path, {
- 'id': history_id
- })
+ self.web.add_request(
+ self.web.REQUEST_UPLOAD_CANCELED, self.path, {"id": history_id}
+ )
else:
# Inform the GUI that the upload has finished
- self.web.add_request(self.web.REQUEST_UPLOAD_FINISHED, self.path, {
- 'id': history_id
- })
+ self.web.add_request(
+ self.web.REQUEST_UPLOAD_FINISHED, self.path, {"id": history_id}
+ )
self.web.receive_mode.uploads_in_progress.remove(history_id)
except AttributeError:
@@ -370,28 +454,34 @@ class ReceiveModeRequest(Request):
return
if self.upload_request:
- self.progress[filename]['uploaded_bytes'] += length
+ self.progress[filename]["uploaded_bytes"] += length
if self.previous_file != filename:
self.previous_file = filename
- print('\r=> {:15s} {}'.format(
- self.web.common.human_readable_filesize(self.progress[filename]['uploaded_bytes']),
- filename
- ), end='')
+ print(
+ "\r=> {:15s} {}".format(
+ self.web.common.human_readable_filesize(
+ self.progress[filename]["uploaded_bytes"]
+ ),
+ filename,
+ ),
+ end="",
+ )
# Update the GUI on the upload progress
if self.told_gui_about_request:
- self.web.add_request(self.web.REQUEST_PROGRESS, self.path, {
- 'id': self.history_id,
- 'progress': self.progress
- })
+ self.web.add_request(
+ self.web.REQUEST_PROGRESS,
+ self.path,
+ {"id": self.history_id, "progress": self.progress},
+ )
def file_close_func(self, filename, upload_error=False):
"""
This function gets called when a specific file is closed.
"""
- self.progress[filename]['complete'] = True
+ self.progress[filename]["complete"] = True
# If the file tells us there was an upload error, let the request know as well
if upload_error: