From af637bc697686b1090d6d5d5791675d4b21e0c74 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 25 Nov 2018 15:13:15 -0800 Subject: Adding a .entitlements file to begin testing macOS sandbox --- install/OnionShare.entitlements | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 install/OnionShare.entitlements diff --git a/install/OnionShare.entitlements b/install/OnionShare.entitlements new file mode 100644 index 00000000..fa6a9141 --- /dev/null +++ b/install/OnionShare.entitlements @@ -0,0 +1,16 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + com.apple.security.network.client + + com.apple.security.temporary-exception.files.home-relative-path.read-write + + /OnionShare + + + -- cgit v1.2.3-54-g00ecf From dac480f212b00d31a1c3ff2ca367dd1e86c5d028 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 25 Nov 2018 15:14:29 -0800 Subject: Use entitlements file when codesigning for macOS --- install/build_osx.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/build_osx.sh b/install/build_osx.sh index f6b27d9b..ad096139 100755 --- a/install/build_osx.sh +++ b/install/build_osx.sh @@ -25,7 +25,7 @@ if [ "$1" = "--release" ]; then IDENTITY_NAME_INSTALLER="Developer ID Installer: Micah Lee" echo "Codesigning the app bundle" - codesign --deep -s "$IDENTITY_NAME_APPLICATION" "$APP_PATH" + codesign --deep -s "$IDENTITY_NAME_APPLICATION" "$APP_PATH" --entitlements "$ROOT/install/OnionShare.entitlements" echo "Creating an installer" productbuild --sign "$IDENTITY_NAME_INSTALLER" --component "$APP_PATH" /Applications "$PKG_PATH" -- cgit v1.2.3-54-g00ecf From 0794d7fb9040e3ecf599202c27c191215a795f37 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 25 Nov 2018 15:52:36 -0800 Subject: Split entitlements files into child and parent, and try using them both --- install/OnionShare.entitlements | 16 ---------------- install/build_osx.sh | 5 ++++- install/macos_sandbox/child.plist | 10 ++++++++++ install/macos_sandbox/parent.plist | 16 ++++++++++++++++ 4 files changed, 30 insertions(+), 17 deletions(-) delete mode 100644 install/OnionShare.entitlements create mode 100644 install/macos_sandbox/child.plist create mode 100644 install/macos_sandbox/parent.plist diff --git a/install/OnionShare.entitlements b/install/OnionShare.entitlements deleted file mode 100644 index fa6a9141..00000000 --- a/install/OnionShare.entitlements +++ /dev/null @@ -1,16 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.files.user-selected.read-only - - com.apple.security.network.client - - com.apple.security.temporary-exception.files.home-relative-path.read-write - - /OnionShare - - - diff --git a/install/build_osx.sh b/install/build_osx.sh index ad096139..010e3edb 100755 --- a/install/build_osx.sh +++ b/install/build_osx.sh @@ -23,9 +23,12 @@ if [ "$1" = "--release" ]; then PKG_PATH="$ROOT/dist/OnionShare.pkg" IDENTITY_NAME_APPLICATION="Developer ID Application: Micah Lee" IDENTITY_NAME_INSTALLER="Developer ID Installer: Micah Lee" + ENTITLEMENTS_CHILD_PATH="$ROOT/install/macos_sandbox/child.plist" + ENTITLEMENTS_PARENT_PATH="$ROOT/install/macos_sandbox/parent.plist" echo "Codesigning the app bundle" - codesign --deep -s "$IDENTITY_NAME_APPLICATION" "$APP_PATH" --entitlements "$ROOT/install/OnionShare.entitlements" + codesign --deep -s "$IDENTITY_NAME_APPLICATION" -f --entitlements "$ENTITLEMENTS_CHILD_PATH" "$APP_PATH" + codesign -s "$IDENTITY_NAME_APPLICATION" -f --entitlements "$ENTITLEMENTS_PARENT_PATH" "$APP_PATH" echo "Creating an installer" productbuild --sign "$IDENTITY_NAME_INSTALLER" --component "$APP_PATH" /Applications "$PKG_PATH" diff --git a/install/macos_sandbox/child.plist b/install/macos_sandbox/child.plist new file mode 100644 index 00000000..06d88f66 --- /dev/null +++ b/install/macos_sandbox/child.plist @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.inherit + + + diff --git a/install/macos_sandbox/parent.plist b/install/macos_sandbox/parent.plist new file mode 100644 index 00000000..ceecd30a --- /dev/null +++ b/install/macos_sandbox/parent.plist @@ -0,0 +1,16 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.files.user-selected.read-only + + com.apple.security.temporary-exception.files.home-relative-path.read-write + + /OnionShare + + + -- cgit v1.2.3-54-g00ecf From d8b873a20825404ea8b9c6727680911b2e19e910 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 25 Nov 2018 16:15:27 -0800 Subject: Create a group container for macOS sandbox, and on Mac put the Tor data dir in it --- install/macos_sandbox/parent.plist | 6 ++++++ onionshare/onion.py | 7 ++++++- onionshare/settings.py | 6 +----- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/install/macos_sandbox/parent.plist b/install/macos_sandbox/parent.plist index ceecd30a..6d557cf0 100644 --- a/install/macos_sandbox/parent.plist +++ b/install/macos_sandbox/parent.plist @@ -4,6 +4,8 @@ com.apple.security.app-sandbox + com.apple.security.network.server + com.apple.security.network.client com.apple.security.files.user-selected.read-only @@ -12,5 +14,9 @@ /OnionShare + com.apple.security.application-groups + + com.micahflee.onionshare + diff --git a/onionshare/onion.py b/onionshare/onion.py index 6066f059..f9f551c4 100644 --- a/onionshare/onion.py +++ b/onionshare/onion.py @@ -166,7 +166,12 @@ class Onion(object): raise BundledTorNotSupported(strings._('settings_error_bundled_tor_not_supported')) # Create a torrc for this session - self.tor_data_directory = tempfile.TemporaryDirectory() + if self.common.platform == 'Darwin': + group_container_dir = os.path.expanduser('~/Library/Group Containers/com.micahflee.onionshare') + os.makedirs(group_container_dir, exist_ok=True) + self.tor_data_directory = tempfile.TemporaryDirectory(dir=group_container_dir) + else: + self.tor_data_directory = tempfile.TemporaryDirectory() if self.common.platform == 'Windows': # Windows needs to use network ports, doesn't support unix sockets diff --git a/onionshare/settings.py b/onionshare/settings.py index ed827cbd..4a056989 100644 --- a/onionshare/settings.py +++ b/onionshare/settings.py @@ -163,11 +163,7 @@ class Settings(object): Save settings to file. """ self.common.log('Settings', 'save') - - try: - os.makedirs(os.path.dirname(self.filename)) - except: - pass + os.makedirs(os.path.dirname(self.filename), exist_ok=True) open(self.filename, 'w').write(json.dumps(self._settings)) self.common.log('Settings', 'save', 'Settings saved in {}'.format(self.filename)) -- cgit v1.2.3-54-g00ecf From 845d7f85647b8f2cb5757e86b3269657bf371b53 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 25 Nov 2018 16:26:54 -0800 Subject: Display tor_data_directory as debug log --- onionshare/onion.py | 1 + 1 file changed, 1 insertion(+) diff --git a/onionshare/onion.py b/onionshare/onion.py index f9f551c4..ec81a894 100644 --- a/onionshare/onion.py +++ b/onionshare/onion.py @@ -170,6 +170,7 @@ class Onion(object): group_container_dir = os.path.expanduser('~/Library/Group Containers/com.micahflee.onionshare') os.makedirs(group_container_dir, exist_ok=True) self.tor_data_directory = tempfile.TemporaryDirectory(dir=group_container_dir) + self.common.log('Onion', 'connect', 'tor_data_directory={}'.format(self.tor_data_directory)) else: self.tor_data_directory = tempfile.TemporaryDirectory() -- cgit v1.2.3-54-g00ecf From 2cbe8979abe549150513cd7489cf3e2e7b348471 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 25 Nov 2018 16:50:20 -0800 Subject: Make macOS use Tor control ports instead of unix sockets to connect to the Tor controller --- install/pyinstaller.spec | 1 - onionshare/onion.py | 41 +++++++++++++++++++++-------------------- share/torrc_template | 1 - share/torrc_template-windows | 9 --------- 4 files changed, 21 insertions(+), 31 deletions(-) delete mode 100644 share/torrc_template-windows diff --git a/install/pyinstaller.spec b/install/pyinstaller.spec index 6811997b..24664bf9 100644 --- a/install/pyinstaller.spec +++ b/install/pyinstaller.spec @@ -15,7 +15,6 @@ a = Analysis( ('../share/torrc_template', 'share'), ('../share/torrc_template-obfs4', 'share'), ('../share/torrc_template-meek_lite_azure', 'share'), - ('../share/torrc_template-windows', 'share'), ('../share/images/*', 'share/images'), ('../share/locale/*', 'share/locale'), ('../share/static/*', 'share/static'), diff --git a/onionshare/onion.py b/onionshare/onion.py index ec81a894..4a94f2ce 100644 --- a/onionshare/onion.py +++ b/onionshare/onion.py @@ -170,36 +170,36 @@ class Onion(object): group_container_dir = os.path.expanduser('~/Library/Group Containers/com.micahflee.onionshare') os.makedirs(group_container_dir, exist_ok=True) self.tor_data_directory = tempfile.TemporaryDirectory(dir=group_container_dir) - self.common.log('Onion', 'connect', 'tor_data_directory={}'.format(self.tor_data_directory)) + self.common.log('Onion', 'connect', 'tor_data_directory={}'.format(self.tor_data_directory.name)) else: self.tor_data_directory = tempfile.TemporaryDirectory() - if self.common.platform == 'Windows': - # Windows needs to use network ports, doesn't support unix sockets - torrc_template = open(self.common.get_resource_path('torrc_template-windows')).read() + # Create the torrc + with open(self.common.get_resource_path('torrc_template')) as f: + torrc_template = f.read() + self.tor_cookie_auth_file = os.path.join(self.tor_data_directory.name, 'cookie') + try: + self.tor_socks_port = self.common.get_available_port(1000, 65535) + except: + raise OSError(strings._('no_available_port')) + self.tor_torrc = os.path.join(self.tor_data_directory.name, 'torrc') + + if self.common.platform == 'Windows' or self.common.platform == "Darwin": + # Windows doesn't support unix sockets, so it must use a network port. + # macOS can't use unix sockets either because socket filenames are limited to + # 100 chars, and the macOS sandbox forces us to put the socket file in a place + # with a really long path. + torrc_template += 'ControlPort {{control_port}}\n' try: self.tor_control_port = self.common.get_available_port(1000, 65535) except: raise OSError(strings._('no_available_port')) self.tor_control_socket = None - self.tor_cookie_auth_file = os.path.join(self.tor_data_directory.name, 'cookie') - try: - self.tor_socks_port = self.common.get_available_port(1000, 65535) - except: - raise OSError(strings._('no_available_port')) - self.tor_torrc = os.path.join(self.tor_data_directory.name, 'torrc') else: - # Linux, Mac and BSD can use unix sockets - with open(self.common.get_resource_path('torrc_template')) as f: - torrc_template = f.read() + # Linux and BSD can use unix sockets + torrc_template += 'ControlSocket {{control_socket}}\n' 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') - try: - self.tor_socks_port = self.common.get_available_port(1000, 65535) - except: - raise OSError(strings._('no_available_port')) - self.tor_torrc = os.path.join(self.tor_data_directory.name, 'torrc') torrc_template = torrc_template.replace('{{data_directory}}', self.tor_data_directory.name) torrc_template = torrc_template.replace('{{control_port}}', str(self.tor_control_port)) @@ -208,6 +208,7 @@ class Onion(object): torrc_template = torrc_template.replace('{{geo_ip_file}}', self.tor_geo_ip_file_path) torrc_template = torrc_template.replace('{{geo_ipv6_file}}', self.tor_geo_ipv6_file_path) torrc_template = torrc_template.replace('{{socks_port}}', str(self.tor_socks_port)) + with open(self.tor_torrc, 'w') as f: f.write(torrc_template) @@ -246,7 +247,7 @@ class Onion(object): # Connect to the controller try: - if self.common.platform == 'Windows': + if self.common.platform == 'Windows' or self.common.platform == "Darwin": self.c = Controller.from_port(port=self.tor_control_port) self.c.authenticate() else: diff --git a/share/torrc_template b/share/torrc_template index 464adf32..8ac9e1ef 100644 --- a/share/torrc_template +++ b/share/torrc_template @@ -1,6 +1,5 @@ DataDirectory {{data_directory}} SocksPort {{socks_port}} -ControlSocket {{control_socket}} CookieAuthentication 1 CookieAuthFile {{cookie_auth_file}} AvoidDiskWrites 1 diff --git a/share/torrc_template-windows b/share/torrc_template-windows deleted file mode 100644 index 38a5bf1e..00000000 --- a/share/torrc_template-windows +++ /dev/null @@ -1,9 +0,0 @@ -DataDirectory {{data_directory}} -SocksPort {{socks_port}} -ControlPort {{control_port}} -CookieAuthentication 1 -CookieAuthFile {{cookie_auth_file}} -AvoidDiskWrites 1 -Log notice stdout -GeoIPFile {{geo_ip_file}} -GeoIPv6File {{geo_ipv6_file}} -- cgit v1.2.3-54-g00ecf From 66e50c96b8f63e82edd1bc0a69cc6f62f3ec1728 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 25 Nov 2018 17:00:02 -0800 Subject: Fix indenting in entitlements plist, and give OnionShare read-only access to Tor Browser's data, so it can optionally use Tor Browser's tor --- install/macos_sandbox/parent.plist | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/install/macos_sandbox/parent.plist b/install/macos_sandbox/parent.plist index 6d557cf0..0e4505d5 100644 --- a/install/macos_sandbox/parent.plist +++ b/install/macos_sandbox/parent.plist @@ -10,13 +10,17 @@ com.apple.security.files.user-selected.read-only + com.apple.security.temporary-exception.files.home-relative-path.read-only + + /Library/Application Support/TorBrowser-Data/Tor/control_auth_cookie + com.apple.security.temporary-exception.files.home-relative-path.read-write - /OnionShare - + /OnionShare + com.apple.security.application-groups - - com.micahflee.onionshare - + + com.micahflee.onionshare + -- cgit v1.2.3-54-g00ecf From 49340321445e9b5dcbcded52f72dd16b02dc7a39 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 25 Nov 2018 17:17:56 -0800 Subject: Make tor data dir always be a tempdir inside OnionShare's data dir --- onionshare/common.py | 17 +++++++++++++++++ onionshare/onion.py | 9 ++------- onionshare/settings.py | 14 +------------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/onionshare/common.py b/onionshare/common.py index ffa6529f..6b3d85c4 100644 --- a/onionshare/common.py +++ b/onionshare/common.py @@ -123,6 +123,23 @@ class Common(object): return (tor_path, tor_geo_ip_file_path, tor_geo_ipv6_file_path, obfs4proxy_file_path) + def build_data_dir(self): + """ + Returns the path of the OnionShare data directory. + """ + if self.platform == 'Windows': + try: + appdata = os.environ['APPDATA'] + return '{}\\OnionShare'.format(appdata) + except: + # If for some reason we don't have the 'APPDATA' environment variable + # (like running tests in Linux while pretending to be in Windows) + return os.path.expanduser('~/.config/onionshare') + elif self.platform == 'Darwin': + return os.path.expanduser('~/Library/Application Support/OnionShare') + else: + return os.path.expanduser('~/.config/onionshare') + def build_slug(self): """ Returns a random string made from two words from the wordlist, such as "deter-trig". diff --git a/onionshare/onion.py b/onionshare/onion.py index 4a94f2ce..7b4f1daa 100644 --- a/onionshare/onion.py +++ b/onionshare/onion.py @@ -166,13 +166,8 @@ class Onion(object): raise BundledTorNotSupported(strings._('settings_error_bundled_tor_not_supported')) # Create a torrc for this session - if self.common.platform == 'Darwin': - group_container_dir = os.path.expanduser('~/Library/Group Containers/com.micahflee.onionshare') - os.makedirs(group_container_dir, exist_ok=True) - self.tor_data_directory = tempfile.TemporaryDirectory(dir=group_container_dir) - self.common.log('Onion', 'connect', 'tor_data_directory={}'.format(self.tor_data_directory.name)) - else: - self.tor_data_directory = tempfile.TemporaryDirectory() + self.tor_data_directory = tempfile.TemporaryDirectory(dir=self.common.build_data_dir()) + self.common.log('Onion', 'connect', 'tor_data_directory={}'.format(self.tor_data_directory.name)) # Create the torrc with open(self.common.get_resource_path('torrc_template')) as f: diff --git a/onionshare/settings.py b/onionshare/settings.py index 4a056989..058557e9 100644 --- a/onionshare/settings.py +++ b/onionshare/settings.py @@ -120,19 +120,7 @@ class Settings(object): """ Returns the path of the settings file. """ - p = platform.system() - if p == 'Windows': - try: - appdata = os.environ['APPDATA'] - return '{}\\OnionShare\\onionshare.json'.format(appdata) - except: - # If for some reason we don't have the 'APPDATA' environment variable - # (like running tests in Linux while pretending to be in Windows) - return os.path.expanduser('~/.config/onionshare/onionshare.json') - elif p == 'Darwin': - return os.path.expanduser('~/Library/Application Support/OnionShare/onionshare.json') - else: - return os.path.expanduser('~/.config/onionshare/onionshare.json') + return os.path.join(self.common.build_data_dir(), 'onionshare.json') def build_default_downloads_dir(self): """ -- cgit v1.2.3-54-g00ecf From 29d2518911e79f13a5b359f1a42919634ec906e7 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 25 Nov 2018 17:18:55 -0800 Subject: Add comments to entitlements file, and remove the application group --- install/macos_sandbox/parent.plist | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/install/macos_sandbox/parent.plist b/install/macos_sandbox/parent.plist index 0e4505d5..35b4447c 100644 --- a/install/macos_sandbox/parent.plist +++ b/install/macos_sandbox/parent.plist @@ -4,23 +4,30 @@ com.apple.security.app-sandbox + com.apple.security.network.server com.apple.security.network.client - com.apple.security.files.user-selected.read-only + + com.apple.security.files.user-selected.read-write + + com.apple.security.temporary-exception.files.absolute-path.read-only + + /private/etc/apache2/mime.types + + com.apple.security.temporary-exception.files.home-relative-path.read-only /Library/Application Support/TorBrowser-Data/Tor/control_auth_cookie + com.apple.security.temporary-exception.files.home-relative-path.read-write /OnionShare - com.apple.security.application-groups - - com.micahflee.onionshare - -- cgit v1.2.3-54-g00ecf From 250dbf91993a4a90a19c33cbff88520ac8660753 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 25 Nov 2018 17:34:06 -0800 Subject: Make sure downloads_dir exists after loading settings --- onionshare/settings.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/onionshare/settings.py b/onionshare/settings.py index 058557e9..41fcc536 100644 --- a/onionshare/settings.py +++ b/onionshare/settings.py @@ -146,6 +146,12 @@ class Settings(object): except: pass + # Make sure downloads_dir exists + try: + os.makedirs(self.get('downloads_dir'), exist_ok=True) + except: + pass + def save(self): """ Save settings to file. -- cgit v1.2.3-54-g00ecf From 33bd7b4a80738e50dbb810086120635db18876e2 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 25 Nov 2018 17:48:11 -0800 Subject: Build downloads_dir a different way in macOS, so it's correct despite the sandbox --- onionshare/settings.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/onionshare/settings.py b/onionshare/settings.py index 41fcc536..ca3fccfa 100644 --- a/onionshare/settings.py +++ b/onionshare/settings.py @@ -22,6 +22,7 @@ import json import os import platform import locale +import pwd from . import strings @@ -128,7 +129,13 @@ class Settings(object): """ # TODO: Test in Windows, though it looks like it should work # https://docs.python.org/3/library/os.path.html#os.path.expanduser - return os.path.expanduser('~/OnionShare') + if self.common.platform == "Darwin": + # We can't use os.path.expanduser in macOS because in the sandbox it + # returns the path to the sandboxed homedir + real_homedir = pwd.getpwuid(os.getuid()).pw_dir + return os.path.join(real_homedir, 'OnionShare') + else: + return os.path.expanduser('~/OnionShare') def load(self): """ -- cgit v1.2.3-54-g00ecf From db93734ed29cb37dece94ea26f9ffbe7574d82b7 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 25 Nov 2018 18:00:04 -0800 Subject: Add trailing slash to ~/OnionShare/ in entitlements file, so the sandbox knows it's a directory and not a file --- install/macos_sandbox/parent.plist | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/install/macos_sandbox/parent.plist b/install/macos_sandbox/parent.plist index 35b4447c..3929abe9 100644 --- a/install/macos_sandbox/parent.plist +++ b/install/macos_sandbox/parent.plist @@ -2,32 +2,38 @@ + com.apple.security.app-sandbox - + + com.apple.security.network.server com.apple.security.network.client + com.apple.security.files.user-selected.read-write + com.apple.security.temporary-exception.files.absolute-path.read-only /private/etc/apache2/mime.types + com.apple.security.temporary-exception.files.home-relative-path.read-only /Library/Application Support/TorBrowser-Data/Tor/control_auth_cookie + com.apple.security.temporary-exception.files.home-relative-path.read-write - /OnionShare + /OnionShare/ -- cgit v1.2.3-54-g00ecf From 01baf3d6fde55a83368a85ace8632079ceb61c25 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 25 Nov 2018 19:10:19 -0800 Subject: Fix test for Windows settings path --- tests/test_onionshare_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_onionshare_settings.py b/tests/test_onionshare_settings.py index 371b2d27..42bf7f12 100644 --- a/tests/test_onionshare_settings.py +++ b/tests/test_onionshare_settings.py @@ -176,7 +176,7 @@ class TestSettings: platform_windows): monkeypatch.setenv('APPDATA', 'C:') obj = settings.Settings(common.Common()) - assert obj.filename == 'C:\\OnionShare\\onionshare.json' + assert obj.filename.replace('/', '\\') == 'C:\\OnionShare\\onionshare.json' def test_set_custom_bridge(self, settings_obj): settings_obj.set('tor_bridges_use_custom_bridges', 'Bridge 45.3.20.65:9050 21300AD88890A49C429A6CB9959CFD44490A8F6E') -- cgit v1.2.3-54-g00ecf From 3a0c8dc32317d4b66230663c1c3a40f6969d9275 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Tue, 27 Nov 2018 12:10:16 -0800 Subject: In macOS, split "Add" button into "Add Files" and "Add Folder" buttons --- onionshare_gui/mode/share_mode/__init__.py | 2 +- onionshare_gui/mode/share_mode/file_selection.py | 51 +++++++++++++++++++++--- onionshare_gui/widgets.py | 4 ++ share/locale/en.json | 2 + 4 files changed, 52 insertions(+), 7 deletions(-) diff --git a/onionshare_gui/mode/share_mode/__init__.py b/onionshare_gui/mode/share_mode/__init__.py index 436d42f7..0cc00f92 100644 --- a/onionshare_gui/mode/share_mode/__init__.py +++ b/onionshare_gui/mode/share_mode/__init__.py @@ -47,7 +47,7 @@ class ShareMode(Mode): self.web = Web(self.common, True, 'share') # File selection - self.file_selection = FileSelection(self.common) + self.file_selection = FileSelection(self.common, self) if self.filenames: for filename in self.filenames: self.file_selection.file_list.add_file(filename) diff --git a/onionshare_gui/mode/share_mode/file_selection.py b/onionshare_gui/mode/share_mode/file_selection.py index ec3b5ea5..0d4229fe 100644 --- a/onionshare_gui/mode/share_mode/file_selection.py +++ b/onionshare_gui/mode/share_mode/file_selection.py @@ -288,10 +288,11 @@ class FileSelection(QtWidgets.QVBoxLayout): The list of files and folders in the GUI, as well as buttons to add and delete the files and folders. """ - def __init__(self, common): + def __init__(self, common, parent): super(FileSelection, self).__init__() self.common = common + self.parent = parent self.server_on = False @@ -302,13 +303,25 @@ class FileSelection(QtWidgets.QVBoxLayout): self.file_list.files_updated.connect(self.update) # Buttons - self.add_button = QtWidgets.QPushButton(strings._('gui_add')) - self.add_button.clicked.connect(self.add) + if self.common.platform == 'Darwin': + # The macOS sandbox makes it so the Mac version needs separate add files + # and folders buttons, in order to use native file selection dialogs + self.add_files_button = QtWidgets.QPushButton(strings._('gui_add_files')) + self.add_files_button.clicked.connect(self.add_files) + self.add_folder_button = QtWidgets.QPushButton(strings._('gui_add_folder')) + self.add_folder_button.clicked.connect(self.add_folder) + else: + self.add_button = QtWidgets.QPushButton(strings._('gui_add')) + self.add_button.clicked.connect(self.add) self.delete_button = QtWidgets.QPushButton(strings._('gui_delete')) self.delete_button.clicked.connect(self.delete) button_layout = QtWidgets.QHBoxLayout() button_layout.addStretch() - button_layout.addWidget(self.add_button) + if self.common.platform == 'Darwin': + button_layout.addWidget(self.add_files_button) + button_layout.addWidget(self.add_folder_button) + else: + button_layout.addWidget(self.add_button) button_layout.addWidget(self.delete_button) # Add the widgets @@ -323,10 +336,18 @@ class FileSelection(QtWidgets.QVBoxLayout): """ # All buttons should be hidden if the server is on if self.server_on: - self.add_button.hide() + if self.common.platform == 'Darwin': + self.add_files_button.hide() + self.add_folder_button.hide() + else: + self.add_button.hide() self.delete_button.hide() else: - self.add_button.show() + if self.common.platform == 'Darwin': + self.add_files_button.show() + self.add_folder_button.show() + else: + self.add_button.show() # Delete button should be hidden if item isn't selected if len(self.file_list.selectedItems()) == 0: @@ -349,6 +370,24 @@ class FileSelection(QtWidgets.QVBoxLayout): self.file_list.setCurrentItem(None) self.update() + def add_files(self): + """ + Add files button clicked. + """ + files = QtWidgets.QFileDialog.getOpenFileNames(self.parent, caption=strings._('gui_choose_items')) + filenames = files[0] + for filename in filenames: + self.file_list.add_file(filename) + + def add_folder(self): + """ + Add folder button clicked. + """ + filename = QtWidgets.QFileDialog.getExistingDirectory(self.parent, + caption=strings._('gui_choose_items'), + options=QtWidgets.QFileDialog.ShowDirsOnly) + self.file_list.add_file(filename) + def delete(self): """ Delete button clicked diff --git a/onionshare_gui/widgets.py b/onionshare_gui/widgets.py index eaa5904d..600165aa 100644 --- a/onionshare_gui/widgets.py +++ b/onionshare_gui/widgets.py @@ -44,6 +44,10 @@ class AddFileDialog(QtWidgets.QFileDialog): """ Overridden version of QFileDialog which allows us to select folders as well as, or instead of, files. For adding files/folders to share. + + Note that this dialog can't be used in macOS, only in Windows, Linux, and BSD. + This is because the macOS sandbox requires native dialogs, and this is a Qt5 + dialog. """ def __init__(self, common, *args, **kwargs): QtWidgets.QFileDialog.__init__(self, *args, **kwargs) diff --git a/share/locale/en.json b/share/locale/en.json index b02e522f..438274ef 100644 --- a/share/locale/en.json +++ b/share/locale/en.json @@ -33,6 +33,8 @@ "help_config": "Custom JSON config file location (optional)", "gui_drag_and_drop": "Drag and drop files and folders\nto start sharing", "gui_add": "Add", + "gui_add_files": "Add Files", + "gui_add_folder": "Add Folder", "gui_delete": "Delete", "gui_choose_items": "Choose", "gui_share_start_server": "Start sharing", -- cgit v1.2.3-54-g00ecf From a06bb0878f5a7c0ebf20ceff48f278b9ae5e5e1a Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 16 Dec 2018 17:20:28 -0800 Subject: When enabling debug mode in Web, use common.build_data_dir() to get data dir path --- onionshare/web/web.py | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/onionshare/web/web.py b/onionshare/web/web.py index 21e9cd8f..0f156941 100644 --- a/onionshare/web/web.py +++ b/onionshare/web/web.py @@ -184,19 +184,7 @@ class Web(object): """ Turn on debugging mode, which will log flask errors to a debug file. """ - if self.common.platform == 'Windows': - try: - appdata = os.environ['APPDATA'] - flask_debug_filename = '{}\\OnionShare\\flask_debug.log'.format(appdata) - except: - # If for some reason we don't have the 'APPDATA' environment variable - # (like running tests in Linux while pretending to be in Windows) - flask_debug_filename = os.path.expanduser('~/.config/onionshare/flask_debug.log') - elif self.common.platform == 'Darwin': - flask_debug_filename = os.path.expanduser('~/Library/Application Support/OnionShare/flask_debug.log') - else: - flask_debug_filename = os.path.expanduser('~/.config/onionshare/flask_debug.log') - + flask_debug_filename = os.path.join(self.common.build_data_dir(), 'flask_debug.log') log_handler = logging.FileHandler(flask_debug_filename) log_handler.setLevel(logging.WARNING) self.app.logger.addHandler(log_handler) -- cgit v1.2.3-54-g00ecf From 498fe64617c0b22b1cfbfcccc6f7cbfedfd92bc8 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Tue, 18 Dec 2018 19:39:40 -0800 Subject: Version bump to 2.0.dev1, and updated changelog --- CHANGELOG.md | 9 +++++++++ share/version.txt | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 136dd2b1..9686439e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # OnionShare Changelog +## 2.0 + +* New feature: Receiver mode allows you to receive files with OnionShare, instead of only sending files +* New feature: If you're sharing a single file, don't zip it up +* New feature: macOS sandbox enabled +* New feature: Allow selecting your language from a dropdown +* New translations: TODO fill in for final release +* Several bugfixes + ## 1.3.1 * Updated Tor to 0.2.3.10 diff --git a/share/version.txt b/share/version.txt index 22351bb8..aa8add45 100644 --- a/share/version.txt +++ b/share/version.txt @@ -1 +1 @@ -2.0.dev +2.0.dev1 -- cgit v1.2.3-54-g00ecf From ec5eff5f9de3762aa14e3ca2df72800c10856c2d Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Wed, 19 Dec 2018 11:42:37 -0800 Subject: Tweak the changelog --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9686439e..e437b939 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,11 @@ ## 2.0 * New feature: Receiver mode allows you to receive files with OnionShare, instead of only sending files +* New feature: macOS sandbox is enabled +* New feature: Support for next generation onion services (TODO waiting on Tor release) * New feature: If you're sharing a single file, don't zip it up -* New feature: macOS sandbox enabled * New feature: Allow selecting your language from a dropdown -* New translations: TODO fill in for final release +* New translations: (TODO fill in for final release) * Several bugfixes ## 1.3.1 -- cgit v1.2.3-54-g00ecf From 6e0081cebaf9d02aafc772b3ea11a156c718214b Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Wed, 19 Dec 2018 11:45:31 -0800 Subject: pwd module doesn't exist in Windows --- onionshare/settings.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/onionshare/settings.py b/onionshare/settings.py index a1d96d26..38478dbd 100644 --- a/onionshare/settings.py +++ b/onionshare/settings.py @@ -22,7 +22,12 @@ import json import os import platform import locale -import pwd + +try: + # We only need pwd module in macOS, and it's not available in Windows + import pwd +except: + pass from . import strings -- cgit v1.2.3-54-g00ecf From 391619e6b55345a07421b784c486af53c9726884 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Wed, 19 Dec 2018 11:47:41 -0800 Subject: Update version and size for Windows release --- install/onionshare.nsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/install/onionshare.nsi b/install/onionshare.nsi index f0b28535..3a4c6c2a 100644 --- a/install/onionshare.nsi +++ b/install/onionshare.nsi @@ -3,10 +3,10 @@ !define ABOUTURL "https:\\onionshare.org\" # change these with each release -!define INSTALLSIZE 66537 -!define VERSIONMAJOR 1 -!define VERSIONMINOR 3 -!define VERSIONSTRING "1.3.1" +!define INSTALLSIZE 115186 +!define VERSIONMAJOR 2 +!define VERSIONMINOR 0 +!define VERSIONSTRING "2.0" RequestExecutionLevel admin -- cgit v1.2.3-54-g00ecf