From d51f762dddd959258de75c933a20dac083e57f8a Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Tue, 18 Nov 2014 17:39:04 +0100 Subject: [PATCH 1/9] pep8: use triple double-quotes for docstrings --- check_lacked_trans.py | 4 ++-- onionshare/onionshare.py | 2 +- test/onionshare_helpers_test.py | 4 ++-- test/onionshare_strings_test.py | 6 +++--- test/onionshare_test.py | 4 ++-- test/onionshare_web_test.py | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/check_lacked_trans.py b/check_lacked_trans.py index 3ee90ec7..ae57cdfa 100644 --- a/check_lacked_trans.py +++ b/check_lacked_trans.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -''' +""" Check translation lacked or disused. Example: @@ -24,7 +24,7 @@ es disused gui_starting_server 2. load translation key from locale/*.json. 3. compare these. -''' +""" import fileinput, argparse, re, os, codecs, json, sys diff --git a/onionshare/onionshare.py b/onionshare/onionshare.py index 44b6874f..739862cf 100644 --- a/onionshare/onionshare.py +++ b/onionshare/onionshare.py @@ -29,7 +29,7 @@ class NoTor(Exception): pass class TailsError(Exception): pass def hsdic2list(dic): - "Convert what we get from get_conf_map to what we need for set_options" + """Convert what we get from get_conf_map to what we need for set_options""" return [ pair for pairs in [ [('HiddenServiceDir',vals[0]),('HiddenServicePort',vals[1])] diff --git a/test/onionshare_helpers_test.py b/test/onionshare_helpers_test.py index eb84cc36..94febed3 100644 --- a/test/onionshare_helpers_test.py +++ b/test/onionshare_helpers_test.py @@ -22,12 +22,12 @@ from nose import with_setup import test_helpers def test_get_platform_on_tails(): - "get_platform() returns 'Tails' when hostname is 'amnesia'" + """get_platform() returns 'Tails' when hostname is 'amnesia'""" helpers.platform.uname = lambda: ('Linux', 'amnesia', '3.14-1-amd64', '#1 SMP Debian 3.14.4-1 (2014-05-13)', 'x86_64', '') assert helpers.get_platform() == 'Tails' def test_get_platform_returns_platform_system(): - "get_platform() returns platform.system() when ONIONSHARE_PLATFORM is not defined" + """get_platform() returns platform.system() when ONIONSHARE_PLATFORM is not defined""" helpers.platform.system = lambda: 'Sega Saturn' assert helpers.get_platform() == 'Sega Saturn' diff --git a/test/onionshare_strings_test.py b/test/onionshare_strings_test.py index f4ad5a87..011bf406 100644 --- a/test/onionshare_strings_test.py +++ b/test/onionshare_strings_test.py @@ -22,17 +22,17 @@ from onionshare import strings from nose import with_setup def test_starts_with_empty_strings(): - "creates an empty strings dict by default" + """creates an empty strings dict by default""" assert strings.strings == {} def test_load_strings_defaults_to_english(): - "load_strings() loads English by default" + """load_strings() loads English by default""" locale.getdefaultlocale = lambda: ('en_US', 'UTF-8') strings.load_strings() 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" + """load_strings() loads other languages in different locales""" locale.getdefaultlocale = lambda: ('fr_FR', 'UTF-8') strings.load_strings("fr") assert strings._('wait_for_hs') == "En attente du HS:" diff --git a/test/onionshare_test.py b/test/onionshare_test.py index 5246d4a1..0edf1be7 100644 --- a/test/onionshare_test.py +++ b/test/onionshare_test.py @@ -21,13 +21,13 @@ from onionshare import OnionShare from nose import with_setup def test_choose_port_returns_a_port_number(): - "choose_port() returns a port number" + """choose_port() returns a port number""" app = OnionShare() app.choose_port() assert 1024 <= app.port <= 65535 def test_choose_port_returns_an_open_port(): - "choose_port() returns an open port" + """choose_port() returns an open port""" app = OnionShare() # choose a new port app.choose_port() diff --git a/test/onionshare_web_test.py b/test/onionshare_web_test.py index 91a04921..963e7e2a 100644 --- a/test/onionshare_web_test.py +++ b/test/onionshare_web_test.py @@ -20,11 +20,11 @@ from onionshare import web from nose import with_setup def test_generate_slug_length(): - "generates a 26-character slug" + """generates a 26-character slug""" assert len(web.slug) == 26 def test_generate_slug_characters(): - "generates a base32-encoded slug" + """generates a base32-encoded slug""" def is_b32(string): b32_alphabet = "01234556789abcdefghijklmnopqrstuvwxyz" From 5deb3f9e0f5b7cd81602f90f859c2ec0e4e41eec Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Tue, 18 Nov 2014 18:03:34 +0100 Subject: [PATCH 2/9] pep8: fix indentation to be a multiple of four note: i used pycharm "reformat file", so there are other reformattings also --- onionshare/web.py | 37 ++++++++++++++++++++++++++++--------- test/test_helpers.py | 18 ++++++++++-------- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/onionshare/web.py b/onionshare/web.py index d9e6b866..07d1fd9c 100644 --- a/onionshare/web.py +++ b/onionshare/web.py @@ -28,11 +28,13 @@ app = Flask(__name__) file_info = [] zip_filename = None zip_filesize = None + + def set_file_info(filenames): global file_info, zip_filename, zip_filesize # build file info list - file_info = {'files':[], 'dirs':[]} + file_info = {'files': [], 'dirs': []} for filename in filenames: info = { 'filename': filename, @@ -59,6 +61,7 @@ def set_file_info(filenames): zip_filename = z.zip_filename zip_filesize = os.path.getsize(zip_filename) + REQUEST_LOAD = 0 REQUEST_DOWNLOAD = 1 REQUEST_PROGRESS = 2 @@ -66,24 +69,31 @@ REQUEST_OTHER = 3 REQUEST_CANCELED = 4 q = Queue.Queue() + def add_request(type, path, data=None): global q q.put({ - 'type': type, - 'path': path, - 'data': data + 'type': type, + 'path': path, + 'data': data }) + slug = helpers.random_string(16) download_count = 0 stay_open = False + + def set_stay_open(new_stay_open): global stay_open stay_open = new_stay_open + + def get_stay_open(): return stay_open + def debug_mode(): import logging @@ -96,6 +106,7 @@ def debug_mode(): log_handler.setLevel(logging.WARNING) app.logger.addHandler(log_handler) + @app.route("/") def index(slug_candidate): if not helpers.constant_time_compare(slug.encode('ascii'), slug_candidate.encode('ascii')): @@ -112,6 +123,7 @@ def index(slug_candidate): strings=strings.strings ) + @app.route("//download") def download(slug_candidate): global download_count @@ -128,13 +140,13 @@ def download(slug_candidate): path = request.path # tell GUI the download started - add_request(REQUEST_DOWNLOAD, path, { 'id':download_id }) + add_request(REQUEST_DOWNLOAD, path, {'id': download_id}) dirname = os.path.dirname(zip_filename) basename = os.path.basename(zip_filename) def generate(): - chunk_size = 102400 # 100kb + chunk_size = 102400 # 100kb fp = open(zip_filename, 'rb') done = False @@ -150,16 +162,17 @@ def download(slug_candidate): # tell GUI the progress downloaded_bytes = fp.tell() percent = round((1.0 * downloaded_bytes / zip_filesize) * 100, 2) - sys.stdout.write("\r{0}, {1}% ".format(helpers.human_readable_filesize(downloaded_bytes), percent)) + sys.stdout.write( + "\r{0}, {1}% ".format(helpers.human_readable_filesize(downloaded_bytes), percent)) sys.stdout.flush() - add_request(REQUEST_PROGRESS, path, { 'id':download_id, 'bytes':downloaded_bytes }) + add_request(REQUEST_PROGRESS, path, {'id': download_id, 'bytes': downloaded_bytes}) except: # looks like the download was canceled done = True canceled = True # tell the GUI the download has canceled - add_request(REQUEST_CANCELED, path, { 'id':download_id }) + add_request(REQUEST_CANCELED, path, {'id': download_id}) fp.close() sys.stdout.write("\n") @@ -181,6 +194,7 @@ def download(slug_candidate): r.headers.add('Content-Type', content_type) return r + @app.errorhandler(404) def page_not_found(e): add_request(REQUEST_OTHER, request.path) @@ -188,6 +202,8 @@ def page_not_found(e): # 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) + + @app.route("//shutdown") def shutdown(shutdown_slug_candidate): if not helpers.constant_time_compare(shutdown_slug.encode('ascii'), shutdown_slug_candidate.encode('ascii')): @@ -201,16 +217,19 @@ def shutdown(shutdown_slug_candidate): return "" + def start(port, stay_open=False): set_stay_open(stay_open) app.run(port=port, threaded=True) + def stop(port): # to stop flask, load http://127.0.0.1://shutdown if helpers.get_platform() == 'Tails': # in Tails everything is proxies over Tor, so we need to get lower level # to connect not over the proxy import socket + s = socket.socket() s.connect(('127.0.0.1', port)) s.sendall('GET /{0}/shutdown HTTP/1.1\r\n\r\n'.format(shutdown_slug)) diff --git a/test/test_helpers.py b/test/test_helpers.py index c4705142..cab2dd34 100644 --- a/test/test_helpers.py +++ b/test/test_helpers.py @@ -18,22 +18,24 @@ along with this program. If not, see . """ import tempfile + class MockSubprocess(): - def __init__(self): - self.last_call = None + def __init__(self): + self.last_call = None - def call(self, args): - self.last_call = args + def call(self, args): + self.last_call = args + + def last_call_args(self): + return self.last_call - def last_call_args(self): - return self.last_call def write_tempfile(text): tempdir = tempfile.mkdtemp() path = tempdir + "/test-file.txt" with open(path, "w") as f: - f.write(text) - f.close() + f.write(text) + f.close() return path From 179eefae29491f5d0c0ddf2aca1164dbf2cba4f9 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Tue, 18 Nov 2014 18:29:32 +0100 Subject: [PATCH 3/9] pep8: fix empty line counts top level: 2, else 1 I also advice to not put "pass" into empty classes, but rather a docstring instead of "pass". --- check_lacked_trans.py | 2 -- onionshare/helpers.py | 9 ++++++- onionshare/onionshare.py | 15 +++++++++--- onionshare/socks.py | 40 +++++++++++++++++++++++++------- onionshare/strings.py | 2 ++ onionshare_gui/common.py | 2 ++ onionshare_gui/downloads.py | 1 + onionshare_gui/file_selection.py | 2 ++ onionshare_gui/onionshare_gui.py | 4 ++++ onionshare_gui/options.py | 1 + onionshare_gui/server_status.py | 1 + setup.py | 1 + test/onionshare_helpers_test.py | 2 ++ test/onionshare_strings_test.py | 3 +++ test/onionshare_test.py | 2 ++ test/onionshare_web_test.py | 2 ++ 16 files changed, 74 insertions(+), 15 deletions(-) diff --git a/check_lacked_trans.py b/check_lacked_trans.py index ae57cdfa..6dc145a7 100644 --- a/check_lacked_trans.py +++ b/check_lacked_trans.py @@ -75,13 +75,11 @@ def main(): key = m.group(1) translate_keys.add(key) - if args.show_all_keys: for k in sorted(translate_keys): print k sys.exit() - locale_files = [f for f in files_in(dir, 'locale') if f.endswith('.json')] for locale_file in locale_files: with codecs.open(locale_file, 'r', encoding='utf-8') as f: diff --git a/onionshare/helpers.py b/onionshare/helpers.py index 4555f7ba..da7e911e 100644 --- a/onionshare/helpers.py +++ b/onionshare/helpers.py @@ -32,6 +32,7 @@ def get_platform(): p = 'Tails' return p + def get_onionshare_dir(): if get_platform() == 'Darwin': onionshare_dir = os.path.dirname(__file__) @@ -39,6 +40,7 @@ def get_onionshare_dir(): onionshare_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) return onionshare_dir + def constant_time_compare(val1, val2): _builtin_constant_time_compare = getattr(hmac, 'compare_digest', None) if _builtin_constant_time_compare is not None: @@ -55,6 +57,7 @@ def constant_time_compare(val1, val2): result |= x ^ y return result == 0 + def random_string(num_bytes, output_len=None): b = os.urandom(num_bytes) h = hashlib.sha256(b).digest()[:16] @@ -63,6 +66,7 @@ def random_string(num_bytes, output_len=None): return s return s[:output_len] + def human_readable_filesize(b): thresh = 1024.0 if b < thresh: @@ -75,9 +79,11 @@ def human_readable_filesize(b): u += 1 return '{0} {1}'.format(round(b, 1), units[u]) + def is_root(): return os.geteuid() == 0 + def dir_size(start_path): total_size = 0 for dirpath, dirnames, filenames in os.walk(start_path): @@ -87,6 +93,7 @@ def dir_size(start_path): total_size += os.path.getsize(fp) return total_size + def get_tmp_dir(): if get_platform() == "Windows": if 'Temp' in os.environ: @@ -97,6 +104,7 @@ def get_tmp_dir(): temp = '/tmp' return temp + class ZipWriter(object): def __init__(self, zip_filename=None): if zip_filename: @@ -120,4 +128,3 @@ class ZipWriter(object): def close(self): self.z.close() - diff --git a/onionshare/onionshare.py b/onionshare/onionshare.py index 739862cf..742a6b98 100644 --- a/onionshare/onionshare.py +++ b/onionshare/onionshare.py @@ -25,8 +25,14 @@ from stem import SocketError import strings, helpers, web -class NoTor(Exception): pass -class TailsError(Exception): pass + +class NoTor(Exception): + pass + + +class TailsError(Exception): + pass + def hsdic2list(dic): """Convert what we get from get_conf_map to what we need for set_options""" @@ -37,6 +43,7 @@ def hsdic2list(dic): ] for pair in pairs ] + class OnionShare(object): def __init__(self, debug=False, local_only=False, stay_open=False): self.port = None @@ -56,7 +63,6 @@ class OnionShare(object): # files and dirs to delete on shutdown self.cleanup_filenames = [] - def cleanup(self): if self.controller: # Get fresh hidden services (maybe changed since last time) @@ -191,6 +197,7 @@ class OnionShare(object): return False return True + def tails_root(): # if running in Tails and as root, do only the things that require root if helpers.get_platform() == 'Tails' and helpers.is_root(): @@ -217,6 +224,7 @@ def tails_root(): # close hole in firewall on shutdown import signal + def handler(signum = None, frame = None): subprocess.call(['/sbin/iptables', '-D', 'OUTPUT', '-o', 'lo', '-p', 'tcp', '--dport', str(port), '-j', 'ACCEPT']) sys.exit() @@ -227,6 +235,7 @@ def tails_root(): while True: time.sleep(1) + def main(): strings.load_strings() tails_root() diff --git a/onionshare/socks.py b/onionshare/socks.py index 709220db..49b96b79 100644 --- a/onionshare/socks.py +++ b/onionshare/socks.py @@ -65,6 +65,7 @@ PRINTABLE_PROXY_TYPES = {SOCKS4: "SOCKS4", SOCKS5: "SOCKS5", HTTP: "HTTP"} _orgsocket = _orig_socket = socket.socket + class ProxyError(IOError): """ socket_err contains original socket.error exception. @@ -79,12 +80,30 @@ class ProxyError(IOError): def __str__(self): return self.msg -class GeneralProxyError(ProxyError): pass -class ProxyConnectionError(ProxyError): pass -class SOCKS5AuthError(ProxyError): pass -class SOCKS5Error(ProxyError): pass -class SOCKS4Error(ProxyError): pass -class HTTPError(ProxyError): pass + +class GeneralProxyError(ProxyError): + pass + + +class ProxyConnectionError(ProxyError): + pass + + +class SOCKS5AuthError(ProxyError): + pass + + +class SOCKS5Error(ProxyError): + pass + + +class SOCKS4Error(ProxyError): + pass + + +class HTTPError(ProxyError): + pass + SOCKS4_ERRORS = { 0x5B: "Request rejected or failed", 0x5C: "Request rejected because SOCKS server cannot connect to identd on the client", @@ -106,6 +125,7 @@ DEFAULT_PORTS = { SOCKS4: 1080, HTTP: 8080 } + def set_default_proxy(proxy_type=None, addr=None, port=None, rdns=True, username=None, password=None): """ set_default_proxy(proxy_type, addr[, port[, rdns[, username, password]]]) @@ -119,6 +139,7 @@ def set_default_proxy(proxy_type=None, addr=None, port=None, rdns=True, username setdefaultproxy = set_default_proxy + def get_default_proxy(): """ Returns the default proxy, set by set_default_proxy. @@ -127,6 +148,7 @@ def get_default_proxy(): getdefaultproxy = get_default_proxy + def wrap_module(module): """ Attempts to replace a module's socket library with a SOCKS socket. Must set @@ -141,7 +163,8 @@ def wrap_module(module): wrapmodule = wrap_module -def create_connection(dest_pair, proxy_type=None, proxy_addr=None, + +def create_connection(dest_pair, proxy_type=None, proxy_addr=None, proxy_port=None, proxy_username=None, proxy_password=None, timeout=None): """create_connection(dest_pair, **proxy_args) -> socket object @@ -161,6 +184,7 @@ def create_connection(dest_pair, proxy_type=None, proxy_addr=None, sock.connect(dest_pair) return sock + class socksocket(socket.socket): """socksocket([family[, type[, proto]]]) -> socket object @@ -446,7 +470,6 @@ class socksocket(socket.socket): self.proxy_sockname = (b"0.0.0.0", 0) self.proxy_peername = addr, dest_port - def connect(self, dest_pair): """ Connects to the specified destination through a proxy. @@ -465,7 +488,6 @@ class socksocket(socket.socket): or not isinstance(dest_port, int)): raise GeneralProxyError("Invalid destination-connection (host, port) pair") - if proxy_type is None: # Treat like regular socket object _orig_socket.connect(self, (dest_addr, dest_port)) diff --git a/onionshare/strings.py b/onionshare/strings.py index 4222fba1..4a0bdb80 100644 --- a/onionshare/strings.py +++ b/onionshare/strings.py @@ -22,6 +22,7 @@ import helpers strings = {} + def load_strings(default="en"): global strings @@ -49,6 +50,7 @@ def load_strings(default="en"): if key in translated[lang]: strings[key] = translated[lang][key] + def translated(k, gui=False): if gui: return strings[k].encode("utf-8").decode('utf-8', 'replace') diff --git a/onionshare_gui/common.py b/onionshare_gui/common.py index 6c5c06a0..927ebfe1 100644 --- a/onionshare_gui/common.py +++ b/onionshare_gui/common.py @@ -19,6 +19,7 @@ along with this program. If not, see . """ import os, sys, inspect, platform + def get_onionshare_gui_dir(): if platform.system() == 'Darwin': onionshare_gui_dir = os.path.dirname(__file__) @@ -28,6 +29,7 @@ def get_onionshare_gui_dir(): onionshare_gui_dir = get_onionshare_gui_dir() + def get_image_path(filename): if platform.system() == 'Linux': prefix = os.path.join(sys.prefix, 'share/onionshare/images') diff --git a/onionshare_gui/downloads.py b/onionshare_gui/downloads.py index 90ef6f0d..be32c0fe 100644 --- a/onionshare_gui/downloads.py +++ b/onionshare_gui/downloads.py @@ -22,6 +22,7 @@ from PyQt4 import QtCore, QtGui import common from onionshare import strings, helpers + class Downloads(QtGui.QVBoxLayout): def __init__(self): super(Downloads, self).__init__() diff --git a/onionshare_gui/file_selection.py b/onionshare_gui/file_selection.py index 4a5bfeb8..eb6cb36f 100644 --- a/onionshare_gui/file_selection.py +++ b/onionshare_gui/file_selection.py @@ -23,6 +23,7 @@ from PyQt4 import QtCore, QtGui import common from onionshare import strings, helpers + class FileList(QtGui.QListWidget): files_dropped = QtCore.pyqtSignal() files_updated = QtCore.pyqtSignal() @@ -137,6 +138,7 @@ class FileList(QtGui.QListWidget): u += 1 return '{0} {1}'.format(round(b, 1), units[u]) + class FileSelection(QtGui.QVBoxLayout): def __init__(self): super(FileSelection, self).__init__() diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index 41f01852..f20c681e 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -35,6 +35,7 @@ from server_status import ServerStatus from downloads import Downloads from options import Options + class Application(QtGui.QApplication): def __init__(self): platform = helpers.get_platform() @@ -42,6 +43,7 @@ class Application(QtGui.QApplication): self.setAttribute(QtCore.Qt.AA_X11InitThreads, True) QtGui.QApplication.__init__(self, sys.argv) + class OnionShareGui(QtGui.QWidget): start_server_finished = QtCore.pyqtSignal() stop_server_finished = QtCore.pyqtSignal() @@ -206,6 +208,7 @@ class OnionShareGui(QtGui.QWidget): def clear_message(self): self.status_bar.clearMessage() + def alert(msg, icon=QtGui.QMessageBox.NoIcon): dialog = QtGui.QMessageBox() dialog.setWindowTitle("OnionShare") @@ -214,6 +217,7 @@ def alert(msg, icon=QtGui.QMessageBox.NoIcon): dialog.setIcon(icon) dialog.exec_() + def main(): strings.load_strings() diff --git a/onionshare_gui/options.py b/onionshare_gui/options.py index 24d59920..f7443b85 100644 --- a/onionshare_gui/options.py +++ b/onionshare_gui/options.py @@ -22,6 +22,7 @@ from PyQt4 import QtCore, QtGui import common from onionshare import strings, helpers + class Options(QtGui.QHBoxLayout): def __init__(self, web): super(Options, self).__init__() diff --git a/onionshare_gui/server_status.py b/onionshare_gui/server_status.py index 2909c316..c5a9daa1 100644 --- a/onionshare_gui/server_status.py +++ b/onionshare_gui/server_status.py @@ -23,6 +23,7 @@ from PyQt4 import QtCore, QtGui import common from onionshare import strings, helpers + class ServerStatus(QtGui.QVBoxLayout): server_started = QtCore.pyqtSignal() server_stopped = QtCore.pyqtSignal() diff --git a/setup.py b/setup.py index 9b9a500f..1ef27ccc 100644 --- a/setup.py +++ b/setup.py @@ -27,6 +27,7 @@ try: except ImportError: from distutils.core import setup + def file_list(path): files = [] for filename in os.listdir(path): diff --git a/test/onionshare_helpers_test.py b/test/onionshare_helpers_test.py index 94febed3..1c7c42d2 100644 --- a/test/onionshare_helpers_test.py +++ b/test/onionshare_helpers_test.py @@ -21,11 +21,13 @@ from nose import with_setup import test_helpers + def test_get_platform_on_tails(): """get_platform() returns 'Tails' when hostname is 'amnesia'""" helpers.platform.uname = lambda: ('Linux', 'amnesia', '3.14-1-amd64', '#1 SMP Debian 3.14.4-1 (2014-05-13)', 'x86_64', '') assert helpers.get_platform() == 'Tails' + def test_get_platform_returns_platform_system(): """get_platform() returns platform.system() when ONIONSHARE_PLATFORM is not defined""" helpers.platform.system = lambda: 'Sega Saturn' diff --git a/test/onionshare_strings_test.py b/test/onionshare_strings_test.py index 011bf406..ab215e0f 100644 --- a/test/onionshare_strings_test.py +++ b/test/onionshare_strings_test.py @@ -21,16 +21,19 @@ import locale from onionshare import strings from nose import with_setup + def test_starts_with_empty_strings(): """creates an empty strings dict by default""" assert strings.strings == {} + def test_load_strings_defaults_to_english(): """load_strings() loads English by default""" locale.getdefaultlocale = lambda: ('en_US', 'UTF-8') strings.load_strings() 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') diff --git a/test/onionshare_test.py b/test/onionshare_test.py index 0edf1be7..76d6b9a0 100644 --- a/test/onionshare_test.py +++ b/test/onionshare_test.py @@ -20,12 +20,14 @@ import socket from onionshare import OnionShare from nose import with_setup + def test_choose_port_returns_a_port_number(): """choose_port() returns a port number""" app = OnionShare() app.choose_port() assert 1024 <= app.port <= 65535 + def test_choose_port_returns_an_open_port(): """choose_port() returns an open port""" app = OnionShare() diff --git a/test/onionshare_web_test.py b/test/onionshare_web_test.py index 963e7e2a..54c4872f 100644 --- a/test/onionshare_web_test.py +++ b/test/onionshare_web_test.py @@ -19,10 +19,12 @@ along with this program. If not, see . from onionshare import web from nose import with_setup + def test_generate_slug_length(): """generates a 26-character slug""" assert len(web.slug) == 26 + def test_generate_slug_characters(): """generates a base32-encoded slug""" From 63965fd2d94c8297bffeb312bbaca7deaf8fb7c6 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Tue, 18 Nov 2014 18:35:09 +0100 Subject: [PATCH 4/9] pep8: blank after comma and colon --- onionshare/helpers.py | 4 ++-- onionshare/onionshare.py | 12 ++++++------ onionshare_gui/file_selection.py | 2 +- onionshare_gui/onionshare_gui.py | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/onionshare/helpers.py b/onionshare/helpers.py index da7e911e..210b9d29 100644 --- a/onionshare/helpers.py +++ b/onionshare/helpers.py @@ -61,7 +61,7 @@ def constant_time_compare(val1, val2): def random_string(num_bytes, output_len=None): b = os.urandom(num_bytes) h = hashlib.sha256(b).digest()[:16] - s = base64.b32encode(h).lower().replace('=','') + s = base64.b32encode(h).lower().replace('=', '') if not output_len: return s return s[:output_len] @@ -71,7 +71,7 @@ def human_readable_filesize(b): thresh = 1024.0 if b < thresh: return '{0} B'.format(b) - units = ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'] + units = ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'] u = 0 b /= thresh while b >= thresh: diff --git a/onionshare/onionshare.py b/onionshare/onionshare.py index 742a6b98..7e95c26c 100644 --- a/onionshare/onionshare.py +++ b/onionshare/onionshare.py @@ -38,8 +38,8 @@ def hsdic2list(dic): """Convert what we get from get_conf_map to what we need for set_options""" return [ pair for pairs in [ - [('HiddenServiceDir',vals[0]),('HiddenServicePort',vals[1])] - for vals in zip(dic.get('HiddenServiceDir',[]),dic.get('HiddenServicePort',[])) + [('HiddenServiceDir', vals[0]), ('HiddenServicePort', vals[1])] + for vals in zip(dic.get('HiddenServiceDir', []), dic.get('HiddenServicePort', [])) ] for pair in pairs ] @@ -70,7 +70,7 @@ class OnionShare(object): hsdic = self.controller.get_conf_map('HiddenServiceOptions') or { 'HiddenServiceDir': [], 'HiddenServicePort': [] } - if self.hidserv_dir and self.hidserv_dir in hsdic.get('HiddenServiceDir',[]): + if self.hidserv_dir and self.hidserv_dir in hsdic.get('HiddenServiceDir', []): dropme = hsdic['HiddenServiceDir'].index(self.hidserv_dir) del hsdic['HiddenServiceDir'][dropme] del hsdic['HiddenServicePort'][dropme] @@ -138,13 +138,13 @@ class OnionShare(object): hsdic = self.controller.get_conf_map('HiddenServiceOptions') or { 'HiddenServiceDir': [], 'HiddenServicePort': [] } - if self.hidserv_dir in hsdic.get('HiddenServiceDir',[]): + if self.hidserv_dir in hsdic.get('HiddenServiceDir', []): # Maybe a stale service with the wrong local port dropme = hsdic['HiddenServiceDir'].index(self.hidserv_dir) del hsdic['HiddenServiceDir'][dropme] del hsdic['HiddenServicePort'][dropme] - hsdic['HiddenServiceDir'] = hsdic.get('HiddenServiceDir',[])+[self.hidserv_dir] - hsdic['HiddenServicePort'] = hsdic.get('HiddenServicePort',[])+[ + hsdic['HiddenServiceDir'] = hsdic.get('HiddenServiceDir', [])+[self.hidserv_dir] + hsdic['HiddenServicePort'] = hsdic.get('HiddenServicePort', [])+[ '80 127.0.0.1:{0}'.format(self.port) ] self.controller.set_options(hsdic2list(hsdic)) diff --git a/onionshare_gui/file_selection.py b/onionshare_gui/file_selection.py index eb6cb36f..e8901403 100644 --- a/onionshare_gui/file_selection.py +++ b/onionshare_gui/file_selection.py @@ -130,7 +130,7 @@ class FileList(QtGui.QListWidget): thresh = 1024.0 if b < thresh: return '{0} B'.format(b) - units = ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'] + units = ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'] u = 0 b /= thresh while b >= thresh: diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index f20c681e..f74b4cc3 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -153,7 +153,7 @@ class OnionShareGui(QtGui.QWidget): self.start_server_finished.emit() 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.start() From aa2b59ec5da442d53ad2585c695da79ff8ac2db3 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Tue, 18 Nov 2014 18:37:17 +0100 Subject: [PATCH 5/9] pep8: 2 spaces before inline comments --- onionshare/onionshare.py | 10 +++++----- onionshare_gui/onionshare_gui.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/onionshare/onionshare.py b/onionshare/onionshare.py index 7e95c26c..57da7115 100644 --- a/onionshare/onionshare.py +++ b/onionshare/onionshare.py @@ -102,7 +102,7 @@ class OnionShare(object): else: args = ['/usr/bin/sudo', '--', '/usr/bin/onionshare'] p = subprocess.Popen(args+[str(self.port)], stderr=subprocess.PIPE, stdout=subprocess.PIPE) - stdout = p.stdout.read(22) # .onion URLs are 22 chars long + stdout = p.stdout.read(22) # .onion URLs are 22 chars long if stdout: self.onion_host = stdout @@ -187,10 +187,10 @@ class OnionShare(object): ready = True sys.stdout.write('{0}\n'.format(strings._('wait_for_hs_yup'))) - except socks.SOCKS5Error: # non-Tails error + except socks.SOCKS5Error: # non-Tails error sys.stdout.write('{0}\n'.format(strings._('wait_for_hs_nope'))) sys.stdout.flush() - except urllib2.HTTPError: # Tails error + except urllib2.HTTPError: # Tails error sys.stdout.write('{0}\n'.format(strings._('wait_for_hs_nope'))) sys.stdout.flush() except KeyboardInterrupt: @@ -282,7 +282,7 @@ def main(): app.cleanup_filenames.append(web.zip_filename) # warn about sending large files over Tor - if web.zip_filesize >= 157286400: # 150mb + if web.zip_filesize >= 157286400: # 150mb print '' print strings._("large_filesize") print '' @@ -292,7 +292,7 @@ def main(): t.daemon = True t.start() - try: # Trap Ctrl-C + try: # Trap Ctrl-C # wait for hs ready = app.wait_for_hs() if not ready: diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index f74b4cc3..f56d8ad2 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -112,7 +112,7 @@ class OnionShareGui(QtGui.QWidget): self.status_bar.showMessage(strings._('gui_starting_server3', True)) # warn about sending large files over Tor - if web.zip_filesize >= 157286400: # 150mb + if web.zip_filesize >= 157286400: # 150mb self.filesize_warning.setText(strings._("large_filesize", True)) self.filesize_warning.show() From 152bc32ba7fe9d3ef711d70b782f5dd3eb9b1843 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Tue, 18 Nov 2014 18:41:45 +0100 Subject: [PATCH 6/9] pep8: no space after {[ or before ]}, reindent --- onionshare/onionshare.py | 2 +- onionshare/socks.py | 46 ++++++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/onionshare/onionshare.py b/onionshare/onionshare.py index 57da7115..6662e980 100644 --- a/onionshare/onionshare.py +++ b/onionshare/onionshare.py @@ -145,7 +145,7 @@ class OnionShare(object): del hsdic['HiddenServicePort'][dropme] hsdic['HiddenServiceDir'] = hsdic.get('HiddenServiceDir', [])+[self.hidserv_dir] hsdic['HiddenServicePort'] = hsdic.get('HiddenServicePort', [])+[ - '80 127.0.0.1:{0}'.format(self.port) ] + '80 127.0.0.1:{0}'.format(self.port)] self.controller.set_options(hsdic2list(hsdic)) diff --git a/onionshare/socks.py b/onionshare/socks.py index 49b96b79..cbfabd06 100644 --- a/onionshare/socks.py +++ b/onionshare/socks.py @@ -105,25 +105,28 @@ class HTTPError(ProxyError): pass -SOCKS4_ERRORS = { 0x5B: "Request rejected or failed", - 0x5C: "Request rejected because SOCKS server cannot connect to identd on the client", - 0x5D: "Request rejected because the client program and identd report different user-ids" - } +SOCKS4_ERRORS = { + 0x5B: "Request rejected or failed", + 0x5C: "Request rejected because SOCKS server cannot connect to identd on the client", + 0x5D: "Request rejected because the client program and identd report different user-ids", +} -SOCKS5_ERRORS = { 0x01: "General SOCKS server failure", - 0x02: "Connection not allowed by ruleset", - 0x03: "Network unreachable", - 0x04: "Host unreachable", - 0x05: "Connection refused", - 0x06: "TTL expired", - 0x07: "Command not supported, or protocol error", - 0x08: "Address type not supported" - } +SOCKS5_ERRORS = { + 0x01: "General SOCKS server failure", + 0x02: "Connection not allowed by ruleset", + 0x03: "Network unreachable", + 0x04: "Host unreachable", + 0x05: "Connection refused", + 0x06: "TTL expired", + 0x07: "Command not supported, or protocol error", + 0x08: "Address type not supported", +} -DEFAULT_PORTS = { SOCKS4: 1080, - SOCKS5: 1080, - HTTP: 8080 - } +DEFAULT_PORTS = { + SOCKS4: 1080, + SOCKS5: 1080, + HTTP: 8080, +} def set_default_proxy(proxy_type=None, addr=None, port=None, rdns=True, username=None, password=None): @@ -205,10 +208,11 @@ class socksocket(socket.socket): self.proxy_sockname = None self.proxy_peername = None - self.proxy_negotiators = { SOCKS4: self._negotiate_SOCKS4, - SOCKS5: self._negotiate_SOCKS5, - HTTP: self._negotiate_HTTP - } + self.proxy_negotiators = { + SOCKS4: self._negotiate_SOCKS4, + SOCKS5: self._negotiate_SOCKS5, + HTTP: self._negotiate_HTTP, + } def _recvall(self, count): """ From f5889d96dd49f821bcba6d9416451881c6814d92 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Tue, 18 Nov 2014 18:43:35 +0100 Subject: [PATCH 7/9] pep8: remove unexpected spaces around "=" in function/method head --- onionshare/onionshare.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onionshare/onionshare.py b/onionshare/onionshare.py index 6662e980..28744d2c 100644 --- a/onionshare/onionshare.py +++ b/onionshare/onionshare.py @@ -225,7 +225,7 @@ def tails_root(): # close hole in firewall on shutdown import signal - def handler(signum = None, frame = None): + def handler(signum=None, frame=None): subprocess.call(['/sbin/iptables', '-D', 'OUTPUT', '-o', 'lo', '-p', 'tcp', '--dport', str(port), '-j', 'ACCEPT']) sys.exit() for sig in [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT]: From 087102bde4ba857b261da269855151ae4beda3a1 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Tue, 18 Nov 2014 18:59:48 +0100 Subject: [PATCH 8/9] pep8: too long lines, reformat lines to < 120 chars. removed redundancy from long_description in setup.py. note: pep8 usually recommends 80 chars, but I find that impractical and unnecessary - it's not 1980 any more when code was edited on 80x25 terminals. i was a bit wondering about onionshare-launcher.py - it does a lot of imports, but does not use the imported names. --- onionshare/onionshare.py | 6 ++++-- onionshare_gui/file_selection.py | 6 ++++-- setup.py | 16 ++++++++++++++-- setup/onionshare-launcher.py | 4 +++- test/onionshare_helpers_test.py | 3 ++- 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/onionshare/onionshare.py b/onionshare/onionshare.py index 28744d2c..d7f13fb8 100644 --- a/onionshare/onionshare.py +++ b/onionshare/onionshare.py @@ -212,7 +212,8 @@ def tails_root(): sys.exit(-1) # open hole in firewall - subprocess.call(['/sbin/iptables', '-I', 'OUTPUT', '-o', 'lo', '-p', 'tcp', '--dport', str(port), '-j', 'ACCEPT']) + subprocess.call(['/sbin/iptables', '-I', 'OUTPUT', '-o', 'lo', + '-p', 'tcp', '--dport', str(port), '-j', 'ACCEPT']) # start hidden service app = OnionShare() @@ -226,7 +227,8 @@ def tails_root(): import signal def handler(signum=None, frame=None): - subprocess.call(['/sbin/iptables', '-D', 'OUTPUT', '-o', 'lo', '-p', 'tcp', '--dport', str(port), '-j', 'ACCEPT']) + subprocess.call(['/sbin/iptables', '-D', 'OUTPUT', '-o', 'lo', + '-p', 'tcp', '--dport', str(port), '-j', 'ACCEPT']) sys.exit() for sig in [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT]: signal.signal(sig, handler) diff --git a/onionshare_gui/file_selection.py b/onionshare_gui/file_selection.py index e8901403..89d2e560 100644 --- a/onionshare_gui/file_selection.py +++ b/onionshare_gui/file_selection.py @@ -188,14 +188,16 @@ class FileSelection(QtGui.QVBoxLayout): self.file_list.update() def add_files(self): - filenames = QtGui.QFileDialog.getOpenFileNames(caption=strings._('gui_choose_files', True), options=QtGui.QFileDialog.ReadOnly) + filenames = QtGui.QFileDialog.getOpenFileNames( + caption=strings._('gui_choose_files', True), options=QtGui.QFileDialog.ReadOnly) if filenames: for filename in filenames: self.file_list.add_file(str(filename)) self.update() def add_dir(self): - filename = QtGui.QFileDialog.getExistingDirectory(caption=strings._('gui_choose_folder', True), options=QtGui.QFileDialog.ReadOnly) + filename = QtGui.QFileDialog.getExistingDirectory( + caption=strings._('gui_choose_folder', True), options=QtGui.QFileDialog.ReadOnly) if filename: self.file_list.add_file(str(filename)) self.update() diff --git a/setup.py b/setup.py index 1ef27ccc..6e797197 100644 --- a/setup.py +++ b/setup.py @@ -38,11 +38,23 @@ def file_list(path): version = open('version').read().strip() +description = ( + """OnionShare lets you securely and anonymously share a file of any size with someone. """ + """It works by starting a web server, making it accessible as a Tor hidden service, """ + """and generating an unguessable URL to access and download the file.""") + +long_description = description + " " + ( + """It doesn't require setting up a server on the internet somewhere or using a third """ + """party filesharing service. You host the file on your own computer and use a Tor """ + """hidden service to make it temporarily accessible over the internet. The other user """ + """just needs to use Tor Browser to download the file from you.""" +) + setup( name='onionshare', version=version, - description='OnionShare lets you securely and anonymously share a file of any size with someone. It works by starting a web server, making it accessible as a Tor hidden service, and generating an unguessable URL to access and download the file.', - long_description="""OnionShare lets you securely and anonymously share a file of any size with someone. It works by starting a web server, making it accessible as a Tor hidden service, and generating an unguessable URL to access and download the file. It doesn't require setting up a server on the internet somewhere or using a third party filesharing service. You host the file on your own computer and use a Tor hidden service to make it temporarily accessible over the internet. The other user just needs to use Tor Browser to download the file from you.""", + description=description, + long_description=long_description, author='Micah Lee', author_email='micah@micahflee.com', url='https://github.com/micahflee/onionshare', diff --git a/setup/onionshare-launcher.py b/setup/onionshare-launcher.py index fe3a4245..6a6a1627 100644 --- a/setup/onionshare-launcher.py +++ b/setup/onionshare-launcher.py @@ -18,7 +18,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ from __future__ import division -import os, sys, subprocess, time, hashlib, platform, json, locale, socket, argparse, Queue, inspect, base64, random, functools, logging, ctypes, hmac, shutil +import os, sys, subprocess, time, hashlib, platform, json, locale, socket +import argparse, Queue, inspect, base64, random, functools, logging, ctypes +import hmac, shutil from itertools import izip import stem, stem.control, flask from PyQt4 import QtCore, QtGui diff --git a/test/onionshare_helpers_test.py b/test/onionshare_helpers_test.py index 1c7c42d2..ab21b9e6 100644 --- a/test/onionshare_helpers_test.py +++ b/test/onionshare_helpers_test.py @@ -24,7 +24,8 @@ import test_helpers def test_get_platform_on_tails(): """get_platform() returns 'Tails' when hostname is 'amnesia'""" - helpers.platform.uname = lambda: ('Linux', 'amnesia', '3.14-1-amd64', '#1 SMP Debian 3.14.4-1 (2014-05-13)', 'x86_64', '') + helpers.platform.uname = lambda: ('Linux', 'amnesia', '3.14-1-amd64', + '#1 SMP Debian 3.14.4-1 (2014-05-13)', 'x86_64', '') assert helpers.get_platform() == 'Tails' From b7a0293470fc43a6bf4138123d83fd50f6d30093 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Tue, 18 Nov 2014 19:03:31 +0100 Subject: [PATCH 9/9] pep8: remove empty lines at EOF --- test/onionshare_helpers_test.py | 1 - test/onionshare_strings_test.py | 1 - test/onionshare_web_test.py | 2 -- test/test_helpers.py | 2 -- 4 files changed, 6 deletions(-) diff --git a/test/onionshare_helpers_test.py b/test/onionshare_helpers_test.py index ab21b9e6..a20e3e9a 100644 --- a/test/onionshare_helpers_test.py +++ b/test/onionshare_helpers_test.py @@ -33,4 +33,3 @@ def test_get_platform_returns_platform_system(): """get_platform() returns platform.system() when ONIONSHARE_PLATFORM is not defined""" helpers.platform.system = lambda: 'Sega Saturn' assert helpers.get_platform() == 'Sega Saturn' - diff --git a/test/onionshare_strings_test.py b/test/onionshare_strings_test.py index ab215e0f..a3981a78 100644 --- a/test/onionshare_strings_test.py +++ b/test/onionshare_strings_test.py @@ -39,4 +39,3 @@ def test_load_strings_loads_other_languages(): locale.getdefaultlocale = lambda: ('fr_FR', 'UTF-8') strings.load_strings("fr") assert strings._('wait_for_hs') == "En attente du HS:" - diff --git a/test/onionshare_web_test.py b/test/onionshare_web_test.py index 54c4872f..cb28e76e 100644 --- a/test/onionshare_web_test.py +++ b/test/onionshare_web_test.py @@ -33,5 +33,3 @@ def test_generate_slug_characters(): return all(char in b32_alphabet for char in string) assert is_b32(web.slug) - - diff --git a/test/test_helpers.py b/test/test_helpers.py index cab2dd34..a5141b30 100644 --- a/test/test_helpers.py +++ b/test/test_helpers.py @@ -37,5 +37,3 @@ def write_tempfile(text): f.write(text) f.close() return path - -