diff --git a/onionshare/common.py b/onionshare/common.py index 176c7931..a2cc4b7d 100644 --- a/onionshare/common.py +++ b/onionshare/common.py @@ -20,7 +20,6 @@ along with this program. If not, see . import base64 import hashlib import inspect -import math import os import platform import random @@ -146,14 +145,14 @@ def human_readable_filesize(b): """ thresh = 1024.0 if b < thresh: - return '{0:.1f} B'.format(b) - units = ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'] + return '{:.1f} B'.format(b) + units = ('KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB') u = 0 b /= thresh while b >= thresh: b /= thresh u += 1 - return '{0:.1f} {1:s}'.format(round(b, 1), units[u]) + return '{:.1f} {}'.format(b, units[u]) def format_seconds(seconds): diff --git a/onionshare/onion.py b/onionshare/onion.py index efcd7ae2..aedd98c2 100644 --- a/onionshare/onion.py +++ b/onionshare/onion.py @@ -433,6 +433,13 @@ class Onion(object): self.stealth = False self.service_id = None + try: + # Delete the temporary tor data directory + self.tor_data_directory.cleanup() + except AttributeError: + # Skip if cleanup was somehow run before connect + pass + def get_tor_socks_port(self): """ Returns a (address, port) tuple for the Tor SOCKS port diff --git a/onionshare/settings.py b/onionshare/settings.py index 18e7dd26..408c8bdc 100644 --- a/onionshare/settings.py +++ b/onionshare/settings.py @@ -18,10 +18,13 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ -import platform, os, json +import json +import os +import platform from . import strings, common + class Settings(object): """ This class stores all of the settings for OnionShare, specifically for how @@ -95,7 +98,7 @@ class Settings(object): try: common.log('Settings', 'load', 'Trying to load {}'.format(self.filename)) with open(self.filename, 'r') as f: - self._settings = json.loads(f.read()) + self._settings = json.load(f) self.fill_in_defaults() except: pass diff --git a/onionshare/strings.py b/onionshare/strings.py index 9b26b4b1..7a1f08a5 100644 --- a/onionshare/strings.py +++ b/onionshare/strings.py @@ -17,17 +17,19 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ -import json, locale, os +import json +import locale +import os strings = {} + def load_strings(common, default="en"): """ Loads translated strings and fallback to English if the translation does not exist. """ global strings - p = common.get_platform() # find locale dir locale_dir = common.get_resource_path('locale') @@ -37,10 +39,9 @@ def load_strings(common, default="en"): for filename in os.listdir(locale_dir): abs_filename = os.path.join(locale_dir, filename) lang, ext = os.path.splitext(filename) - if abs_filename.endswith('.json'): + if ext == '.json': with open(abs_filename, encoding='utf-8') as f: - lang_json = f.read() - translations[lang] = json.loads(lang_json) + translations[lang] = json.load(f) strings = translations[default] lc, enc = locale.getdefaultlocale() diff --git a/onionshare/web.py b/onionshare/web.py index aec86bf4..1d8237da 100644 --- a/onionshare/web.py +++ b/onionshare/web.py @@ -17,12 +17,22 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ + +import hmac +import logging +import mimetypes +import os +import queue +import socket +import sys +import tempfile from distutils.version import StrictVersion as Version -import queue, mimetypes, platform, os, sys, socket, logging, hmac from urllib.request import urlopen -from flask import Flask, Response, request, render_template_string, abort, make_response -from flask import __version__ as flask_version +from flask import ( + Flask, Response, request, render_template_string, abort, make_response, + __version__ as flask_version +) from . import strings, common @@ -56,6 +66,7 @@ security_headers = [ ('Server', 'OnionShare') ] + def set_file_info(filenames, processed_size_callback=None): """ Using the list of filenames being shared, fill in details that the web @@ -115,6 +126,8 @@ def add_request(request_type, path, data=None): slug = None + + def generate_slug(): global slug slug = common.build_slug() @@ -123,12 +136,16 @@ download_count = 0 error404_count = 0 stay_open = False + + def set_stay_open(new_stay_open): """ Set stay_open variable. """ global stay_open stay_open = new_stay_open + + def get_stay_open(): """ Get stay_open variable. @@ -138,6 +155,8 @@ def get_stay_open(): # Are we running in GUI mode? gui_mode = False + + def set_gui_mode(): """ Tell the web service that we're running in GUI mode @@ -145,21 +164,19 @@ def set_gui_mode(): global gui_mode gui_mode = True + def debug_mode(): """ Turn on debugging mode, which will log flask errors to a debug file. """ - if platform.system() == 'Windows': - temp_dir = os.environ['Temp'].replace('\\', '/') - else: - temp_dir = '/tmp/' - - log_handler = logging.FileHandler('{0:s}/onionshare_server.log'.format(temp_dir)) + temp_dir = tempfile.gettempdir() + log_handler = logging.FileHandler( + os.path.join(temp_dir, 'onionshare_server.log')) log_handler.setLevel(logging.WARNING) app.logger.addHandler(log_handler) -def check_slug_candidate(slug_candidate, slug_compare = None): - global slug + +def check_slug_candidate(slug_candidate, slug_compare=None): if not slug_compare: slug_compare = slug if not hmac.compare_digest(slug_compare, slug_candidate): @@ -170,6 +187,7 @@ def check_slug_candidate(slug_candidate, slug_compare = None): # one download at a time. download_in_progress = False + @app.route("/") def index(slug_candidate): """ @@ -185,7 +203,7 @@ def index(slug_candidate): deny_download = not stay_open and download_in_progress if deny_download: r = make_response(render_template_string(open(common.get_resource_path('html/denied.html')).read())) - for header,value in security_headers: + for header, value in security_headers: r.headers.set(header, value) return r @@ -198,15 +216,17 @@ def index(slug_candidate): filename=os.path.basename(zip_filename), filesize=zip_filesize, filesize_human=common.human_readable_filesize(zip_filesize))) - for header,value in security_headers: + for header, value in security_headers: r.headers.set(header, value) return r + # 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 # used to tell the download function that the client is canceling the download. client_cancel = False + @app.route("//download") def download(slug_candidate): """ @@ -332,10 +352,11 @@ def page_not_found(e): print(strings._('error_rate_limit')) r = make_response(render_template_string(open(common.get_resource_path('html/404.html')).read())) - for header,value in security_headers: + for header, value in security_headers: r.headers.set(header, value) return r + # shutting down the server only works within the context of flask, so the easiest way to do it is over http shutdown_slug = common.random_string(16)