mirror of
https://github.com/onionshare/onionshare.git
synced 2024-10-01 01:35:40 -04:00
merge ux-update in, and fix conflict
This commit is contained in:
commit
b7df7f8dc9
@ -201,7 +201,9 @@ Section "install"
|
|||||||
File "${BINPATH}\share\html\index.html"
|
File "${BINPATH}\share\html\index.html"
|
||||||
|
|
||||||
SetOutPath "$INSTDIR\share\images"
|
SetOutPath "$INSTDIR\share\images"
|
||||||
|
File "${BINPATH}\share\images\favicon.ico"
|
||||||
File "${BINPATH}\share\images\file_delete.png"
|
File "${BINPATH}\share\images\file_delete.png"
|
||||||
|
File "${BINPATH}\share\images\info.png"
|
||||||
File "${BINPATH}\share\images\logo.png"
|
File "${BINPATH}\share\images\logo.png"
|
||||||
File "${BINPATH}\share\images\logo_transparent.png"
|
File "${BINPATH}\share\images\logo_transparent.png"
|
||||||
File "${BINPATH}\share\images\logo_grayscale.png"
|
File "${BINPATH}\share\images\logo_grayscale.png"
|
||||||
@ -209,7 +211,8 @@ Section "install"
|
|||||||
File "${BINPATH}\share\images\server_stopped.png"
|
File "${BINPATH}\share\images\server_stopped.png"
|
||||||
File "${BINPATH}\share\images\server_working.png"
|
File "${BINPATH}\share\images\server_working.png"
|
||||||
File "${BINPATH}\share\images\settings.png"
|
File "${BINPATH}\share\images\settings.png"
|
||||||
File "${BINPATH}\share\images\settings_inactive.png"
|
File "${BINPATH}\share\images\web_file.png"
|
||||||
|
File "${BINPATH}\share\images\web_folder.png"
|
||||||
|
|
||||||
SetOutPath "$INSTDIR\share\locale"
|
SetOutPath "$INSTDIR\share\locale"
|
||||||
File "${BINPATH}\share\locale\cs.json"
|
File "${BINPATH}\share\locale\cs.json"
|
||||||
@ -380,7 +383,9 @@ FunctionEnd
|
|||||||
Delete "$INSTDIR\share\html\404.html"
|
Delete "$INSTDIR\share\html\404.html"
|
||||||
Delete "$INSTDIR\share\html\denied.html"
|
Delete "$INSTDIR\share\html\denied.html"
|
||||||
Delete "$INSTDIR\share\html\index.html"
|
Delete "$INSTDIR\share\html\index.html"
|
||||||
|
Delete "$INSTDIR\share\images\favicon.ico"
|
||||||
Delete "$INSTDIR\share\images\file_delete.png"
|
Delete "$INSTDIR\share\images\file_delete.png"
|
||||||
|
Delete "$INSTDIR\share\images\info.png"
|
||||||
Delete "$INSTDIR\share\images\logo.png"
|
Delete "$INSTDIR\share\images\logo.png"
|
||||||
Delete "$INSTDIR\share\images\logo_transparent.png"
|
Delete "$INSTDIR\share\images\logo_transparent.png"
|
||||||
Delete "$INSTDIR\share\images\logo_grayscale.png"
|
Delete "$INSTDIR\share\images\logo_grayscale.png"
|
||||||
@ -388,7 +393,8 @@ FunctionEnd
|
|||||||
Delete "$INSTDIR\share\images\server_stopped.png"
|
Delete "$INSTDIR\share\images\server_stopped.png"
|
||||||
Delete "$INSTDIR\share\images\server_working.png"
|
Delete "$INSTDIR\share\images\server_working.png"
|
||||||
Delete "$INSTDIR\share\images\settings.png"
|
Delete "$INSTDIR\share\images\settings.png"
|
||||||
Delete "$INSTDIR\share\images\settings_inactive.png"
|
Delete "$INSTDIR\share\images\web_file.png"
|
||||||
|
Delete "$INSTDIR\share\images\web_folder.png"
|
||||||
Delete "$INSTDIR\share\license.txt"
|
Delete "$INSTDIR\share\license.txt"
|
||||||
Delete "$INSTDIR\share\locale\cs.json"
|
Delete "$INSTDIR\share\locale\cs.json"
|
||||||
Delete "$INSTDIR\share\locale\de.json"
|
Delete "$INSTDIR\share\locale\de.json"
|
||||||
|
@ -26,6 +26,7 @@ import queue
|
|||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import base64
|
||||||
from distutils.version import LooseVersion as Version
|
from distutils.version import LooseVersion as Version
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
@ -125,6 +126,12 @@ def add_request(request_type, path, data=None):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
# Load and base64 encode images to pass into templates
|
||||||
|
favicon_b64 = base64.b64encode(open(common.get_resource_path('images/favicon.ico'), 'rb').read()).decode()
|
||||||
|
logo_b64 = base64.b64encode(open(common.get_resource_path('images/logo.png'), 'rb').read()).decode()
|
||||||
|
folder_b64 = base64.b64encode(open(common.get_resource_path('images/web_folder.png'), 'rb').read()).decode()
|
||||||
|
file_b64 = base64.b64encode(open(common.get_resource_path('images/web_file.png'), 'rb').read()).decode()
|
||||||
|
|
||||||
slug = None
|
slug = None
|
||||||
|
|
||||||
|
|
||||||
@ -206,7 +213,10 @@ def index(slug_candidate):
|
|||||||
global stay_open, download_in_progress
|
global stay_open, download_in_progress
|
||||||
deny_download = not stay_open and download_in_progress
|
deny_download = not stay_open and download_in_progress
|
||||||
if deny_download:
|
if deny_download:
|
||||||
r = make_response(render_template_string(open(common.get_resource_path('html/denied.html')).read()))
|
r = make_response(render_template_string(
|
||||||
|
open(common.get_resource_path('html/denied.html')).read(),
|
||||||
|
favicon_b64=favicon_b64
|
||||||
|
))
|
||||||
for header, value in security_headers:
|
for header, value in security_headers:
|
||||||
r.headers.set(header, value)
|
r.headers.set(header, value)
|
||||||
return r
|
return r
|
||||||
@ -215,6 +225,10 @@ def index(slug_candidate):
|
|||||||
|
|
||||||
r = make_response(render_template_string(
|
r = make_response(render_template_string(
|
||||||
open(common.get_resource_path('html/index.html')).read(),
|
open(common.get_resource_path('html/index.html')).read(),
|
||||||
|
favicon_b64=favicon_b64,
|
||||||
|
logo_b64=logo_b64,
|
||||||
|
folder_b64=folder_b64,
|
||||||
|
file_b64=file_b64,
|
||||||
slug=slug,
|
slug=slug,
|
||||||
file_info=file_info,
|
file_info=file_info,
|
||||||
filename=os.path.basename(zip_filename),
|
filename=os.path.basename(zip_filename),
|
||||||
@ -243,7 +257,10 @@ def download(slug_candidate):
|
|||||||
global stay_open, download_in_progress, done
|
global stay_open, download_in_progress, done
|
||||||
deny_download = not stay_open and download_in_progress
|
deny_download = not stay_open and download_in_progress
|
||||||
if deny_download:
|
if deny_download:
|
||||||
r = make_response(render_template_string(open(common.get_resource_path('html/denied.html')).read()))
|
r = make_response(render_template_string(
|
||||||
|
open(common.get_resource_path('html/denied.html')).read(),
|
||||||
|
favicon_b64=favicon_b64
|
||||||
|
))
|
||||||
for header,value in security_headers:
|
for header,value in security_headers:
|
||||||
r.headers.set(header, value)
|
r.headers.set(header, value)
|
||||||
return r
|
return r
|
||||||
@ -355,7 +372,10 @@ def page_not_found(e):
|
|||||||
force_shutdown()
|
force_shutdown()
|
||||||
print(strings._('error_rate_limit'))
|
print(strings._('error_rate_limit'))
|
||||||
|
|
||||||
r = make_response(render_template_string(open(common.get_resource_path('html/404.html')).read()), 404)
|
r = make_response(render_template_string(
|
||||||
|
open(common.get_resource_path('html/404.html')).read(),
|
||||||
|
favicon_b64=favicon_b64
|
||||||
|
), 404)
|
||||||
for header, value in security_headers:
|
for header, value in security_headers:
|
||||||
r.headers.set(header, value)
|
r.headers.set(header, value)
|
||||||
return r
|
return r
|
||||||
|
@ -145,7 +145,8 @@ class FileList(QtWidgets.QListWidget):
|
|||||||
count = len(event.mimeData().urls())
|
count = len(event.mimeData().urls())
|
||||||
self.drop_count.setText('+{}'.format(count))
|
self.drop_count.setText('+{}'.format(count))
|
||||||
|
|
||||||
self.drop_count.setGeometry(self.width() - 60, self.height() - 40, 50, 30)
|
size_hint = self.drop_count.sizeHint()
|
||||||
|
self.drop_count.setGeometry(self.width() - size_hint.width() - 10, self.height() - size_hint.height() - 10, size_hint.width(), size_hint.height())
|
||||||
self.drop_count.show()
|
self.drop_count.show()
|
||||||
event.accept()
|
event.accept()
|
||||||
else:
|
else:
|
||||||
@ -207,15 +208,24 @@ class FileList(QtWidgets.QListWidget):
|
|||||||
icon = ip.icon(fileinfo)
|
icon = ip.icon(fileinfo)
|
||||||
|
|
||||||
if os.path.isfile(filename):
|
if os.path.isfile(filename):
|
||||||
size = common.human_readable_filesize(fileinfo.size())
|
size_bytes = fileinfo.size()
|
||||||
|
size_readable = common.human_readable_filesize(size_bytes)
|
||||||
else:
|
else:
|
||||||
size = common.human_readable_filesize(common.dir_size(filename))
|
size_bytes = common.dir_size(filename)
|
||||||
item_name = '{0:s} ({1:s})'.format(basename, size)
|
size_readable = common.human_readable_filesize(size_bytes)
|
||||||
|
|
||||||
# Create a new item
|
# Create a new item
|
||||||
item = QtWidgets.QListWidgetItem(item_name)
|
item = QtWidgets.QListWidgetItem()
|
||||||
item.setToolTip(size)
|
|
||||||
item.setIcon(icon)
|
item.setIcon(icon)
|
||||||
|
item.size_bytes = size_bytes
|
||||||
|
|
||||||
|
# Item's name and size labels
|
||||||
|
item_name = QtWidgets.QLabel(basename)
|
||||||
|
item_name.setWordWrap(False)
|
||||||
|
item_name.setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
item_name.setStyleSheet('QLabel { color: #000000; font-size: 13px; }')
|
||||||
|
item_size = QtWidgets.QLabel(size_readable)
|
||||||
|
item_size.setStyleSheet('QLabel { color: #666666; font-size: 11px; }')
|
||||||
|
|
||||||
# Item's delete button
|
# Item's delete button
|
||||||
def delete_item():
|
def delete_item():
|
||||||
@ -229,16 +239,22 @@ class FileList(QtWidgets.QListWidget):
|
|||||||
item.item_button.setFlat(True)
|
item.item_button.setFlat(True)
|
||||||
item.item_button.setIcon( QtGui.QIcon(common.get_resource_path('images/file_delete.png')) )
|
item.item_button.setIcon( QtGui.QIcon(common.get_resource_path('images/file_delete.png')) )
|
||||||
item.item_button.clicked.connect(delete_item)
|
item.item_button.clicked.connect(delete_item)
|
||||||
|
item.item_button.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
|
||||||
# Create an item widget to display on the item
|
# Create the item's widget and layouts
|
||||||
item_widget_layout = QtWidgets.QHBoxLayout()
|
item_vlayout = QtWidgets.QVBoxLayout()
|
||||||
item_widget_layout.addStretch()
|
item_vlayout.addWidget(item_name)
|
||||||
item_widget_layout.addWidget(item.item_button)
|
item_vlayout.addWidget(item_size)
|
||||||
item_widget = QtWidgets.QWidget()
|
item_hlayout = QtWidgets.QHBoxLayout()
|
||||||
item_widget.setLayout(item_widget_layout)
|
item_hlayout.addLayout(item_vlayout)
|
||||||
|
item_hlayout.addWidget(item.item_button)
|
||||||
|
widget = QtWidgets.QWidget()
|
||||||
|
widget.setLayout(item_hlayout)
|
||||||
|
|
||||||
|
item.setSizeHint(widget.sizeHint())
|
||||||
|
|
||||||
self.addItem(item)
|
self.addItem(item)
|
||||||
self.setItemWidget(item, item_widget)
|
self.setItemWidget(item, widget)
|
||||||
|
|
||||||
self.files_updated.emit()
|
self.files_updated.emit()
|
||||||
|
|
||||||
@ -252,12 +268,17 @@ class FileSelection(QtWidgets.QVBoxLayout):
|
|||||||
super(FileSelection, self).__init__()
|
super(FileSelection, self).__init__()
|
||||||
self.server_on = False
|
self.server_on = False
|
||||||
|
|
||||||
# file list
|
# Info label
|
||||||
|
self.info_label = QtWidgets.QLabel()
|
||||||
|
self.info_label.setStyleSheet('QLabel { font-size: 12px; color: #666666; }')
|
||||||
|
|
||||||
|
# File list
|
||||||
self.file_list = FileList()
|
self.file_list = FileList()
|
||||||
self.file_list.currentItemChanged.connect(self.update)
|
self.file_list.currentItemChanged.connect(self.update)
|
||||||
self.file_list.files_dropped.connect(self.update)
|
self.file_list.files_dropped.connect(self.update)
|
||||||
|
self.file_list.files_updated.connect(self.update)
|
||||||
|
|
||||||
# buttons
|
# Buttons
|
||||||
self.add_button = QtWidgets.QPushButton(strings._('gui_add', True))
|
self.add_button = QtWidgets.QPushButton(strings._('gui_add', True))
|
||||||
self.add_button.clicked.connect(self.add)
|
self.add_button.clicked.connect(self.add)
|
||||||
self.delete_button = QtWidgets.QPushButton(strings._('gui_delete', True))
|
self.delete_button = QtWidgets.QPushButton(strings._('gui_delete', True))
|
||||||
@ -267,7 +288,8 @@ class FileSelection(QtWidgets.QVBoxLayout):
|
|||||||
button_layout.addWidget(self.add_button)
|
button_layout.addWidget(self.add_button)
|
||||||
button_layout.addWidget(self.delete_button)
|
button_layout.addWidget(self.delete_button)
|
||||||
|
|
||||||
# add the widgets
|
# Add the widgets
|
||||||
|
self.addWidget(self.info_label)
|
||||||
self.addWidget(self.file_list)
|
self.addWidget(self.file_list)
|
||||||
self.addLayout(button_layout)
|
self.addLayout(button_layout)
|
||||||
|
|
||||||
@ -277,6 +299,23 @@ class FileSelection(QtWidgets.QVBoxLayout):
|
|||||||
"""
|
"""
|
||||||
Update the GUI elements based on the current state.
|
Update the GUI elements based on the current state.
|
||||||
"""
|
"""
|
||||||
|
# Update the info label
|
||||||
|
file_count = self.file_list.count()
|
||||||
|
if file_count == 0:
|
||||||
|
self.info_label.hide()
|
||||||
|
else:
|
||||||
|
total_size_bytes = 0
|
||||||
|
for index in range(self.file_list.count()):
|
||||||
|
item = self.file_list.item(index)
|
||||||
|
total_size_bytes += item.size_bytes
|
||||||
|
total_size_readable = common.human_readable_filesize(total_size_bytes)
|
||||||
|
|
||||||
|
if file_count > 1:
|
||||||
|
self.info_label.setText(strings._('gui_file_info', True).format(file_count, total_size_readable))
|
||||||
|
else:
|
||||||
|
self.info_label.setText(strings._('gui_file_info_single', True).format(file_count, total_size_readable))
|
||||||
|
self.info_label.show()
|
||||||
|
|
||||||
# All buttons should be hidden if the server is on
|
# All buttons should be hidden if the server is on
|
||||||
if self.server_on:
|
if self.server_on:
|
||||||
self.add_button.hide()
|
self.add_button.hide()
|
||||||
|
@ -56,7 +56,7 @@ class OnionShareGui(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
self.setWindowTitle('OnionShare')
|
self.setWindowTitle('OnionShare')
|
||||||
self.setWindowIcon(QtGui.QIcon(common.get_resource_path('images/logo.png')))
|
self.setWindowIcon(QtGui.QIcon(common.get_resource_path('images/logo.png')))
|
||||||
self.setMinimumWidth(350)
|
self.setMinimumWidth(430)
|
||||||
|
|
||||||
# Load settings
|
# Load settings
|
||||||
self.config = config
|
self.config = config
|
||||||
@ -91,9 +91,11 @@ class OnionShareGui(QtWidgets.QMainWindow):
|
|||||||
self.starting_server_step2.connect(self.start_server_step2)
|
self.starting_server_step2.connect(self.start_server_step2)
|
||||||
self.starting_server_step3.connect(self.start_server_step3)
|
self.starting_server_step3.connect(self.start_server_step3)
|
||||||
self.starting_server_error.connect(self.start_server_error)
|
self.starting_server_error.connect(self.start_server_error)
|
||||||
|
self.server_status.button_clicked.connect(self.clear_message)
|
||||||
|
|
||||||
# Filesize warning
|
# Filesize warning
|
||||||
self.filesize_warning = QtWidgets.QLabel()
|
self.filesize_warning = QtWidgets.QLabel()
|
||||||
|
self.filesize_warning.setWordWrap(True)
|
||||||
self.filesize_warning.setStyleSheet('padding: 10px 0; font-weight: bold; color: #333333;')
|
self.filesize_warning.setStyleSheet('padding: 10px 0; font-weight: bold; color: #333333;')
|
||||||
self.filesize_warning.hide()
|
self.filesize_warning.hide()
|
||||||
|
|
||||||
@ -133,24 +135,32 @@ class OnionShareGui(QtWidgets.QMainWindow):
|
|||||||
# Status bar
|
# Status bar
|
||||||
self.status_bar = QtWidgets.QStatusBar()
|
self.status_bar = QtWidgets.QStatusBar()
|
||||||
self.status_bar.setSizeGripEnabled(False)
|
self.status_bar.setSizeGripEnabled(False)
|
||||||
self.status_bar.setStyleSheet("QStatusBar::item { border: 0px; }")
|
statusBar_cssStyleData ="""
|
||||||
|
QStatusBar {
|
||||||
|
font-style: italic;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStatusBar::item {
|
||||||
|
border: 0px;
|
||||||
|
}"""
|
||||||
|
|
||||||
|
self.status_bar.setStyleSheet(statusBar_cssStyleData)
|
||||||
self.status_bar.addPermanentWidget(self.server_status_indicator)
|
self.status_bar.addPermanentWidget(self.server_status_indicator)
|
||||||
self.status_bar.addPermanentWidget(self.settings_button)
|
self.status_bar.addPermanentWidget(self.settings_button)
|
||||||
self.setStatusBar(self.status_bar)
|
self.setStatusBar(self.status_bar)
|
||||||
|
|
||||||
# Status bar, zip progress bar
|
# Status bar, zip progress bar
|
||||||
self._zip_progress_bar = None
|
self._zip_progress_bar = None
|
||||||
|
# Status bar, sharing messages
|
||||||
# Persistent URL notification
|
self.server_share_status_label = QtWidgets.QLabel('')
|
||||||
self.persistent_url_label = QtWidgets.QLabel(strings._('persistent_url_in_use', True))
|
self.server_share_status_label.setStyleSheet('QLabel { font-style: italic; color: #666666; padding: 2px; }')
|
||||||
self.persistent_url_label.setStyleSheet('font-weight: bold; color: #333333;')
|
self.status_bar.insertWidget(0, self.server_share_status_label)
|
||||||
self.persistent_url_label.hide()
|
|
||||||
|
|
||||||
# Primary action layout
|
# Primary action layout
|
||||||
primary_action_layout = QtWidgets.QVBoxLayout()
|
primary_action_layout = QtWidgets.QVBoxLayout()
|
||||||
primary_action_layout.addWidget(self.server_status)
|
primary_action_layout.addWidget(self.server_status)
|
||||||
primary_action_layout.addWidget(self.filesize_warning)
|
primary_action_layout.addWidget(self.filesize_warning)
|
||||||
primary_action_layout.addWidget(self.persistent_url_label)
|
|
||||||
primary_action_layout.addWidget(self.downloads_container)
|
primary_action_layout.addWidget(self.downloads_container)
|
||||||
self.primary_action = QtWidgets.QWidget()
|
self.primary_action = QtWidgets.QWidget()
|
||||||
self.primary_action.setLayout(primary_action_layout)
|
self.primary_action.setLayout(primary_action_layout)
|
||||||
@ -189,16 +199,15 @@ class OnionShareGui(QtWidgets.QMainWindow):
|
|||||||
self.check_for_updates()
|
self.check_for_updates()
|
||||||
|
|
||||||
def update_primary_action(self):
|
def update_primary_action(self):
|
||||||
common.log('OnionShareGui', 'update_primary_action')
|
|
||||||
# Resize window
|
|
||||||
self.adjustSize()
|
|
||||||
|
|
||||||
# Show or hide primary action layout
|
# Show or hide primary action layout
|
||||||
if self.file_selection.file_list.count() > 0:
|
if self.file_selection.file_list.count() > 0:
|
||||||
self.primary_action.show()
|
self.primary_action.show()
|
||||||
else:
|
else:
|
||||||
self.primary_action.hide()
|
self.primary_action.hide()
|
||||||
|
|
||||||
|
# Resize window
|
||||||
|
self.adjustSize()
|
||||||
|
|
||||||
def update_server_status_indicator(self):
|
def update_server_status_indicator(self):
|
||||||
common.log('OnionShareGui', 'update_server_status_indicator')
|
common.log('OnionShareGui', 'update_server_status_indicator')
|
||||||
|
|
||||||
@ -316,6 +325,7 @@ class OnionShareGui(QtWidgets.QMainWindow):
|
|||||||
self.downloads_container.hide()
|
self.downloads_container.hide()
|
||||||
self.downloads.reset_downloads()
|
self.downloads.reset_downloads()
|
||||||
self.status_bar.clearMessage()
|
self.status_bar.clearMessage()
|
||||||
|
self.server_share_status_label.setText('')
|
||||||
|
|
||||||
# Reset web counters
|
# Reset web counters
|
||||||
web.download_count = 0
|
web.download_count = 0
|
||||||
@ -376,7 +386,6 @@ class OnionShareGui(QtWidgets.QMainWindow):
|
|||||||
self.starting_server_error.emit(e.strerror)
|
self.starting_server_error.emit(e.strerror)
|
||||||
return
|
return
|
||||||
|
|
||||||
#self.status_bar.showMessage(strings._('gui_starting_server2', True))
|
|
||||||
t = threading.Thread(target=finish_starting_server, kwargs={'self': self})
|
t = threading.Thread(target=finish_starting_server, kwargs={'self': self})
|
||||||
t.daemon = True
|
t.daemon = True
|
||||||
t.start()
|
t.start()
|
||||||
@ -398,7 +407,7 @@ class OnionShareGui(QtWidgets.QMainWindow):
|
|||||||
self.filesize_warning.setText(strings._("large_filesize", True))
|
self.filesize_warning.setText(strings._("large_filesize", True))
|
||||||
self.filesize_warning.show()
|
self.filesize_warning.show()
|
||||||
|
|
||||||
if self.server_status.timer_enabled:
|
if self.settings.get('shutdown_timeout'):
|
||||||
# Convert the date value to seconds between now and then
|
# Convert the date value to seconds between now and then
|
||||||
now = QtCore.QDateTime.currentDateTime()
|
now = QtCore.QDateTime.currentDateTime()
|
||||||
self.timeout = now.secsTo(self.server_status.timeout)
|
self.timeout = now.secsTo(self.server_status.timeout)
|
||||||
@ -411,9 +420,6 @@ class OnionShareGui(QtWidgets.QMainWindow):
|
|||||||
self.stop_server()
|
self.stop_server()
|
||||||
self.start_server_error(strings._('gui_server_started_after_timeout'))
|
self.start_server_error(strings._('gui_server_started_after_timeout'))
|
||||||
|
|
||||||
if self.settings.get('save_private_key'):
|
|
||||||
self.persistent_url_label.show()
|
|
||||||
|
|
||||||
def start_server_error(self, error):
|
def start_server_error(self, error):
|
||||||
"""
|
"""
|
||||||
If there's an error when trying to start the onion service
|
If there's an error when trying to start the onion service
|
||||||
@ -453,10 +459,10 @@ class OnionShareGui(QtWidgets.QMainWindow):
|
|||||||
# Remove ephemeral service, but don't disconnect from Tor
|
# Remove ephemeral service, but don't disconnect from Tor
|
||||||
self.onion.cleanup(stop_tor=False)
|
self.onion.cleanup(stop_tor=False)
|
||||||
self.filesize_warning.hide()
|
self.filesize_warning.hide()
|
||||||
self.persistent_url_label.hide()
|
self.file_selection.file_list.adjustSize()
|
||||||
self.stop_server_finished.emit()
|
|
||||||
|
|
||||||
self.set_server_active(False)
|
self.set_server_active(False)
|
||||||
|
self.stop_server_finished.emit()
|
||||||
|
|
||||||
def check_for_updates(self):
|
def check_for_updates(self):
|
||||||
"""
|
"""
|
||||||
@ -539,7 +545,8 @@ class OnionShareGui(QtWidgets.QMainWindow):
|
|||||||
# close on finish?
|
# close on finish?
|
||||||
if not web.get_stay_open():
|
if not web.get_stay_open():
|
||||||
self.server_status.stop_server()
|
self.server_status.stop_server()
|
||||||
self.status_bar.showMessage(strings._('closing_automatically', True))
|
self.status_bar.clearMessage()
|
||||||
|
self.server_share_status_label.setText(strings._('closing_automatically', True))
|
||||||
else:
|
else:
|
||||||
if self.server_status.status == self.server_status.STATUS_STOPPED:
|
if self.server_status.status == self.server_status.STATUS_STOPPED:
|
||||||
self.downloads.cancel_download(event["data"]["id"])
|
self.downloads.cancel_download(event["data"]["id"])
|
||||||
@ -554,30 +561,34 @@ class OnionShareGui(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
# If the auto-shutdown timer has stopped, stop the server
|
# If the auto-shutdown timer has stopped, stop the server
|
||||||
if self.server_status.status == self.server_status.STATUS_STARTED:
|
if self.server_status.status == self.server_status.STATUS_STARTED:
|
||||||
if self.app.shutdown_timer and self.server_status.timer_enabled:
|
if self.app.shutdown_timer and self.settings.get('shutdown_timeout'):
|
||||||
if self.timeout > 0:
|
if self.timeout > 0:
|
||||||
if not self.app.shutdown_timer.is_alive():
|
if not self.app.shutdown_timer.is_alive():
|
||||||
# If there were no attempts to download the share, or all downloads are done, we can stop
|
# If there were no attempts to download the share, or all downloads are done, we can stop
|
||||||
if web.download_count == 0 or web.done:
|
if web.download_count == 0 or web.done:
|
||||||
self.server_status.stop_server()
|
self.server_status.stop_server()
|
||||||
self.status_bar.showMessage(strings._('close_on_timeout', True))
|
self.status_bar.clearMessage()
|
||||||
|
self.server_share_status_label.setText(strings._('close_on_timeout', True))
|
||||||
# A download is probably still running - hold off on stopping the share
|
# A download is probably still running - hold off on stopping the share
|
||||||
else:
|
else:
|
||||||
self.status_bar.showMessage(strings._('timeout_download_still_running', True))
|
self.status_bar.clearMessage()
|
||||||
|
self.server_share_status_label.setText(strings._('timeout_download_still_running', True))
|
||||||
|
|
||||||
def copy_url(self):
|
def copy_url(self):
|
||||||
"""
|
"""
|
||||||
When the URL gets copied to the clipboard, display this in the status bar.
|
When the URL gets copied to the clipboard, display this in the status bar.
|
||||||
"""
|
"""
|
||||||
common.log('OnionShareGui', 'copy_url')
|
common.log('OnionShareGui', 'copy_url')
|
||||||
self.status_bar.showMessage(strings._('gui_copied_url', True), 2000)
|
if self.systemTray.supportsMessages() and self.settings.get('systray_notifications'):
|
||||||
|
self.systemTray.showMessage(strings._('gui_copied_url_title', True), strings._('gui_copied_url', True))
|
||||||
|
|
||||||
def copy_hidservauth(self):
|
def copy_hidservauth(self):
|
||||||
"""
|
"""
|
||||||
When the stealth onion service HidServAuth gets copied to the clipboard, display this in the status bar.
|
When the stealth onion service HidServAuth gets copied to the clipboard, display this in the status bar.
|
||||||
"""
|
"""
|
||||||
common.log('OnionShareGui', 'copy_hidservauth')
|
common.log('OnionShareGui', 'copy_hidservauth')
|
||||||
self.status_bar.showMessage(strings._('gui_copied_hidservauth', True), 2000)
|
if self.systemTray.supportsMessages() and self.settings.get('systray_notifications'):
|
||||||
|
self.systemTray.showMessage(strings._('gui_copied_hidservauth_title', True), strings._('gui_copied_hidservauth', True))
|
||||||
|
|
||||||
def clear_message(self):
|
def clear_message(self):
|
||||||
"""
|
"""
|
||||||
@ -589,11 +600,10 @@ class OnionShareGui(QtWidgets.QMainWindow):
|
|||||||
"""
|
"""
|
||||||
Disable the Settings button while an OnionShare server is active.
|
Disable the Settings button while an OnionShare server is active.
|
||||||
"""
|
"""
|
||||||
self.settings_button.setEnabled(not active)
|
|
||||||
if active:
|
if active:
|
||||||
self.settings_button.setIcon( QtGui.QIcon(common.get_resource_path('images/settings_inactive.png')) )
|
self.settings_button.hide()
|
||||||
else:
|
else:
|
||||||
self.settings_button.setIcon( QtGui.QIcon(common.get_resource_path('images/settings.png')) )
|
self.settings_button.show()
|
||||||
|
|
||||||
# Disable settings menu action when server is active
|
# Disable settings menu action when server is active
|
||||||
self.settingsAction.setEnabled(not active)
|
self.settingsAction.setEnabled(not active)
|
||||||
|
@ -30,6 +30,7 @@ class ServerStatus(QtWidgets.QWidget):
|
|||||||
server_started = QtCore.pyqtSignal()
|
server_started = QtCore.pyqtSignal()
|
||||||
server_stopped = QtCore.pyqtSignal()
|
server_stopped = QtCore.pyqtSignal()
|
||||||
server_canceled = QtCore.pyqtSignal()
|
server_canceled = QtCore.pyqtSignal()
|
||||||
|
button_clicked = QtCore.pyqtSignal()
|
||||||
url_copied = QtCore.pyqtSignal()
|
url_copied = QtCore.pyqtSignal()
|
||||||
hidservauth_copied = QtCore.pyqtSignal()
|
hidservauth_copied = QtCore.pyqtSignal()
|
||||||
|
|
||||||
@ -48,17 +49,15 @@ class ServerStatus(QtWidgets.QWidget):
|
|||||||
|
|
||||||
self.settings = settings
|
self.settings = settings
|
||||||
|
|
||||||
# Helper boolean as this is used in a few places
|
|
||||||
self.timer_enabled = False
|
|
||||||
|
|
||||||
# Shutdown timeout layout
|
# Shutdown timeout layout
|
||||||
self.shutdown_timeout_label = QtWidgets.QLabel(strings._('gui_settings_shutdown_timeout', True))
|
self.shutdown_timeout_label = QtWidgets.QLabel(strings._('gui_settings_shutdown_timeout', True))
|
||||||
self.shutdown_timeout = QtWidgets.QDateTimeEdit()
|
self.shutdown_timeout = QtWidgets.QDateTimeEdit()
|
||||||
# Set proposed timeout to be 5 minutes into the future
|
# Set proposed timeout to be 5 minutes into the future
|
||||||
|
self.shutdown_timeout.setDisplayFormat("hh:mm A MMM d, yy")
|
||||||
self.shutdown_timeout.setDateTime(QtCore.QDateTime.currentDateTime().addSecs(300))
|
self.shutdown_timeout.setDateTime(QtCore.QDateTime.currentDateTime().addSecs(300))
|
||||||
# Onion services can take a little while to start, so reduce the risk of it expiring too soon by setting the minimum to 2 min from now
|
# Onion services can take a little while to start, so reduce the risk of it expiring too soon by setting the minimum to 2 min from now
|
||||||
self.shutdown_timeout.setMinimumDateTime(QtCore.QDateTime.currentDateTime().addSecs(120))
|
self.shutdown_timeout.setMinimumDateTime(QtCore.QDateTime.currentDateTime().addSecs(120))
|
||||||
self.shutdown_timeout.setCurrentSectionIndex(4)
|
self.shutdown_timeout.setCurrentSection(QtWidgets.QDateTimeEdit.MinuteSection)
|
||||||
shutdown_timeout_layout = QtWidgets.QHBoxLayout()
|
shutdown_timeout_layout = QtWidgets.QHBoxLayout()
|
||||||
shutdown_timeout_layout.addWidget(self.shutdown_timeout_label)
|
shutdown_timeout_layout.addWidget(self.shutdown_timeout_label)
|
||||||
shutdown_timeout_layout.addWidget(self.shutdown_timeout)
|
shutdown_timeout_layout.addWidget(self.shutdown_timeout)
|
||||||
@ -84,6 +83,7 @@ class ServerStatus(QtWidgets.QWidget):
|
|||||||
self.url.setFont(url_font)
|
self.url.setFont(url_font)
|
||||||
self.url.setWordWrap(True)
|
self.url.setWordWrap(True)
|
||||||
self.url.setMinimumHeight(60)
|
self.url.setMinimumHeight(60)
|
||||||
|
self.url.setMinimumSize(self.url.sizeHint())
|
||||||
self.url.setStyleSheet('QLabel { background-color: #ffffff; color: #000000; padding: 10px; border: 1px solid #666666; }')
|
self.url.setStyleSheet('QLabel { background-color: #ffffff; color: #000000; padding: 10px; border: 1px solid #666666; }')
|
||||||
|
|
||||||
url_buttons_style = 'QPushButton { color: #3f7fcf; }'
|
url_buttons_style = 'QPushButton { color: #3f7fcf; }'
|
||||||
@ -115,22 +115,6 @@ class ServerStatus(QtWidgets.QWidget):
|
|||||||
|
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
def shutdown_timeout_toggled(self, checked):
|
|
||||||
"""
|
|
||||||
Shutdown timer option was toggled. If checked, show the timer settings.
|
|
||||||
"""
|
|
||||||
if checked:
|
|
||||||
self.timer_enabled = True
|
|
||||||
# Hide the checkbox, show the options
|
|
||||||
self.shutdown_timeout_label.show()
|
|
||||||
# Reset the default timer to 5 minutes into the future after toggling the option on
|
|
||||||
self.shutdown_timeout.setDateTime(QtCore.QDateTime.currentDateTime().addSecs(300))
|
|
||||||
self.shutdown_timeout.show()
|
|
||||||
else:
|
|
||||||
self.timer_enabled = False
|
|
||||||
self.shutdown_timeout_label.hide()
|
|
||||||
self.shutdown_timeout.hide()
|
|
||||||
|
|
||||||
def shutdown_timeout_reset(self):
|
def shutdown_timeout_reset(self):
|
||||||
"""
|
"""
|
||||||
Reset the timeout in the UI after stopping a share
|
Reset the timeout in the UI after stopping a share
|
||||||
@ -146,10 +130,19 @@ class ServerStatus(QtWidgets.QWidget):
|
|||||||
if self.status == self.STATUS_STARTED:
|
if self.status == self.STATUS_STARTED:
|
||||||
self.url_description.show()
|
self.url_description.show()
|
||||||
|
|
||||||
if self.settings.get('close_after_first_download'):
|
info_image = common.get_resource_path('images/info.png')
|
||||||
self.url_label.setText(strings._('gui_url_label_one_time', True))
|
self.url_label.setText(strings._('gui_url_label', True).format(info_image))
|
||||||
|
# Show a Tool Tip explaining the lifecycle of this URL
|
||||||
|
if self.settings.get('save_private_key'):
|
||||||
|
if self.settings.get('close_after_first_download'):
|
||||||
|
self.url_label.setToolTip(strings._('gui_url_label_onetime_and_persistent', True))
|
||||||
|
else:
|
||||||
|
self.url_label.setToolTip(strings._('gui_url_label_persistent', True))
|
||||||
else:
|
else:
|
||||||
self.url_label.setText(strings._('gui_url_label', True))
|
if self.settings.get('close_after_first_download'):
|
||||||
|
self.url_label.setToolTip(strings._('gui_url_label_onetime', True))
|
||||||
|
else:
|
||||||
|
self.url_label.setToolTip(strings._('gui_url_label_stay_open', True))
|
||||||
self.url_label.show()
|
self.url_label.show()
|
||||||
|
|
||||||
self.url.setText('http://{0:s}/{1:s}'.format(self.app.onion_host, self.web.slug))
|
self.url.setText('http://{0:s}/{1:s}'.format(self.app.onion_host, self.web.slug))
|
||||||
@ -213,7 +206,7 @@ class ServerStatus(QtWidgets.QWidget):
|
|||||||
Toggle starting or stopping the server.
|
Toggle starting or stopping the server.
|
||||||
"""
|
"""
|
||||||
if self.status == self.STATUS_STOPPED:
|
if self.status == self.STATUS_STOPPED:
|
||||||
if self.timer_enabled:
|
if self.settings.get('shutdown_timeout'):
|
||||||
# Get the timeout chosen, stripped of its seconds. This prevents confusion if the share stops at (say) 37 seconds past the minute chosen
|
# Get the timeout chosen, stripped of its seconds. This prevents confusion if the share stops at (say) 37 seconds past the minute chosen
|
||||||
self.timeout = self.shutdown_timeout.dateTime().toPyDateTime().replace(second=0, microsecond=0)
|
self.timeout = self.shutdown_timeout.dateTime().toPyDateTime().replace(second=0, microsecond=0)
|
||||||
# If the timeout has actually passed already before the user hit Start, refuse to start the server.
|
# If the timeout has actually passed already before the user hit Start, refuse to start the server.
|
||||||
@ -227,6 +220,7 @@ class ServerStatus(QtWidgets.QWidget):
|
|||||||
self.stop_server()
|
self.stop_server()
|
||||||
elif self.status == self.STATUS_WORKING:
|
elif self.status == self.STATUS_WORKING:
|
||||||
self.cancel_server()
|
self.cancel_server()
|
||||||
|
self.button_clicked.emit()
|
||||||
|
|
||||||
def start_server(self):
|
def start_server(self):
|
||||||
"""
|
"""
|
||||||
|
@ -86,12 +86,14 @@ class SettingsDialog(QtWidgets.QDialog):
|
|||||||
stealth_details.setWordWrap(True)
|
stealth_details.setWordWrap(True)
|
||||||
stealth_details.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)
|
stealth_details.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)
|
||||||
stealth_details.setOpenExternalLinks(True)
|
stealth_details.setOpenExternalLinks(True)
|
||||||
|
stealth_details.setMinimumSize(stealth_details.sizeHint())
|
||||||
self.stealth_checkbox = QtWidgets.QCheckBox()
|
self.stealth_checkbox = QtWidgets.QCheckBox()
|
||||||
self.stealth_checkbox.setCheckState(QtCore.Qt.Unchecked)
|
self.stealth_checkbox.setCheckState(QtCore.Qt.Unchecked)
|
||||||
self.stealth_checkbox.setText(strings._("gui_settings_stealth_option", True))
|
self.stealth_checkbox.setText(strings._("gui_settings_stealth_option", True))
|
||||||
|
|
||||||
hidservauth_details = QtWidgets.QLabel(strings._('gui_settings_stealth_hidservauth_string', True))
|
hidservauth_details = QtWidgets.QLabel(strings._('gui_settings_stealth_hidservauth_string', True))
|
||||||
hidservauth_details.setWordWrap(True)
|
hidservauth_details.setWordWrap(True)
|
||||||
|
hidservauth_details.setMinimumSize(hidservauth_details.sizeHint())
|
||||||
hidservauth_details.hide()
|
hidservauth_details.hide()
|
||||||
|
|
||||||
self.hidservauth_copy_button = QtWidgets.QPushButton(strings._('gui_copy_hidservauth', True))
|
self.hidservauth_copy_button = QtWidgets.QPushButton(strings._('gui_copy_hidservauth', True))
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Error 404</title>
|
<title>Error 404</title>
|
||||||
|
<link href="data:image/x-icon;base64,{{favicon_b64}}" rel="icon" type="image/x-icon" />
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
body {
|
body {
|
||||||
background-color: #FFC4D5;
|
background-color: #FFC4D5;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>OnionShare</title>
|
<title>OnionShare</title>
|
||||||
|
<link href="data:image/x-icon;base64,{{favicon_b64}}" rel="icon" type="image/x-icon" />
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
background-color: #222222;
|
background-color: #222222;
|
||||||
|
@ -2,104 +2,137 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>OnionShare</title>
|
<title>OnionShare</title>
|
||||||
|
<link href="data:image/x-icon;base64,{{favicon_b64}}" rel="icon" type="image/x-icon" />
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
body {
|
.clearfix:after {
|
||||||
background-color: #222222;
|
content: ".";
|
||||||
color: #ffffff;
|
display: block;
|
||||||
text-align: center;
|
clear: both;
|
||||||
font-family: sans-serif;
|
visibility: hidden;
|
||||||
padding: 5em 1em;
|
line-height: 0;
|
||||||
}
|
height: 0;
|
||||||
.button {
|
}
|
||||||
-moz-box-shadow:inset 0px 1px 0px 0px #cae3fc;
|
|
||||||
-webkit-box-shadow:inset 0px 1px 0px 0px #cae3fc;
|
|
||||||
box-shadow:inset 0px 1px 0px 0px #cae3fc;
|
|
||||||
background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #79bbff), color-stop(1, #4197ee) );
|
|
||||||
background:-moz-linear-gradient( center top, #79bbff 5%, #4197ee 100% );
|
|
||||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#79bbff', endColorstr='#4197ee');
|
|
||||||
background-color:#79bbff;
|
|
||||||
-webkit-border-top-left-radius:12px;
|
|
||||||
-moz-border-radius-topleft:12px;
|
|
||||||
border-top-left-radius:12px;
|
|
||||||
-webkit-border-top-right-radius:12px;
|
|
||||||
-moz-border-radius-topright:12px;
|
|
||||||
border-top-right-radius:12px;
|
|
||||||
-webkit-border-bottom-right-radius:12px;
|
|
||||||
-moz-border-radius-bottomright:12px;
|
|
||||||
border-bottom-right-radius:12px;
|
|
||||||
-webkit-border-bottom-left-radius:12px;
|
|
||||||
-moz-border-radius-bottomleft:12px;
|
|
||||||
border-bottom-left-radius:12px;
|
|
||||||
text-indent:0;
|
|
||||||
border:1px solid #469df5;
|
|
||||||
display:inline-block;
|
|
||||||
color:#ffffff;
|
|
||||||
font-size:29px;
|
|
||||||
font-weight:bold;
|
|
||||||
font-style:normal;
|
|
||||||
height:50px;
|
|
||||||
line-height:50px;
|
|
||||||
text-decoration:none;
|
|
||||||
text-align:center;
|
|
||||||
text-shadow:1px 1px 0px #287ace;
|
|
||||||
padding: 0 20px;
|
|
||||||
}
|
|
||||||
.button:hover {
|
|
||||||
background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #4197ee), color-stop(1, #79bbff) );
|
|
||||||
background:-moz-linear-gradient( center top, #4197ee 5%, #79bbff 100% );
|
|
||||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#4197ee', endColorstr='#79bbff');
|
|
||||||
background-color:#4197ee;
|
|
||||||
}.button:active {
|
|
||||||
position:relative;
|
|
||||||
top:1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.download-size {
|
body {
|
||||||
color: #999999;
|
margin: 0;
|
||||||
}
|
font-family: Helvetica;
|
||||||
.download-description {
|
}
|
||||||
padding: 10px;
|
|
||||||
}
|
header {
|
||||||
.file-list {
|
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
margin: 50px auto 0 auto;
|
background: #fcfcfc;
|
||||||
padding: 10px;
|
background: -webkit-linear-gradient(top, #fcfcfc 0%, #f2f2f2 100%);
|
||||||
text-align: left;
|
padding: 0.8rem;
|
||||||
background-color: #333333;
|
}
|
||||||
}
|
|
||||||
.file-list th {
|
header .logo {
|
||||||
padding: 5px;
|
vertical-align: middle;
|
||||||
font-weight: bold;
|
width: 45px;
|
||||||
color: #999999;
|
height: 45px;
|
||||||
}
|
}
|
||||||
.file-list td {
|
|
||||||
padding: 5px;
|
header h1 {
|
||||||
}
|
display: inline-block;
|
||||||
|
margin: 0 0 0 0.5rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
header .right {
|
||||||
|
float: right;
|
||||||
|
font-size: .75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
header .right ul li {
|
||||||
|
display: inline;
|
||||||
|
margin: 0 0 0 .5rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
header .button {
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #4e064f;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-decoration: none;
|
||||||
|
margin-left: 1rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.file-list {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.file-list th {
|
||||||
|
text-align: left;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: normal;
|
||||||
|
color: #666666;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.file-list tr {
|
||||||
|
border-bottom: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.file-list td {
|
||||||
|
white-space: nowrap;
|
||||||
|
padding: 0.5rem 10rem 0.5rem 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.file-list td img {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.file-list td:last-child {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<meta name="onionshare-filename" content="{{ filename }}">
|
<meta name="onionshare-filename" content="{{ filename }}">
|
||||||
<meta name="onionshare-filesize" content="{{ filesize }}">
|
<meta name="onionshare-filesize" content="{{ filesize }}">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<p><a class="button" href='/{{ slug }}/download'>{{ filename }} ▼</a></p>
|
|
||||||
<p class="download-size"><strong title="{{ filesize }} bytes">{{ filesize_human }} (compressed)</strong></p>
|
<header class="clearfix">
|
||||||
<p class="download-description">This zip file contains the following contents:</p>
|
<div class="right">
|
||||||
|
<ul>
|
||||||
|
<li>Total size: <strong>{{ filesize_human }}</strong> (compressed)</li>
|
||||||
|
<li><a class="button" href='/{{ slug }}/download'>Download Files</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<img class="logo" src="data:image/png;base64,{{logo_b64}}" title="OnionShare">
|
||||||
|
<h1>OnionShare</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
<table class="file-list">
|
<table class="file-list">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Type</th>
|
<th>Filename</th>
|
||||||
<th>Name</th>
|
|
||||||
<th>Size</th>
|
<th>Size</th>
|
||||||
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for info in file_info.dirs %}
|
{% for info in file_info.dirs %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><img width="30" height="30" title="" alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAB3RJTUUH3ggbFCQXOpwjbQAAAM5JREFUSMftlksOwyAMRDFCbNjkDL1kz9K75Cq9AZF3kYIM7oqoP/KpcFK1mRUrnsbW2Fbq0N+JiPhZRMS1OZAfzLzocwCAGmC9V2Vhjduarj8CzynGqIwxsDl4SXV267E4uFTN33X8deCxDyV1XXeRYJo1UUDEa9M0pxoRK+b4HiqRcz3nVAJKRK+TSxqaGbrkNKUkBn0oNSK2+T0MA1dau9NzO4QwuvPen1lAxQtEsq/vNpSWhvZ9v/3IRMTWOQezkyuEoKy14tfHoU11A6Mr5AxrpuMVAAAAAElFTkSuQmCC" /></td>
|
<td>
|
||||||
<td>{{ info.basename }}</td>
|
<img width="30" height="30" title="" alt="" src="data:image/png;base64,{{ folder_b64 }}" />
|
||||||
|
{{ info.basename }}
|
||||||
|
</td>
|
||||||
<td>{{ info.size_human }}</td>
|
<td>{{ info.size_human }}</td>
|
||||||
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% for info in file_info.files %}
|
{% for info in file_info.files %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><img width="30" height="30" title="" alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAB3RJTUUH3ggbFCQqYvRvfAAAAJFJREFUSMftlUkOwCAIAEWJ//+uIUivtYmtG7VN8KYHRhlA5zYtuB6klCTG2BcEAHrBeN4ws3jvX3lxQZmFiogMgVesVrhKXlvgakKf4KqVdAdXL+Ea3O8aILh0GnUMEhjtw9mLbUv1tx33fgItynBVoN+k2hybY3Nsjg08Bs45q4GYuQ4OIQARLYcSkUPEoiUP4j5IFasKOnUAAAAASUVORK5CYII=" /></td>
|
<td>
|
||||||
<td>{{ info.basename }}</td>
|
<img width="30" height="30" title="" alt="" src="data:image/png;base64,{{ file_b64 }}" />
|
||||||
|
{{ info.basename }}
|
||||||
|
</td>
|
||||||
<td>{{ info.size_human }}</td>
|
<td>{{ info.size_human }}</td>
|
||||||
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
BIN
share/images/favicon.ico
Normal file
BIN
share/images/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
BIN
share/images/info.png
Normal file
BIN
share/images/info.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 435 B |
Binary file not shown.
Before Width: | Height: | Size: 513 B |
BIN
share/images/web_file.png
Normal file
BIN
share/images/web_file.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 251 B |
BIN
share/images/web_folder.png
Normal file
BIN
share/images/web_folder.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 338 B |
@ -13,9 +13,9 @@
|
|||||||
"no_available_port": "Could not start the Onion service as there was no available port.",
|
"no_available_port": "Could not start the Onion service as there was no available port.",
|
||||||
"download_page_loaded": "Download page loaded",
|
"download_page_loaded": "Download page loaded",
|
||||||
"other_page_loaded": "Address loaded",
|
"other_page_loaded": "Address loaded",
|
||||||
"close_on_timeout": "Closing automatically because timeout was reached",
|
"close_on_timeout": "Stopped because timer expired",
|
||||||
"closing_automatically": "Closing automatically because download finished",
|
"closing_automatically": "Stopped because download finished",
|
||||||
"timeout_download_still_running": "Waiting for download to complete before auto-stopping",
|
"timeout_download_still_running": "Waiting for download to complete",
|
||||||
"large_filesize": "Warning: Sending large files could take hours",
|
"large_filesize": "Warning: Sending large files could take hours",
|
||||||
"error_tails_invalid_port": "Invalid value, port must be an integer",
|
"error_tails_invalid_port": "Invalid value, port must be an integer",
|
||||||
"error_tails_unknown_root": "Unknown error with Tails root process",
|
"error_tails_unknown_root": "Unknown error with Tails root process",
|
||||||
@ -44,8 +44,10 @@
|
|||||||
"gui_copy_hidservauth": "Copy HidServAuth",
|
"gui_copy_hidservauth": "Copy HidServAuth",
|
||||||
"gui_downloads": "Downloads:",
|
"gui_downloads": "Downloads:",
|
||||||
"gui_canceled": "Canceled",
|
"gui_canceled": "Canceled",
|
||||||
"gui_copied_url": "Copied address to clipboard",
|
"gui_copied_url_title": "Copied OnionShare address",
|
||||||
"gui_copied_hidservauth": "Copied HidServAuth line to clipboard",
|
"gui_copied_url": "The OnionShare address has been copied to clipboard",
|
||||||
|
"gui_copied_hidservauth_title": "Copied HidServAuth",
|
||||||
|
"gui_copied_hidservauth": "The HidServAuth line has been copied to clipboard",
|
||||||
"gui_starting_server1": "Starting Tor onion service...",
|
"gui_starting_server1": "Starting Tor onion service...",
|
||||||
"gui_starting_server2": "Crunching files...",
|
"gui_starting_server2": "Crunching files...",
|
||||||
"gui_please_wait": "Starting... Click to cancel",
|
"gui_please_wait": "Starting... Click to cancel",
|
||||||
@ -133,11 +135,15 @@
|
|||||||
"gui_server_timeout_expired": "The chosen timeout has already expired.\nPlease update the timeout and then you may start sharing.",
|
"gui_server_timeout_expired": "The chosen timeout has already expired.\nPlease update the timeout and then you may start sharing.",
|
||||||
"share_via_onionshare": "Share via OnionShare",
|
"share_via_onionshare": "Share via OnionShare",
|
||||||
"gui_save_private_key_checkbox": "Use a persistent address\n(unchecking will delete any saved address)",
|
"gui_save_private_key_checkbox": "Use a persistent address\n(unchecking will delete any saved address)",
|
||||||
"persistent_url_in_use": "This share is using a persistent address",
|
|
||||||
"gui_url_description": "<b>Anyone</b> with this link can <b>download</b> your files using <b>Tor Browser</b>:",
|
"gui_url_description": "<b>Anyone</b> with this link can <b>download</b> your files using <b>Tor Browser</b>:",
|
||||||
"gui_url_label": "Your Download Address",
|
"gui_url_label": "Your Download Address <img src={} />",
|
||||||
"gui_url_label_one_time": "Your One-Time Download Address",
|
"gui_url_label_persistent": "This share will not stop automatically<br><br>Every share will have the same address (to use one-time addresses, disable persistence in the Settings)",
|
||||||
|
"gui_url_label_stay_open": "This share will not stop automatically",
|
||||||
|
"gui_url_label_onetime": "This share will stop after the first download",
|
||||||
|
"gui_url_label_onetime_and_persistent": "This share will stop after the first download<br><br>Every share will have the same address (to use one-time addresses, disable persistence in the Settings)",
|
||||||
"gui_status_indicator_stopped": "Ready to Share",
|
"gui_status_indicator_stopped": "Ready to Share",
|
||||||
"gui_status_indicator_working": "Starting...",
|
"gui_status_indicator_working": "Starting...",
|
||||||
"gui_status_indicator_started": "Sharing"
|
"gui_status_indicator_started": "Sharing",
|
||||||
|
"gui_file_info": "{} Files, {}",
|
||||||
|
"gui_file_info_single": "{} File, {}"
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
|
import sys
|
||||||
|
# Force tests to look for resources in the source code tree
|
||||||
|
sys.onionshare_dev_mode = True
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from onionshare import common
|
from onionshare import common
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def temp_dir_1024():
|
def temp_dir_1024():
|
||||||
""" Create a temporary directory that has a single file of a
|
""" Create a temporary directory that has a single file of a
|
||||||
|
Loading…
Reference in New Issue
Block a user