diff --git a/onionshare/__init__.py b/onionshare/__init__.py index f859e10c..1043334e 100644 --- a/onionshare/__init__.py +++ b/onionshare/__init__.py @@ -20,7 +20,7 @@ along with this program. If not, see . import os, sys, time, argparse, threading -from . import strings, helpers, web +from . import strings, common, web from .onion import * from .onionshare import OnionShare @@ -30,11 +30,11 @@ def main(cwd=None): The main() function implements all of the logic that the command-line version of onionshare uses. """ - strings.load_strings(helpers) - print(strings._('version_string').format(helpers.get_version())) + strings.load_strings(common) + print(strings._('version_string').format(common.get_version())) # OnionShare CLI in OSX needs to change current working directory (#132) - if helpers.get_platform() == 'Darwin': + if common.get_platform() == 'Darwin': if cwd: os.chdir(cwd) diff --git a/onionshare/helpers.py b/onionshare/common.py similarity index 100% rename from onionshare/helpers.py rename to onionshare/common.py diff --git a/onionshare/onion.py b/onionshare/onion.py index 194bdfd2..8b673773 100644 --- a/onionshare/onion.py +++ b/onionshare/onion.py @@ -24,7 +24,7 @@ from stem.connection import MissingPassword, UnreadableCookieFile, Authenticatio import os, sys, tempfile, shutil, urllib, platform, subprocess, time, shlex from . import socks -from . import helpers, strings +from . import common, strings from .settings import Settings class TorErrorAutomatic(Exception): @@ -134,7 +134,7 @@ class Onion(object): self.bundle_tor_supported = True # Set the path of the tor binary, for bundled tor - (self.tor_path, self.tor_geo_ip_file_path, self.tor_geo_ipv6_file_path) = helpers.get_tor_paths() + (self.tor_path, self.tor_geo_ip_file_path, self.tor_geo_ipv6_file_path) = common.get_tor_paths() # The tor process self.tor_proc = None @@ -159,19 +159,19 @@ class Onion(object): if self.system == 'Windows': # Windows needs to use network ports, doesn't support unix sockets - torrc_template = open(helpers.get_resource_path('torrc_template-windows')).read() - self.tor_control_port = helpers.get_available_port(1000, 65535) + torrc_template = open(common.get_resource_path('torrc_template-windows')).read() + self.tor_control_port = common.get_available_port(1000, 65535) self.tor_control_socket = None self.tor_cookie_auth_file = os.path.join(self.tor_data_directory.name, 'cookie') - self.tor_socks_port = helpers.get_available_port(1000, 65535) + self.tor_socks_port = common.get_available_port(1000, 65535) self.tor_torrc = os.path.join(self.tor_data_directory.name, 'torrc') else: # Linux and Mac can use unix sockets - torrc_template = open(helpers.get_resource_path('torrc_template')).read() + torrc_template = open(common.get_resource_path('torrc_template')).read() self.tor_control_port = None self.tor_control_socket = os.path.join(self.tor_data_directory.name, 'control_socket') self.tor_cookie_auth_file = os.path.join(self.tor_data_directory.name, 'cookie') - self.tor_socks_port = helpers.get_available_port(1000, 65535) + self.tor_socks_port = common.get_available_port(1000, 65535) self.tor_torrc = os.path.join(self.tor_data_directory.name, 'torrc') torrc_template = torrc_template.replace('{{data_directory}}', self.tor_data_directory.name) diff --git a/onionshare/onionshare.py b/onionshare/onionshare.py index ac5f6fad..43c19694 100644 --- a/onionshare/onionshare.py +++ b/onionshare/onionshare.py @@ -20,7 +20,7 @@ along with this program. If not, see . import os, shutil -from . import helpers +from . import common class OnionShare(object): """ @@ -53,7 +53,7 @@ class OnionShare(object): Start the onionshare onion service. """ # Choose a random port - self.port = helpers.get_available_port(17600, 17650) + self.port = common.get_available_port(17600, 17650) if self.local_only: self.onion_host = '127.0.0.1:{0:d}'.format(self.port) diff --git a/onionshare/settings.py b/onionshare/settings.py index 72e79a7f..119d59a7 100644 --- a/onionshare/settings.py +++ b/onionshare/settings.py @@ -20,7 +20,7 @@ along with this program. If not, see . import platform, os, json -from . import strings, helpers +from . import strings, common class Settings(object): """ @@ -34,7 +34,7 @@ class Settings(object): # These are the default settings. They will get overwritten when loading from disk self.default_settings = { - 'version': helpers.get_version(), + 'version': common.get_version(), 'connection_type': 'bundled', 'control_port_address': '127.0.0.1', 'control_port_port': 9051, diff --git a/onionshare/strings.py b/onionshare/strings.py index 1637e05d..95fcc107 100644 --- a/onionshare/strings.py +++ b/onionshare/strings.py @@ -21,16 +21,16 @@ import json, locale, os strings = {} -def load_strings(helpers, default="en"): +def load_strings(common, default="en"): """ Loads translated strings and fallback to English if the translation does not exist. """ global strings - p = helpers.get_platform() + p = common.get_platform() # find locale dir - locale_dir = helpers.get_resource_path('locale') + locale_dir = common.get_resource_path('locale') # load all translations translations = {} diff --git a/onionshare/web.py b/onionshare/web.py index 2d4af135..2ff60bd2 100644 --- a/onionshare/web.py +++ b/onionshare/web.py @@ -24,7 +24,7 @@ from urllib.request import urlopen from flask import Flask, Response, request, render_template_string, abort from flask import __version__ as flask_version -from . import strings, helpers +from . import strings, common def _safe_select_jinja_autoescape(self, filename): @@ -64,17 +64,17 @@ def set_file_info(filenames, processed_size_callback=None): } if os.path.isfile(filename): info['size'] = os.path.getsize(filename) - info['size_human'] = helpers.human_readable_filesize(info['size']) + info['size_human'] = common.human_readable_filesize(info['size']) file_info['files'].append(info) if os.path.isdir(filename): - info['size'] = helpers.dir_size(filename) - info['size_human'] = helpers.human_readable_filesize(info['size']) + info['size'] = common.dir_size(filename) + info['size_human'] = common.human_readable_filesize(info['size']) file_info['dirs'].append(info) file_info['files'] = sorted(file_info['files'], key=lambda k: k['basename']) file_info['dirs'] = sorted(file_info['dirs'], key=lambda k: k['basename']) # zip up the files and folders - z = helpers.ZipWriter(processed_size_callback=processed_size_callback) + z = common.ZipWriter(processed_size_callback=processed_size_callback) for info in file_info['files']: z.add_file(info['filename']) for info in file_info['dirs']: @@ -108,7 +108,7 @@ def add_request(request_type, path, data=None): slug = None def generate_slug(): global slug - slug = helpers.build_slug() + slug = common.build_slug() download_count = 0 error404_count = 0 @@ -153,7 +153,7 @@ def check_slug_candidate(slug_candidate, slug_compare = None): global slug if not slug_compare: slug_compare = slug - if not helpers.constant_time_compare(slug_compare.encode('ascii'), slug_candidate.encode('ascii')): + if not common.constant_time_compare(slug_compare.encode('ascii'), slug_candidate.encode('ascii')): abort(404) @@ -175,16 +175,16 @@ def index(slug_candidate): global stay_open, download_in_progress deny_download = not stay_open and download_in_progress if deny_download: - return render_template_string(open(helpers.get_resource_path('html/denied.html')).read()) + return render_template_string(open(common.get_resource_path('html/denied.html')).read()) # If download is allowed to continue, serve download page return render_template_string( - open(helpers.get_resource_path('html/index.html')).read(), + open(common.get_resource_path('html/index.html')).read(), slug=slug, file_info=file_info, filename=os.path.basename(zip_filename), filesize=zip_filesize, - filesize_human=helpers.human_readable_filesize(zip_filesize)) + filesize_human=common.human_readable_filesize(zip_filesize)) # 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 @@ -203,7 +203,7 @@ def download(slug_candidate): global stay_open, download_in_progress deny_download = not stay_open and download_in_progress if deny_download: - return render_template_string(open(helpers.get_resource_path('html/denied.html')).read()) + return render_template_string(open(common.get_resource_path('html/denied.html')).read()) global download_count @@ -255,9 +255,9 @@ def download(slug_candidate): percent = (1.0 * downloaded_bytes / zip_filesize) * 100 # only output to stdout if running onionshare in CLI mode, or if using Linux (#203, #304) - if not gui_mode or helpers.get_platform() == 'Linux': + if not gui_mode or common.get_platform() == 'Linux': sys.stdout.write( - "\r{0:s}, {1:.2f}% ".format(helpers.human_readable_filesize(downloaded_bytes), percent)) + "\r{0:s}, {1:.2f}% ".format(common.human_readable_filesize(downloaded_bytes), percent)) sys.stdout.flush() add_request(REQUEST_PROGRESS, path, {'id': download_id, 'bytes': downloaded_bytes}) @@ -271,7 +271,7 @@ def download(slug_candidate): fp.close() - if helpers.get_platform() != 'Darwin': + if common.get_platform() != 'Darwin': sys.stdout.write("\n") # Download is finished @@ -311,10 +311,10 @@ def page_not_found(e): force_shutdown() print(strings._('error_rate_limit')) - return render_template_string(open(helpers.get_resource_path('html/404.html')).read()) + return render_template_string(open(common.get_resource_path('html/404.html')).read()) # shutting down the server only works within the context of flask, so the easiest way to do it is over http -shutdown_slug = helpers.random_string(16) +shutdown_slug = common.random_string(16) @app.route("//shutdown") diff --git a/onionshare_gui/__init__.py b/onionshare_gui/__init__.py index 8168ffcc..8b7bdf3b 100644 --- a/onionshare_gui/__init__.py +++ b/onionshare_gui/__init__.py @@ -21,7 +21,7 @@ from __future__ import division import os, sys, platform, argparse from PyQt5 import QtCore, QtWidgets -from onionshare import strings, helpers, web +from onionshare import strings, common, web from onionshare.onion import Onion from onionshare.onionshare import OnionShare from onionshare.settings import Settings @@ -52,8 +52,8 @@ def main(): """ The main() function implements all of the logic that the GUI version of onionshare uses. """ - strings.load_strings(helpers) - print(strings._('version_string').format(helpers.get_version())) + strings.load_strings(common) + print(strings._('version_string').format(common.get_version())) # Start the Qt app global qtapp diff --git a/onionshare_gui/alert.py b/onionshare_gui/alert.py index 2af7daf0..a07c5569 100644 --- a/onionshare_gui/alert.py +++ b/onionshare_gui/alert.py @@ -19,7 +19,7 @@ along with this program. If not, see . """ from PyQt5 import QtCore, QtWidgets, QtGui -from onionshare import helpers +from onionshare import common class Alert(QtWidgets.QMessageBox): """ @@ -28,7 +28,7 @@ class Alert(QtWidgets.QMessageBox): def __init__(self, message, icon=QtWidgets.QMessageBox.NoIcon, buttons=QtWidgets.QMessageBox.Ok, autostart=True): super(Alert, self).__init__(None) self.setWindowTitle("OnionShare") - self.setWindowIcon(QtGui.QIcon(helpers.get_resource_path('images/logo.png'))) + self.setWindowIcon(QtGui.QIcon(common.get_resource_path('images/logo.png'))) self.setText(message) self.setIcon(icon) self.setStandardButtons(buttons) diff --git a/onionshare_gui/downloads.py b/onionshare_gui/downloads.py index 51e12ac4..f3ac2cb0 100644 --- a/onionshare_gui/downloads.py +++ b/onionshare_gui/downloads.py @@ -21,7 +21,7 @@ import time from PyQt5 import QtCore, QtWidgets -from onionshare import strings, helpers +from onionshare import strings, common class Download(object): @@ -51,7 +51,7 @@ class Download(object): self.progress_bar.setValue(downloaded_bytes) if downloaded_bytes == self.progress_bar.total_bytes: pb_fmt = strings._('gui_download_progress_complete').format( - helpers.format_seconds(time.time() - self.started)) + common.format_seconds(time.time() - self.started)) else: elapsed = time.time() - self.started if elapsed < 10: @@ -59,10 +59,10 @@ class Download(object): # This prevents a "Windows copy dialog"-esque experience at # the beginning of the download. pb_fmt = strings._('gui_download_progress_starting').format( - helpers.human_readable_filesize(downloaded_bytes)) + common.human_readable_filesize(downloaded_bytes)) else: pb_fmt = strings._('gui_download_progress_eta').format( - helpers.human_readable_filesize(downloaded_bytes), + common.human_readable_filesize(downloaded_bytes), self.estimated_time_remaining) self.progress_bar.setFormat(pb_fmt) @@ -72,7 +72,7 @@ class Download(object): @property def estimated_time_remaining(self): - return helpers.estimated_time_remaining(self.downloaded_bytes, + return common.estimated_time_remaining(self.downloaded_bytes, self.total_bytes, self.started) diff --git a/onionshare_gui/file_selection.py b/onionshare_gui/file_selection.py index fa8a7801..5fbf5a75 100644 --- a/onionshare_gui/file_selection.py +++ b/onionshare_gui/file_selection.py @@ -20,7 +20,7 @@ along with this program. If not, see . import os from PyQt5 import QtCore, QtWidgets, QtGui -from onionshare import strings, helpers +from onionshare import strings, common class FileList(QtWidgets.QListWidget): """ @@ -47,7 +47,7 @@ class FileList(QtWidgets.QListWidget): self.setAlignment(QtCore.Qt.AlignCenter) if image: - self.setPixmap(QtGui.QPixmap.fromImage(QtGui.QImage(helpers.get_resource_path('images/drop_files.png')))) + self.setPixmap(QtGui.QPixmap.fromImage(QtGui.QImage(common.get_resource_path('images/drop_files.png')))) else: self.setText(strings._('gui_drag_and_drop', True)) self.setStyleSheet('color: #999999;') @@ -137,9 +137,9 @@ class FileList(QtWidgets.QListWidget): icon = ip.icon(fileinfo) if os.path.isfile(filename): - size = helpers.human_readable_filesize(fileinfo.size()) + size = common.human_readable_filesize(fileinfo.size()) else: - size = helpers.human_readable_filesize(helpers.dir_size(filename)) + size = common.human_readable_filesize(common.dir_size(filename)) item_name = '{0:s} ({1:s})'.format(basename, size) item = QtWidgets.QListWidgetItem(item_name) item.setToolTip(size) diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index 2b464e14..db1c7838 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -20,7 +20,7 @@ along with this program. If not, see . import os, platform, threading, time from PyQt5 import QtCore, QtWidgets, QtGui -from onionshare import strings, helpers, web +from onionshare import strings, common, web from onionshare.settings import Settings from onionshare.onion import * @@ -52,7 +52,7 @@ class OnionShareGui(QtWidgets.QMainWindow): self.app = app self.setWindowTitle('OnionShare') - self.setWindowIcon(QtGui.QIcon(helpers.get_resource_path('images/logo.png'))) + self.setWindowIcon(QtGui.QIcon(common.get_resource_path('images/logo.png'))) # Load settings self.settings = Settings() @@ -118,7 +118,7 @@ class OnionShareGui(QtWidgets.QMainWindow): # Status bar self.status_bar = QtWidgets.QStatusBar() self.status_bar.setSizeGripEnabled(False) - version_label = QtWidgets.QLabel('v{0:s}'.format(helpers.get_version())) + version_label = QtWidgets.QLabel('v{0:s}'.format(common.get_version())) version_label.setStyleSheet('color: #666666; padding: 0 10px;') self.status_bar.addPermanentWidget(version_label) self.setStatusBar(self.status_bar) @@ -280,7 +280,7 @@ class OnionShareGui(QtWidgets.QMainWindow): if os.path.isfile(filename): total_size += os.path.getsize(filename) if os.path.isdir(filename): - total_size += helpers.dir_size(filename) + total_size += common.dir_size(filename) return total_size def check_for_requests(self): diff --git a/onionshare_gui/server_status.py b/onionshare_gui/server_status.py index f5b44337..87143725 100644 --- a/onionshare_gui/server_status.py +++ b/onionshare_gui/server_status.py @@ -20,7 +20,7 @@ along with this program. If not, see . import platform from PyQt5 import QtCore, QtWidgets, QtGui -from onionshare import strings, helpers +from onionshare import strings, common class ServerStatus(QtWidgets.QVBoxLayout): """ @@ -45,9 +45,9 @@ class ServerStatus(QtWidgets.QVBoxLayout): self.file_selection = file_selection # server layout - self.status_image_stopped = QtGui.QImage(helpers.get_resource_path('images/server_stopped.png')) - self.status_image_working = QtGui.QImage(helpers.get_resource_path('images/server_working.png')) - self.status_image_started = QtGui.QImage(helpers.get_resource_path('images/server_started.png')) + self.status_image_stopped = QtGui.QImage(common.get_resource_path('images/server_stopped.png')) + self.status_image_working = QtGui.QImage(common.get_resource_path('images/server_working.png')) + self.status_image_started = QtGui.QImage(common.get_resource_path('images/server_started.png')) self.status_image_label = QtWidgets.QLabel() self.status_image_label.setFixedWidth(30) self.server_button = QtWidgets.QPushButton() diff --git a/onionshare_gui/settings_dialog.py b/onionshare_gui/settings_dialog.py index bfd82569..d368fb4f 100644 --- a/onionshare_gui/settings_dialog.py +++ b/onionshare_gui/settings_dialog.py @@ -20,7 +20,7 @@ along with this program. If not, see . from PyQt5 import QtCore, QtWidgets, QtGui import sys, platform, datetime -from onionshare import strings, helpers +from onionshare import strings, common from onionshare.settings import Settings from onionshare.onion import * @@ -38,7 +38,7 @@ class SettingsDialog(QtWidgets.QDialog): self.setModal(True) self.setWindowTitle(strings._('gui_settings_window_title', True)) - self.setWindowIcon(QtGui.QIcon(helpers.get_resource_path('images/logo.png'))) + self.setWindowIcon(QtGui.QIcon(common.get_resource_path('images/logo.png'))) system = platform.system() diff --git a/onionshare_gui/tor_connection_dialog.py b/onionshare_gui/tor_connection_dialog.py index ee1a9b28..486f7b51 100644 --- a/onionshare_gui/tor_connection_dialog.py +++ b/onionshare_gui/tor_connection_dialog.py @@ -19,7 +19,7 @@ along with this program. If not, see . """ from PyQt5 import QtCore, QtWidgets, QtGui -from onionshare import strings, helpers +from onionshare import strings, common from onionshare.onion import * from .alert import Alert @@ -36,7 +36,7 @@ class TorConnectionDialog(QtWidgets.QProgressDialog): self.onion = onion self.setWindowTitle("OnionShare") - self.setWindowIcon(QtGui.QIcon(helpers.get_resource_path('images/logo.png'))) + self.setWindowIcon(QtGui.QIcon(common.get_resource_path('images/logo.png'))) self.setModal(True) self.setFixedSize(400, 150) diff --git a/onionshare_gui/update_checker.py b/onionshare_gui/update_checker.py index dcba820a..233f29e7 100644 --- a/onionshare_gui/update_checker.py +++ b/onionshare_gui/update_checker.py @@ -24,7 +24,7 @@ from onionshare import socks from onionshare.settings import Settings from onionshare.onion import Onion -from . import strings, helpers +from . import strings, common class UpdateCheckerCheckError(Exception): """ @@ -85,7 +85,7 @@ class UpdateChecker(QtCore.QObject): # Download the latest-version file over Tor try: # User agent string includes OnionShare version and platform - user_agent = 'OnionShare {}, {}'.format(helpers.get_version(), platform.system()) + user_agent = 'OnionShare {}, {}'.format(common.get_version(), platform.system()) # If the update is forced, add '?force=1' to the URL, to more # accurately measure daily users @@ -124,7 +124,7 @@ class UpdateChecker(QtCore.QObject): # Do we need to update? update_url = 'https://github.com/micahflee/onionshare/releases/tag/v{}'.format(latest_version) - installed_version = helpers.get_version() + installed_version = common.get_version() if installed_version < latest_version: self.update_available.emit(update_url, installed_version, latest_version) return diff --git a/share/locale/en.json b/share/locale/en.json index 75b4341b..cd346868 100644 --- a/share/locale/en.json +++ b/share/locale/en.json @@ -19,7 +19,7 @@ "help_stay_open": "Keep onion service running after download has finished", "help_transparent_torification": "My system is transparently torified", "help_stealth": "Create stealth onion service (advanced)", - "help_debug": "Log errors to disk", + "help_debug": "Log application errors to stdout, and log web errors to disk", "help_filename": "List of files or folders to share", "gui_drag_and_drop": "Drag and drop\nfiles here", "gui_add_files": "Add Files", diff --git a/test/onionshare_helpers_test.py b/test/onionshare_common_test.py similarity index 81% rename from test/onionshare_helpers_test.py rename to test/onionshare_common_test.py index 6637a5ff..3bc4b9d6 100644 --- a/test/onionshare_helpers_test.py +++ b/test/onionshare_common_test.py @@ -17,20 +17,19 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ import socket -from onionshare import helpers +from onionshare import common def test_get_platform_returns_platform_system(): """get_platform() returns platform.system() when ONIONSHARE_PLATFORM is not defined""" - p = helpers.platform.system - helpers.platform.system = lambda: 'Sega Saturn' - assert helpers.get_platform() == 'Sega Saturn' - helpers.platform.system = p + p = common.platform.system + common.platform.system = lambda: 'Sega Saturn' + assert common.get_platform() == 'Sega Saturn' + common.platform.system = p def test_get_available_port_returns_an_open_port(): """get_available_port() should return an open port within the range""" for i in range(100): - port = helpers.get_available_port(1024, 2048) + port = common.get_available_port(1024, 2048) assert 1024 <= port <= 2048 socket.socket().bind(("127.0.0.1", port)) - diff --git a/test/onionshare_strings_test.py b/test/onionshare_strings_test.py index dc20a271..ee532b81 100644 --- a/test/onionshare_strings_test.py +++ b/test/onionshare_strings_test.py @@ -18,14 +18,14 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ import locale, os -from onionshare import helpers, strings +from onionshare import common, strings # Stub get_resource_path so it finds the correct path while running tests def get_resource_path(filename): resources_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'share') path = os.path.join(resources_dir, filename) return path -helpers.get_resource_path = get_resource_path +common.get_resource_path = get_resource_path def test_starts_with_empty_strings(): """creates an empty strings dict by default""" @@ -35,12 +35,12 @@ def test_starts_with_empty_strings(): def test_load_strings_defaults_to_english(): """load_strings() loads English by default""" locale.getdefaultlocale = lambda: ('en_US', 'UTF-8') - strings.load_strings(helpers) + strings.load_strings(common) assert strings._('wait_for_hs') == "Waiting for HS to be ready:" def test_load_strings_loads_other_languages(): """load_strings() loads other languages in different locales""" locale.getdefaultlocale = lambda: ('fr_FR', 'UTF-8') - strings.load_strings(helpers, "fr") + strings.load_strings(common, "fr") assert strings._('wait_for_hs') == "En attente du HS:"