mirror of
https://github.com/onionshare/onionshare.git
synced 2024-10-01 01:35:40 -04:00
Hold a share open if its timer hsa expired but a file is still uploading. Don't allow other uploads during this time
This commit is contained in:
parent
4777c45ad8
commit
b06fd8af26
@ -118,6 +118,7 @@ class Web(object):
|
|||||||
self.download_in_progress = False
|
self.download_in_progress = False
|
||||||
|
|
||||||
self.done = False
|
self.done = False
|
||||||
|
self.can_upload = True
|
||||||
|
|
||||||
# If the client closes the OnionShare window while a download is in progress,
|
# If the client closes the OnionShare window while a download is in progress,
|
||||||
# it should immediately stop serving the file. The client_cancel global is
|
# it should immediately stop serving the file. The client_cancel global is
|
||||||
@ -343,96 +344,104 @@ class Web(object):
|
|||||||
"""
|
"""
|
||||||
Upload files.
|
Upload files.
|
||||||
"""
|
"""
|
||||||
# Make sure downloads_dir exists
|
while self.can_upload:
|
||||||
valid = True
|
# Make sure downloads_dir exists
|
||||||
try:
|
valid = True
|
||||||
self.common.validate_downloads_dir()
|
try:
|
||||||
except DownloadsDirErrorCannotCreate:
|
self.common.validate_downloads_dir()
|
||||||
self.add_request(Web.REQUEST_ERROR_DOWNLOADS_DIR_CANNOT_CREATE, request.path)
|
except DownloadsDirErrorCannotCreate:
|
||||||
print(strings._('error_cannot_create_downloads_dir').format(self.common.settings.get('downloads_dir')))
|
self.add_request(Web.REQUEST_ERROR_DOWNLOADS_DIR_CANNOT_CREATE, request.path)
|
||||||
valid = False
|
print(strings._('error_cannot_create_downloads_dir').format(self.common.settings.get('downloads_dir')))
|
||||||
except DownloadsDirErrorNotWritable:
|
valid = False
|
||||||
self.add_request(Web.REQUEST_ERROR_DOWNLOADS_DIR_NOT_WRITABLE, request.path)
|
except DownloadsDirErrorNotWritable:
|
||||||
print(strings._('error_downloads_dir_not_writable').format(self.common.settings.get('downloads_dir')))
|
self.add_request(Web.REQUEST_ERROR_DOWNLOADS_DIR_NOT_WRITABLE, request.path)
|
||||||
valid = False
|
print(strings._('error_downloads_dir_not_writable').format(self.common.settings.get('downloads_dir')))
|
||||||
if not valid:
|
valid = False
|
||||||
flash('Error uploading, please inform the OnionShare user', 'error')
|
if not valid:
|
||||||
|
flash('Error uploading, please inform the OnionShare user', 'error')
|
||||||
|
if self.common.settings.get('public_mode'):
|
||||||
|
return redirect('/')
|
||||||
|
else:
|
||||||
|
return redirect('/{}'.format(slug_candidate))
|
||||||
|
|
||||||
|
files = request.files.getlist('file[]')
|
||||||
|
filenames = []
|
||||||
|
print('')
|
||||||
|
for f in files:
|
||||||
|
if f.filename != '':
|
||||||
|
# Automatically rename the file, if a file of the same name already exists
|
||||||
|
filename = secure_filename(f.filename)
|
||||||
|
filenames.append(filename)
|
||||||
|
local_path = os.path.join(self.common.settings.get('downloads_dir'), filename)
|
||||||
|
if os.path.exists(local_path):
|
||||||
|
if '.' in filename:
|
||||||
|
# Add "-i", e.g. change "foo.txt" to "foo-2.txt"
|
||||||
|
parts = filename.split('.')
|
||||||
|
name = parts[:-1]
|
||||||
|
ext = parts[-1]
|
||||||
|
|
||||||
|
i = 2
|
||||||
|
valid = False
|
||||||
|
while not valid:
|
||||||
|
new_filename = '{}-{}.{}'.format('.'.join(name), i, ext)
|
||||||
|
local_path = os.path.join(self.common.settings.get('downloads_dir'), new_filename)
|
||||||
|
if os.path.exists(local_path):
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
valid = True
|
||||||
|
else:
|
||||||
|
# If no extension, just add "-i", e.g. change "foo" to "foo-2"
|
||||||
|
i = 2
|
||||||
|
valid = False
|
||||||
|
while not valid:
|
||||||
|
new_filename = '{}-{}'.format(filename, i)
|
||||||
|
local_path = os.path.join(self.common.settings.get('downloads_dir'), new_filename)
|
||||||
|
if os.path.exists(local_path):
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
valid = True
|
||||||
|
|
||||||
|
basename = os.path.basename(local_path)
|
||||||
|
if f.filename != basename:
|
||||||
|
# Tell the GUI that the file has changed names
|
||||||
|
self.add_request(Web.REQUEST_UPLOAD_FILE_RENAMED, request.path, {
|
||||||
|
'id': request.upload_id,
|
||||||
|
'old_filename': f.filename,
|
||||||
|
'new_filename': basename
|
||||||
|
})
|
||||||
|
|
||||||
|
self.common.log('Web', 'receive_routes', '/upload, uploaded {}, saving to {}'.format(f.filename, local_path))
|
||||||
|
print(strings._('receive_mode_received_file').format(local_path))
|
||||||
|
f.save(local_path)
|
||||||
|
|
||||||
|
# Note that flash strings are on English, and not translated, on purpose,
|
||||||
|
# to avoid leaking the locale of the OnionShare user
|
||||||
|
if len(filenames) == 0:
|
||||||
|
flash('No files uploaded', 'info')
|
||||||
|
else:
|
||||||
|
for filename in filenames:
|
||||||
|
flash('Sent {}'.format(filename), 'info')
|
||||||
|
|
||||||
|
|
||||||
|
# Register that uploads were sent (for shutdown timer)
|
||||||
|
self.done = True
|
||||||
|
|
||||||
if self.common.settings.get('public_mode'):
|
if self.common.settings.get('public_mode'):
|
||||||
return redirect('/')
|
return redirect('/')
|
||||||
else:
|
else:
|
||||||
return redirect('/{}'.format(slug_candidate))
|
return redirect('/{}'.format(slug_candidate))
|
||||||
|
|
||||||
files = request.files.getlist('file[]')
|
|
||||||
filenames = []
|
|
||||||
print('')
|
|
||||||
for f in files:
|
|
||||||
if f.filename != '':
|
|
||||||
# Automatically rename the file, if a file of the same name already exists
|
|
||||||
filename = secure_filename(f.filename)
|
|
||||||
filenames.append(filename)
|
|
||||||
local_path = os.path.join(self.common.settings.get('downloads_dir'), filename)
|
|
||||||
if os.path.exists(local_path):
|
|
||||||
if '.' in filename:
|
|
||||||
# Add "-i", e.g. change "foo.txt" to "foo-2.txt"
|
|
||||||
parts = filename.split('.')
|
|
||||||
name = parts[:-1]
|
|
||||||
ext = parts[-1]
|
|
||||||
|
|
||||||
i = 2
|
|
||||||
valid = False
|
|
||||||
while not valid:
|
|
||||||
new_filename = '{}-{}.{}'.format('.'.join(name), i, ext)
|
|
||||||
local_path = os.path.join(self.common.settings.get('downloads_dir'), new_filename)
|
|
||||||
if os.path.exists(local_path):
|
|
||||||
i += 1
|
|
||||||
else:
|
|
||||||
valid = True
|
|
||||||
else:
|
|
||||||
# If no extension, just add "-i", e.g. change "foo" to "foo-2"
|
|
||||||
i = 2
|
|
||||||
valid = False
|
|
||||||
while not valid:
|
|
||||||
new_filename = '{}-{}'.format(filename, i)
|
|
||||||
local_path = os.path.join(self.common.settings.get('downloads_dir'), new_filename)
|
|
||||||
if os.path.exists(local_path):
|
|
||||||
i += 1
|
|
||||||
else:
|
|
||||||
valid = True
|
|
||||||
|
|
||||||
basename = os.path.basename(local_path)
|
|
||||||
if f.filename != basename:
|
|
||||||
# Tell the GUI that the file has changed names
|
|
||||||
self.add_request(Web.REQUEST_UPLOAD_FILE_RENAMED, request.path, {
|
|
||||||
'id': request.upload_id,
|
|
||||||
'old_filename': f.filename,
|
|
||||||
'new_filename': basename
|
|
||||||
})
|
|
||||||
|
|
||||||
self.common.log('Web', 'receive_routes', '/upload, uploaded {}, saving to {}'.format(f.filename, local_path))
|
|
||||||
print(strings._('receive_mode_received_file').format(local_path))
|
|
||||||
f.save(local_path)
|
|
||||||
|
|
||||||
# Note that flash strings are on English, and not translated, on purpose,
|
|
||||||
# to avoid leaking the locale of the OnionShare user
|
|
||||||
if len(filenames) == 0:
|
|
||||||
flash('No files uploaded', 'info')
|
|
||||||
else:
|
|
||||||
for filename in filenames:
|
|
||||||
flash('Sent {}'.format(filename), 'info')
|
|
||||||
|
|
||||||
if self.common.settings.get('public_mode'):
|
|
||||||
return redirect('/')
|
|
||||||
else:
|
|
||||||
return redirect('/{}'.format(slug_candidate))
|
|
||||||
|
|
||||||
@self.app.route("/<slug_candidate>/upload", methods=['POST'])
|
@self.app.route("/<slug_candidate>/upload", methods=['POST'])
|
||||||
def upload(slug_candidate):
|
def upload(slug_candidate):
|
||||||
self.check_slug_candidate(slug_candidate)
|
self.check_slug_candidate(slug_candidate)
|
||||||
return upload_logic(slug_candidate)
|
if self.can_upload:
|
||||||
|
return upload_logic(slug_candidate)
|
||||||
|
else:
|
||||||
|
return self.error404()
|
||||||
|
|
||||||
@self.app.route("/upload", methods=['POST'])
|
@self.app.route("/upload", methods=['POST'])
|
||||||
def upload_public():
|
def upload_public():
|
||||||
if not self.common.settings.get('public_mode'):
|
if not self.common.settings.get('public_mode') or not self.can_upload:
|
||||||
return self.error404()
|
return self.error404()
|
||||||
return upload_logic()
|
return upload_logic()
|
||||||
|
|
||||||
@ -449,11 +458,14 @@ class Web(object):
|
|||||||
@self.app.route("/<slug_candidate>/close", methods=['POST'])
|
@self.app.route("/<slug_candidate>/close", methods=['POST'])
|
||||||
def close(slug_candidate):
|
def close(slug_candidate):
|
||||||
self.check_slug_candidate(slug_candidate)
|
self.check_slug_candidate(slug_candidate)
|
||||||
return close_logic(slug_candidate)
|
if self.can_upload:
|
||||||
|
return close_logic(slug_candidate)
|
||||||
|
else:
|
||||||
|
return self.error404()
|
||||||
|
|
||||||
@self.app.route("/close", methods=['POST'])
|
@self.app.route("/close", methods=['POST'])
|
||||||
def close_public():
|
def close_public():
|
||||||
if not self.common.settings.get('public_mode'):
|
if not self.common.settings.get('public_mode') or not self.can_upload:
|
||||||
return self.error404()
|
return self.error404()
|
||||||
return close_logic()
|
return close_logic()
|
||||||
|
|
||||||
@ -745,7 +757,7 @@ class ReceiveModeRequest(Request):
|
|||||||
|
|
||||||
# Is this a valid upload request?
|
# Is this a valid upload request?
|
||||||
self.upload_request = False
|
self.upload_request = False
|
||||||
if self.method == 'POST':
|
if self.method == 'POST' and self.web.can_upload:
|
||||||
if self.path == '/{}/upload'.format(self.web.slug):
|
if self.path == '/{}/upload'.format(self.web.slug):
|
||||||
self.upload_request = True
|
self.upload_request = True
|
||||||
else:
|
else:
|
||||||
|
@ -98,6 +98,17 @@ class ReceiveMode(Mode):
|
|||||||
The shutdown timer expired, should we stop the server? Returns a bool
|
The shutdown timer expired, should we stop the server? Returns a bool
|
||||||
"""
|
"""
|
||||||
# TODO: wait until the final upload is done before stoppign the server?
|
# TODO: wait until the final upload is done before stoppign the server?
|
||||||
|
# If there were no attempts to upload files, or all uploads are done, we can stop
|
||||||
|
if self.web.upload_count == 0 or self.web.done:
|
||||||
|
self.server_status.stop_server()
|
||||||
|
self.server_status_label.setText(strings._('close_on_timeout', True))
|
||||||
|
return True
|
||||||
|
# An upload is probably still running - hold off on stopping the share, but block new shares.
|
||||||
|
else:
|
||||||
|
self.server_status_label.setText(strings._('timeout_upload_still_running', True))
|
||||||
|
self.web.can_upload = False
|
||||||
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def start_server_custom(self):
|
def start_server_custom(self):
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
"close_on_timeout": "Stopped because timer expired",
|
"close_on_timeout": "Stopped because timer expired",
|
||||||
"closing_automatically": "Stopped because download finished",
|
"closing_automatically": "Stopped because download finished",
|
||||||
"timeout_download_still_running": "Waiting for download to complete",
|
"timeout_download_still_running": "Waiting for download to complete",
|
||||||
|
"timeout_upload_still_running": "Waiting for upload to complete",
|
||||||
"large_filesize": "Warning: Sending large files could take hours",
|
"large_filesize": "Warning: Sending large files could take hours",
|
||||||
"systray_menu_exit": "Quit",
|
"systray_menu_exit": "Quit",
|
||||||
"systray_download_started_title": "OnionShare Download Started",
|
"systray_download_started_title": "OnionShare Download Started",
|
||||||
|
Loading…
Reference in New Issue
Block a user