From ca6a4b9235ecda5465244f2ef71cb0bfc3dde765 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Fri, 6 Sep 2013 23:38:24 +0200 Subject: fix license filename --- relnotes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relnotes.txt b/relnotes.txt index 349b430c..7a9696cc 100644 --- a/relnotes.txt +++ b/relnotes.txt @@ -53,7 +53,7 @@ LICENSE You may use Bitmask under the GNU General Public License, version 3 or, at your option, any later version. See the file -"COPYING.GPL" for the terms of the GNU General Public +"LICENSE" for the terms of the GNU General Public License, version 3. In addition, as a special exception, the copyright holders give -- cgit v1.2.3 From b90f6525b13657b6ed845c56d1b8f6a101ce8e33 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Sat, 7 Sep 2013 21:20:02 +0200 Subject: fix repo name in yet another place --- docs/dev/environment.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/dev/environment.rst b/docs/dev/environment.rst index 7ce536f9..5ae3871a 100644 --- a/docs/dev/environment.rst +++ b/docs/dev/environment.rst @@ -13,9 +13,11 @@ Cloning the repo :: - git clone git://leap.se/bitmask + git clone git://leap.se/leap_client git checkout develop +.. XXX change this when repo changes. + Base Dependencies ------------------ Bitmask depends on these libraries: @@ -121,6 +123,10 @@ If you *only* are running bitmask from inside a virtualenv, you will need to cop Missing Authentication agent ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -If you are running a desktop other than gnome or unity, you might get an error saying that you are not running the authentication agent. You can launch it like this:: +If you are using linux and running a desktop other than unity or gnome, you might get an error saying that you are not running the authentication agent. For systems with gnome libraries installed you can launch it like this:: /usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1 & + +or if you are a kde user:: + + /usr/lib/kde4/libexec/polkit-kde-authentication-agent-1 & -- cgit v1.2.3 From 528ed8aa4fbd4550fe41fa6afa96eb6ddcab7d1c Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 5 Sep 2013 17:15:49 -0300 Subject: Improve systray tooltip. --- ...ure-3758_show-eip-and-mx-status-in-systray-tooltip | 2 ++ src/leap/bitmask/gui/statuspanel.py | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 changes/feature-3758_show-eip-and-mx-status-in-systray-tooltip diff --git a/changes/feature-3758_show-eip-and-mx-status-in-systray-tooltip b/changes/feature-3758_show-eip-and-mx-status-in-systray-tooltip new file mode 100644 index 00000000..edbb3ea0 --- /dev/null +++ b/changes/feature-3758_show-eip-and-mx-status-in-systray-tooltip @@ -0,0 +1,2 @@ + o Display the Encrypted Internet and Encrypted Email status in the systray + tooltip. Closes #3758. diff --git a/src/leap/bitmask/gui/statuspanel.py b/src/leap/bitmask/gui/statuspanel.py index 3a91f08e..190bc02f 100644 --- a/src/leap/bitmask/gui/statuspanel.py +++ b/src/leap/bitmask/gui/statuspanel.py @@ -141,6 +141,9 @@ class StatusPanelWidget(QtGui.QWidget): self.hide_status_box() + # set systray tooltip statuses + self._eip_status = self._mx_status = "" + # Set the EIP status icons self.CONNECTING_ICON = None self.CONNECTED_ICON = None @@ -336,6 +339,15 @@ class StatusPanelWidget(QtGui.QWidget): """ leap_assert_type(systray, QtGui.QSystemTrayIcon) self._systray = systray + self._systray.setToolTip(self.tr("All services are OFF")) + + def _update_systray_tooltip(self): + """ + Updates the system tray icon tooltip using the eip and mx statuses. + """ + status = self.tr("Encrypted Internet is {0}").format(self._eip_status) + status += self.tr("\nEncrypted Mail is {0}").format(self._mx_status) + self._systray.setToolTip(status) def set_action_eip_startstop(self, action_eip_startstop): """ @@ -400,10 +412,12 @@ class StatusPanelWidget(QtGui.QWidget): """ leap_assert_type(error, bool) - self._systray.setToolTip(status) + self._eip_status = status + if error: status = "%s" % (status,) self.ui.lblEIPStatus.setText(status) + self._update_systray_tooltip() def set_startstop_enabled(self, value): """ @@ -559,15 +573,18 @@ class StatusPanelWidget(QtGui.QWidget): """ self.ui.lblMailStatus.setText(status) + self._mx_status = self.tr('OFF') tray_status = self.tr('Encrypted Mail is OFF') icon = QtGui.QPixmap(self.MAIL_OFF_ICON) if ready: icon = QtGui.QPixmap(self.MAIL_ON_ICON) + self._mx_status = self.tr('ON') tray_status = self.tr('Encrypted Mail is ON') self.ui.lblMailIcon.setPixmap(icon) self._action_mail_status.setText(tray_status) + self._update_systray_tooltip() def _mail_handle_soledad_events(self, req): """ -- cgit v1.2.3 From 3d7ceef972571dc898448e572dd70bf77cd91b8e Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 9 Sep 2013 11:23:02 -0300 Subject: Update release doc, remove exec bits. Closes #3617 --- changes/bug-3617_remove-exec-bits-from-text-in-bundle | 1 + docs/release_checklist.wiki | 2 +- pkg/linux/build_bundle.sh | 12 ++++++------ 3 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 changes/bug-3617_remove-exec-bits-from-text-in-bundle diff --git a/changes/bug-3617_remove-exec-bits-from-text-in-bundle b/changes/bug-3617_remove-exec-bits-from-text-in-bundle new file mode 100644 index 00000000..caf3a62e --- /dev/null +++ b/changes/bug-3617_remove-exec-bits-from-text-in-bundle @@ -0,0 +1 @@ + o Remove execution bits in text files in bundle. Closes #3617. diff --git a/docs/release_checklist.wiki b/docs/release_checklist.wiki index e6467048..273804c7 100644 --- a/docs/release_checklist.wiki +++ b/docs/release_checklist.wiki @@ -27,7 +27,7 @@ * [ ] git checkout develop && git pull origin develop && git merge release-X.Y.Z && git push origin develop * [ ] Build and upload bundles * [ ] Use the scripts under pkg// to build the the bundles. - * [ ] Sign them with gpg -a + * [ ] Sign them with gpg -a --sign --detach-sign * [ ] Upload bundle and signature to web-uploads@salmon.leap.se:~/public/client//Bitmask--.(tar.bz2,dmg,zip) * [ ] Update symbolic link for latest upload and signature: * [ ] ~/public/client/Bitmask--latest diff --git a/pkg/linux/build_bundle.sh b/pkg/linux/build_bundle.sh index e6a1043f..879579f0 100755 --- a/pkg/linux/build_bundle.sh +++ b/pkg/linux/build_bundle.sh @@ -77,13 +77,13 @@ cp $JOINT_CHANGELOG $TEMPLATE_BUNDLE/CHANGELOG cp $REPOS_ROOT/leap_client/LICENSE $TEMPLATE_BUNDLE/LICENSE -# clean pyc$ - +# clean *.pyc files cd $TEMPLATE_BUNDLE -for i in $(find . | grep pyc$); - do - rm $i - done +find . -name "*.pyc" -delete + +# remove execution flags (because vbox fs) and set all read permissions +chmod -x CHANGELOG LICENSE README +chmod +r CHANGELOG LICENSE README # create tarball -- cgit v1.2.3 From e1ba124417ff76580d64f331d38759dcf8bb3f46 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 9 Sep 2013 09:13:30 -0300 Subject: Fix path prefix helper for bundle and add test. --- changes/bug-3778_fix-path-prefix-helper | 1 + src/leap/bitmask/config/leapsettings.py | 12 ++-- src/leap/bitmask/config/tests/test_leapsettings.py | 71 ++++++++++++++++++++++ 3 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 changes/bug-3778_fix-path-prefix-helper create mode 100644 src/leap/bitmask/config/tests/test_leapsettings.py diff --git a/changes/bug-3778_fix-path-prefix-helper b/changes/bug-3778_fix-path-prefix-helper new file mode 100644 index 00000000..e7cec539 --- /dev/null +++ b/changes/bug-3778_fix-path-prefix-helper @@ -0,0 +1 @@ + o Fix path prefix helper for the bundle and add regresion tests. Closes #3778. diff --git a/src/leap/bitmask/config/leapsettings.py b/src/leap/bitmask/config/leapsettings.py index ad67b29e..7d8b5977 100644 --- a/src/leap/bitmask/config/leapsettings.py +++ b/src/leap/bitmask/config/leapsettings.py @@ -75,12 +75,12 @@ class LeapSettings(object): """ Constructor - :param standalone: parameter used to define the location of - the config + :param standalone: parameter used to define the location of the config. :type standalone: bool """ - settings_path = os.path.join( - get_path_prefix(standalone=standalone), "leap", self.CONFIG_NAME) + self._path_prefix = get_path_prefix(standalone=standalone) + settings_path = os.path.join(self._path_prefix, + "leap", self.CONFIG_NAME) self._settings = QtCore.QSettings(settings_path, QtCore.QSettings.IniFormat) @@ -132,8 +132,8 @@ class LeapSettings(object): # other things, not just the directories providers = [] try: - providers_path = os.path.join( - get_path_prefix(), "leap", "providers") + providers_path = os.path.join(self._path_prefix, + "leap", "providers") providers = os.listdir(providers_path) except Exception as e: logger.debug("Error listing providers, assume there are none. %r" diff --git a/src/leap/bitmask/config/tests/test_leapsettings.py b/src/leap/bitmask/config/tests/test_leapsettings.py new file mode 100644 index 00000000..18166923 --- /dev/null +++ b/src/leap/bitmask/config/tests/test_leapsettings.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# test_leapsettings.py +# Copyright (C) 2013 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# 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 . + +""" +Tests for leapsettings module. +""" + +try: + import unittest2 as unittest +except ImportError: + import unittest + +import os +import mock + +from leap.common.testing.basetest import BaseLeapTest +from leap.bitmask.config.leapsettings import LeapSettings + + +class LeapSettingsTest(BaseLeapTest): + """Tests for LeapSettings""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_get_configured_providers(self): + """ + Test that the config file IS NOT stored under the CWD. + """ + self._leapsettings = LeapSettings() + with mock.patch('os.listdir') as os_listdir: + # use this method only to spy where LeapSettings is looking for + self._leapsettings.get_configured_providers() + args, kwargs = os_listdir.call_args + config_dir = args[0] + self.assertFalse(config_dir.startswith(os.getcwd())) + self.assertFalse(config_dir.endswith('config')) + + def test_get_configured_providers_in_bundle(self): + """ + Test that the config file IS stored under the CWD. + """ + self._leapsettings = LeapSettings(standalone=True) + with mock.patch('os.listdir') as os_listdir: + # use this method only to spy where LeapSettings is looking for + self._leapsettings.get_configured_providers() + args, kwargs = os_listdir.call_args + config_dir = args[0] + self.assertTrue(config_dir.startswith(os.getcwd())) + self.assertFalse(config_dir.endswith('config')) + + +if __name__ == "__main__": + unittest.main() -- cgit v1.2.3 From 9a176cc73d2e964d77f1933800aa2a8dd3fdae72 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Fri, 6 Sep 2013 23:23:14 +0200 Subject: add codename --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 577bb6ca..e94943ae 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -0.3.2 Sep 9: +0.3.2 Sep 6 -- the "no crashes or anything" release: o Fix up script in non-bundle linuces. Closes: #3450 o Logout stops imap and smtp services. Closes: #3553 o Properly daemonize polkit-gnome-authentication-agent. Closes: #3554 -- cgit v1.2.3 From 724d149aea99173674493ad1f1f4f9a948202749 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 9 Sep 2013 12:28:17 -0300 Subject: Make user messages more consistent. --- src/leap/bitmask/gui/mainwindow.py | 2 +- src/leap/bitmask/gui/statuspanel.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 0950462b..6141a3a2 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -256,7 +256,7 @@ class MainWindow(QtGui.QMainWindow): self._action_eip_provider.setEnabled(False) self._action_eip_status = QtGui.QAction( - self.tr("Encrypted internet is OFF"), + self.tr("Encrypted Internet is OFF"), self) self._action_eip_status.setEnabled(False) self._status_panel.set_action_eip_status( diff --git a/src/leap/bitmask/gui/statuspanel.py b/src/leap/bitmask/gui/statuspanel.py index 190bc02f..10e6bca3 100644 --- a/src/leap/bitmask/gui/statuspanel.py +++ b/src/leap/bitmask/gui/statuspanel.py @@ -346,7 +346,8 @@ class StatusPanelWidget(QtGui.QWidget): Updates the system tray icon tooltip using the eip and mx statuses. """ status = self.tr("Encrypted Internet is {0}").format(self._eip_status) - status += self.tr("\nEncrypted Mail is {0}").format(self._mx_status) + status += '\n' + status += self.tr("Encrypted Mail is {0}").format(self._mx_status) self._systray.setToolTip(status) def set_action_eip_startstop(self, action_eip_startstop): @@ -544,14 +545,14 @@ class StatusPanelWidget(QtGui.QWidget): """ selected_pixmap = self.ERROR_ICON selected_pixmap_tray = self.ERROR_ICON_TRAY - tray_message = self.tr("Encryption is OFF") + tray_message = self.tr("Encrypted Internet is OFF") if status in ("WAIT", "AUTH", "GET_CONFIG", "RECONNECTING", "ASSIGN_IP"): selected_pixmap = self.CONNECTING_ICON selected_pixmap_tray = self.CONNECTING_ICON_TRAY tray_message = self.tr("Turning ON") elif status in ("CONNECTED"): - tray_message = self.tr("Encryption is ON") + tray_message = self.tr("Encrypted Internet is ON") selected_pixmap = self.CONNECTED_ICON selected_pixmap_tray = self.CONNECTED_ICON_TRAY -- cgit v1.2.3 From b0cc3f3096db324a9e4106556b5c5718d5e1c2b5 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 10 Sep 2013 16:05:44 -0300 Subject: Fix LoggerWindow saving triple \n. Closes #3714. --- changes/bug-3714_fix-logger-saving-several-line-returns | 2 ++ src/leap/bitmask/gui/loggerwindow.py | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 changes/bug-3714_fix-logger-saving-several-line-returns diff --git a/changes/bug-3714_fix-logger-saving-several-line-returns b/changes/bug-3714_fix-logger-saving-several-line-returns new file mode 100644 index 00000000..455c5a95 --- /dev/null +++ b/changes/bug-3714_fix-logger-saving-several-line-returns @@ -0,0 +1,2 @@ + o Fix LoggerWindow saving more than one line return per line in the logs + file. Closes #3714. diff --git a/src/leap/bitmask/gui/loggerwindow.py b/src/leap/bitmask/gui/loggerwindow.py index ece4cad6..ad2ceded 100644 --- a/src/leap/bitmask/gui/loggerwindow.py +++ b/src/leap/bitmask/gui/loggerwindow.py @@ -91,7 +91,6 @@ class LoggerWindow(QtGui.QDialog): } level = log[LeapLogHandler.RECORD_KEY].levelno message = log[LeapLogHandler.MESSAGE_KEY] - message = message.replace('\n', '
\n') if self._logs_to_display[level]: open_tag = "" @@ -152,8 +151,13 @@ class LoggerWindow(QtGui.QDialog): if fileName: try: with open(fileName, 'w') as output: - output.write(self.ui.txtLogHistory.toPlainText()) - output.write('\n') + history = self.ui.txtLogHistory.toPlainText() + # Chop some \n. + # html->plain adds several \n because the html is made + # using table cells. + history = history.replace('\n\n\n', '\n') + + output.write(history) logger.debug('Log saved in %s' % (fileName, )) except IOError, e: logger.error("Error saving log file: %r" % (e, )) -- cgit v1.2.3 From 9ff57c8046ed012e907e623188329728eaef267b Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Tue, 10 Sep 2013 19:13:15 +0200 Subject: do not try to install globally. --- changes/bug_3803-do-not-install-resolv-update-globally | 1 + setup.py | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 changes/bug_3803-do-not-install-resolv-update-globally diff --git a/changes/bug_3803-do-not-install-resolv-update-globally b/changes/bug_3803-do-not-install-resolv-update-globally new file mode 100644 index 00000000..f6e06d5f --- /dev/null +++ b/changes/bug_3803-do-not-install-resolv-update-globally @@ -0,0 +1 @@ + o Do not try to install resolv-update globally. Closes: #3803 diff --git a/setup.py b/setup.py index 5099c1b1..88cb0e40 100755 --- a/setup.py +++ b/setup.py @@ -135,17 +135,17 @@ import platform _system = platform.system() IS_LINUX = True if _system == "Linux" else False +data_files = [] + if IS_LINUX: + # XXX use check_for_permissions to install data + # globally. See #3805 data_files = [ - # ("share/man/man1", - # ["docs/man/bitmask.1"]), ("share/polkit-1/actions", ["pkg/linux/polkit/net.openvpn.gui.leap.policy"]), - ("/etc/leap/", + ("etc/leap/", ["pkg/linux/resolv-update"]), ] -else: - data_files = [] setup( name="leap.bitmask", -- cgit v1.2.3 From 16fbe19986b8cc36873b24bd2b8f61cffd1b1d29 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 11 Sep 2013 12:41:51 +0200 Subject: catch indexerror on first utility --- changes/bug_fix-first | 1 + src/leap/bitmask/util/__init__.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changes/bug_fix-first diff --git a/changes/bug_fix-first b/changes/bug_fix-first new file mode 100644 index 00000000..0ef5188c --- /dev/null +++ b/changes/bug_fix-first @@ -0,0 +1 @@ + o Catch IndexError on `first` utility. diff --git a/src/leap/bitmask/util/__init__.py b/src/leap/bitmask/util/__init__.py index 6dd18bcf..78efcb6e 100644 --- a/src/leap/bitmask/util/__init__.py +++ b/src/leap/bitmask/util/__init__.py @@ -27,7 +27,7 @@ def first(things): """ try: return things[0] - except TypeError: + except (IndexError, TypeError): return None -- cgit v1.2.3 From 8ccd37675068abb63887faed0e556306f442058f Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 10 Sep 2013 17:48:41 -0300 Subject: Prevent last window closing the app in tray. --- changes/bug-3791_prevent-last-window-close-app | 1 + src/leap/bitmask/gui/mainwindow.py | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 changes/bug-3791_prevent-last-window-close-app diff --git a/changes/bug-3791_prevent-last-window-close-app b/changes/bug-3791_prevent-last-window-close-app new file mode 100644 index 00000000..3eeee72a --- /dev/null +++ b/changes/bug-3791_prevent-last-window-close-app @@ -0,0 +1 @@ + o Prevent dialogs closing the app when it has been minimized to the tray. Closes #3791. diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 6141a3a2..2942d4c8 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -682,11 +682,18 @@ class MainWindow(QtGui.QMainWindow): Toggles the window visibility """ visible = self.isVisible() and self.isActiveWindow() + qApp = QtCore.QCoreApplication.instance() + if not visible: + qApp.setQuitOnLastWindowClosed(True) self.show() self.activateWindow() self.raise_() else: + # We set this in order to avoid dialogs shutting down the + # app on close, as they will be the only visible window. + # e.g.: PreferencesWindow, LoggerWindow + qApp.setQuitOnLastWindowClosed(False) self.hide() self._update_hideshow_menu() @@ -1611,6 +1618,11 @@ class MainWindow(QtGui.QMainWindow): """ # TODO separate the shutting down of services from the # UI stuff. + + # Set this in case that the app is hidden + qApp = QtCore.QCoreApplication.instance() + qApp.setQuitOnLastWindowClosed(True) + self._cleanup_and_quit() self._really_quit = True -- cgit v1.2.3 From 41bae82d52a189064b09a4dded8ce5be8d7217e3 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 11 Sep 2013 16:39:19 +0200 Subject: remove unused icons from resources --- data/resources/mainwindow.qrc | 3 --- 1 file changed, 3 deletions(-) diff --git a/data/resources/mainwindow.qrc b/data/resources/mainwindow.qrc index d1268186..1e4159b8 100644 --- a/data/resources/mainwindow.qrc +++ b/data/resources/mainwindow.qrc @@ -2,10 +2,8 @@ ../images/mask-launcher.png ../images/mask-icon.png - ../images/watermark.png ../images/leap-gray-big.png ../images/Blue-Arrow-Right-32.png - ../images/Globe.png ../images/leap-color-big.png ../images/Arrow-Down-32.png ../images/Arrow-Up-32.png @@ -15,7 +13,6 @@ ../images/conn_connecting-light.png ../images/conn_connected-light.png ../images/conn_error-light.png - ../images/leap-color-small.png ../images/Dialog-accept.png ../images/Dialog-error.png ../images/Emblem-question.png -- cgit v1.2.3 From 5336cde1fb05da618b01aac39777655497065d5e Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 11 Sep 2013 17:14:33 +0200 Subject: Fix the format for the keyring requirement --- pkg/requirements.pip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/requirements.pip b/pkg/requirements.pip index 77cdf17c..7fc2a75e 100644 --- a/pkg/requirements.pip +++ b/pkg/requirements.pip @@ -18,7 +18,7 @@ qt4reactor python-gnupg python-daemon # this should not be needed for Windows. -keyring<3.0.0 # See #3759 +keyring<=2.9 # See #3759 leap.common>=0.3.2 leap.soledad.client>=0.3.0 -- cgit v1.2.3 From f4ca53c9c8ce3a0d3dac34c956be6899695498d0 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 12 Sep 2013 13:50:18 +0200 Subject: remove duplicated dependency --- pkg/requirements.pip | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/requirements.pip b/pkg/requirements.pip index 7fc2a75e..081f3ba9 100644 --- a/pkg/requirements.pip +++ b/pkg/requirements.pip @@ -9,7 +9,6 @@ argparse requests srp>=1.0.2 pyopenssl -keyring python-dateutil psutil ipaddr -- cgit v1.2.3 From 5dcb215617ac174aed4e346d21a9efc648f6ee45 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 12 Sep 2013 11:35:30 -0300 Subject: Change the order of the actions in the release. With this change we are following more accurately: http://nvie.com/posts/a-successful-git-branching-model/ Also, we achieve a clean version in master. If we do the tag before the merge in master, then we would have an extra commit after the tagging, which causes version to be X.Y.Z-1-blah. --- docs/release_checklist.wiki | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/release_checklist.wiki b/docs/release_checklist.wiki index 273804c7..aa83b566 100644 --- a/docs/release_checklist.wiki +++ b/docs/release_checklist.wiki @@ -21,10 +21,10 @@ * [ ] Review pkg/requirements.pip for everything and update if needed (that's why the order). - See whatever has been introduced in changes/VERSION_COMPAT - Reset changes/VERSION_COMPAT + * [ ] git checkout master && git pull origin master && git merge --no-ff release-X.Y.Z && git push origin master + * [ ] git checkout develop && git pull origin develop && git merge --no-ff release-X.Y.Z && git push origin develop * [ ] git tag -s X.Y.Z (note the -s so that it's a signed tag) The message should be something like: Tag version X.Y.Z * [ ] git push origin X.Y.Z - * [ ] git checkout master && git pull origin master && git merge release-X.Y.Z && git push origin master - * [ ] git checkout develop && git pull origin develop && git merge release-X.Y.Z && git push origin develop * [ ] Build and upload bundles * [ ] Use the scripts under pkg// to build the the bundles. * [ ] Sign them with gpg -a --sign --detach-sign @@ -38,3 +38,5 @@ Notes ----- (*) this checklist kindly borrowed from tahoe-lafs documentation =) + +For a good reference look at http://nvie.com/posts/a-successful-git-branching-model/ -- cgit v1.2.3 From 061c2aae0821f1e37b1de5b0347077ecfb276b65 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 12 Sep 2013 15:07:24 +0200 Subject: add --version flag --- changes/feature_3816-add-version-flag | 1 + docs/man/bitmask.1.rst | 2 ++ src/leap/bitmask/app.py | 7 ++++++- src/leap/bitmask/util/leap_argparse.py | 4 +++- 4 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 changes/feature_3816-add-version-flag diff --git a/changes/feature_3816-add-version-flag b/changes/feature_3816-add-version-flag new file mode 100644 index 00000000..cfbd2f67 --- /dev/null +++ b/changes/feature_3816-add-version-flag @@ -0,0 +1 @@ + o Adds --version flag. Closes: #3816 diff --git a/docs/man/bitmask.1.rst b/docs/man/bitmask.1.rst index 7a1d2ae1..ed4f7133 100644 --- a/docs/man/bitmask.1.rst +++ b/docs/man/bitmask.1.rst @@ -38,6 +38,8 @@ general options **-s, --standalone** Makes Bitmask use standalone directories for configuration and binary searching. +**-V, --version** Displays Bitmask version and exits. + openvpn options --------------- diff --git a/src/leap/bitmask/app.py b/src/leap/bitmask/app.py index 158f1afe..8c839edc 100644 --- a/src/leap/bitmask/app.py +++ b/src/leap/bitmask/app.py @@ -24,6 +24,7 @@ from functools import partial from PySide import QtCore, QtGui +from leap.bitmask import __version__ as VERSION from leap.bitmask.util import leap_argparse from leap.bitmask.util import log_silencer from leap.bitmask.util.leap_log_handler import LeapLogHandler @@ -133,6 +134,11 @@ def main(): print "Could not ensure server: %r" % (e,) _, opts = leap_argparse.init_leapc_args() + + if opts.version: + print "Bitmask version: %s" % (VERSION,) + sys.exit(0) + standalone = opts.standalone bypass_checks = getattr(opts, 'danger', False) debug = opts.debug @@ -156,7 +162,6 @@ def main(): from leap.bitmask.gui.mainwindow import MainWindow from leap.bitmask.platform_init import IS_MAC from leap.bitmask.platform_init.locks import we_are_the_one_and_only - from leap.bitmask import __version__ as VERSION from leap.bitmask.util.requirement_checker import check_requirements # pylint: avoid unused import diff --git a/src/leap/bitmask/util/leap_argparse.py b/src/leap/bitmask/util/leap_argparse.py index bc21a9cf..afe5be48 100644 --- a/src/leap/bitmask/util/leap_argparse.py +++ b/src/leap/bitmask/util/leap_argparse.py @@ -27,7 +27,7 @@ def build_parser(): All the options for the leap arg parser Some of these could be switched on only if debug flag is present! """ - epilog = "Copyright 2012 The LEAP Encryption Access Project" + epilog = "Copyright 2012-2013 The LEAP Encryption Access Project" parser = argparse.ArgumentParser(description=""" Launches Bitmask""", epilog=epilog) parser.add_argument('-d', '--debug', action="store_true", @@ -50,6 +50,8 @@ Launches Bitmask""", epilog=epilog) help='Makes Bitmask use standalone' 'directories for configuration and binary' 'searching') + parser.add_argument('-V', '--version', action="store_true", + help='Displays Bitmask version and exits') # Not in use, we might want to reintroduce them. #parser.add_argument('-i', '--no-provider-checks', -- cgit v1.2.3 From 63d5a8f004cd34f5e8a9e0168a28610fc1f2ebd2 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 12 Sep 2013 17:03:56 +0200 Subject: add checkboxes --- docs/release_checklist.wiki | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/release_checklist.wiki b/docs/release_checklist.wiki index aa83b566..e6513f90 100644 --- a/docs/release_checklist.wiki +++ b/docs/release_checklist.wiki @@ -2,12 +2,12 @@ * [ ] Check that all tests are passing! * [ ] Tag everything * Should be done for the following packages, in order: - 1. leap.common - 2. leap.keymanager - 3. leap.soledad - 4. leap.mail - 5. leap.bitmask - 6. leap.mx + * [ ] 1. leap.common + * [ ] 2. leap.keymanager + * [ ] 3. leap.soledad + * [ ] 4. leap.mail + * [ ] 5. leap.bitmask + * [ ] 6. leap.mx * NOTE: It's assumed that origin is the leap.se repo * [ ] git fetch origin * [ ] git tag -l, and see the latest tagged version (unless it's not a minor version bump, in which case, just bump to it) -- cgit v1.2.3 From fd697344cb39bd7b5a53e8e8b83ab7c78e1ef5ed Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 12 Sep 2013 17:01:58 -0300 Subject: Update instructions to improve release process. This allows us to have master and develop in sync after the release. Also get a correct and clean version report. I've included the `-m` switch in the `git tag` command so we avoid to open an editor and let us closer to make a script to automate this. --- docs/release_checklist.wiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/release_checklist.wiki b/docs/release_checklist.wiki index e6513f90..b12a42a4 100644 --- a/docs/release_checklist.wiki +++ b/docs/release_checklist.wiki @@ -22,9 +22,9 @@ - See whatever has been introduced in changes/VERSION_COMPAT - Reset changes/VERSION_COMPAT * [ ] git checkout master && git pull origin master && git merge --no-ff release-X.Y.Z && git push origin master - * [ ] git checkout develop && git pull origin develop && git merge --no-ff release-X.Y.Z && git push origin develop - * [ ] git tag -s X.Y.Z (note the -s so that it's a signed tag) The message should be something like: Tag version X.Y.Z + * [ ] git tag -s X.Y.Z -m "Tag version X.Y.Z" # (note the -s so that it's a signed tag and -m to specify the message for the tag) * [ ] git push origin X.Y.Z + * [ ] git checkout develop && git merge master && git push origin develop * [ ] Build and upload bundles * [ ] Use the scripts under pkg// to build the the bundles. * [ ] Sign them with gpg -a --sign --detach-sign -- cgit v1.2.3 From 25cecaf03dd02ca2dd9fa78b7495c8557f20ec85 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 12 Sep 2013 23:12:52 +0200 Subject: update to new git repo name --- README.rst | 4 ++-- changes/feature_3417_update-repo-in-docs | 1 + docs/dev/environment.rst | 2 +- docs/testers/howto.rst | 4 ++-- docs/user/install.rst | 6 ++---- 5 files changed, 8 insertions(+), 9 deletions(-) create mode 100644 changes/feature_3417_update-repo-in-docs diff --git a/README.rst b/README.rst index f8308566..c6d37390 100644 --- a/README.rst +++ b/README.rst @@ -71,7 +71,7 @@ Hacking The Bitmask git repository is available at:: - git://leap.se/leap_client + git://leap.se/bitmask_client Some steps need to be run when setting a development environment for the first time. @@ -117,7 +117,7 @@ which the first time should automagically install all the needed dependencies in License ======= -.. image:: https://raw.github.com/leapcode/leap_client/develop/docs/user/gpl.png +.. image:: https://raw.github.com/leapcode/bitmask_client/develop/docs/user/gpl.png Bitmask is released under the terms of the `GNU GPL version 3`_ or later. diff --git a/changes/feature_3417_update-repo-in-docs b/changes/feature_3417_update-repo-in-docs new file mode 100644 index 00000000..065b9497 --- /dev/null +++ b/changes/feature_3417_update-repo-in-docs @@ -0,0 +1 @@ + o Update git repo name in docs. Closes: #3417 diff --git a/docs/dev/environment.rst b/docs/dev/environment.rst index 5ae3871a..e942b1cb 100644 --- a/docs/dev/environment.rst +++ b/docs/dev/environment.rst @@ -13,7 +13,7 @@ Cloning the repo :: - git clone git://leap.se/leap_client + git clone git://leap.se/bitmask_client git checkout develop .. XXX change this when repo changes. diff --git a/docs/testers/howto.rst b/docs/testers/howto.rst index 9c6561ed..015a4ab2 100644 --- a/docs/testers/howto.rst +++ b/docs/testers/howto.rst @@ -41,12 +41,12 @@ Download and source the following script in the parent folder where you want you .. code-block:: bash cd /tmp - wget https://raw.github.com/leapcode/leap_client/develop/pkg/scripts/bitmask_bootstrap.sh + wget https://raw.github.com/leapcode/bitmask_client/develop/pkg/scripts/bitmask_bootstrap.sh source bitmask_bootstrap.sh Tada! If everything went well, you should be able to run bitmask by typing:: - bin/bitmask + bitmask Noticed that your prompt changed? That was *virtualenv*. Keep reading... diff --git a/docs/user/install.rst b/docs/user/install.rst index 81807a43..e5765302 100644 --- a/docs/user/install.rst +++ b/docs/user/install.rst @@ -88,15 +88,13 @@ Installing Bitmask is as simple as using `pip `_ Show me the code! ----------------- -.. XXX UPDATE REPO NAMES AS SOON AS #3417 is DONE - You can get the code from LEAP public git repository :: - $ git clone git://leap.se/leap_client + $ git clone git://leap.se/bitmask_client Or from the github mirror :: - $ git clone git://github.com/leapcode/leap_client.git + $ git clone git://github.com/leapcode/bitmask_client.git Once you have grabbed a copy of the sources, you can install it into your site-packages easily :: -- cgit v1.2.3 From a81ae28db34412c298ececc64319a9cf993c18f3 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 13 Sep 2013 15:53:41 -0300 Subject: Handle correctly a logout problem. Closes #3774. Also remove preferences button disable, we don't need that. --- changes/bug-3774_fix-logout-error | 2 ++ src/leap/bitmask/crypto/srpauth.py | 1 + src/leap/bitmask/gui/mainwindow.py | 17 ++++++++++------- 3 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 changes/bug-3774_fix-logout-error diff --git a/changes/bug-3774_fix-logout-error b/changes/bug-3774_fix-logout-error new file mode 100644 index 00000000..ce0951f0 --- /dev/null +++ b/changes/bug-3774_fix-logout-error @@ -0,0 +1,2 @@ + o Catch logout problem, display a user message and allow log back in after a + successful logout if there was a logout error before. Closes #3774. diff --git a/src/leap/bitmask/crypto/srpauth.py b/src/leap/bitmask/crypto/srpauth.py index 41ce130a..776fb2cc 100644 --- a/src/leap/bitmask/crypto/srpauth.py +++ b/src/leap/bitmask/crypto/srpauth.py @@ -553,6 +553,7 @@ class SRPAuth(QtCore.QObject): except Exception as e: logger.warning("Something went wrong with the logout: %r" % (e,)) + raise else: self.set_session_id(None) self.set_uid(None) diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 2942d4c8..c0983b67 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1451,13 +1451,16 @@ class MainWindow(QtGui.QMainWindow): Switches the stackedWidget back to the login stage after logging out """ - self._logged_user = None - self.ui.action_log_out.setEnabled(False) - self.ui.stackedWidget.setCurrentIndex(self.LOGIN_INDEX) - self._login_widget.set_password("") - self._login_widget.set_enabled(True) - self._login_widget.set_status("") - self.ui.btnPreferences.setEnabled(False) + if ok: + self._logged_user = None + self.ui.action_log_out.setEnabled(False) + self.ui.stackedWidget.setCurrentIndex(self.LOGIN_INDEX) + self._login_widget.set_password("") + self._login_widget.set_enabled(True) + self._login_widget.set_status("") + else: + status_text = self.tr("Something went wrong with the logout.") + self._status_panel.set_global_status(status_text, error=True) def _intermediate_stage(self, data): """ -- cgit v1.2.3 From ee2c55062a2cb5112adc9f63e042ad8748b511cb Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Fri, 13 Sep 2013 11:07:41 +0200 Subject: update metadata in setup.py --- docs/release_checklist.wiki | 2 +- setup.py | 61 +++++++++++++++++++++++++++++++------------- src/leap/bitmask/__init__.py | 2 +- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/docs/release_checklist.wiki b/docs/release_checklist.wiki index b12a42a4..19a19289 100644 --- a/docs/release_checklist.wiki +++ b/docs/release_checklist.wiki @@ -17,10 +17,10 @@ - Helper bash line: for i in $(ls changes); do cat changes/$i; echo; done * [ ] Update relnotes.txt if needed. * [ ] git rm changes/* - * [ ] git commit -av * [ ] Review pkg/requirements.pip for everything and update if needed (that's why the order). - See whatever has been introduced in changes/VERSION_COMPAT - Reset changes/VERSION_COMPAT + * [ ] git commit -av # we should add a commit message here... * [ ] git checkout master && git pull origin master && git merge --no-ff release-X.Y.Z && git push origin master * [ ] git tag -s X.Y.Z -m "Tag version X.Y.Z" # (note the -s so that it's a signed tag and -m to specify the message for the tag) * [ ] git push origin X.Y.Z diff --git a/setup.py b/setup.py index 88cb0e40..78c5b0fb 100755 --- a/setup.py +++ b/setup.py @@ -18,10 +18,10 @@ """ Setup file for bitmask. """ - from __future__ import print_function import sys +import re if not sys.version_info[0] == 2: print("[ERROR] Sorry, Python 3 is not supported (yet). " @@ -65,10 +65,13 @@ trove_classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", - "Topic :: Communications", "Topic :: Security", - "Topic :: System :: Networking", - "Topic :: Utilities" + 'Topic :: Security :: Cryptography', + "Topic :: Communications", + 'Topic :: Communications :: Email', + 'Topic :: Communications :: Email :: Post-Office :: IMAP', + 'Topic :: Internet', + "Topic :: Utilities", ] @@ -139,7 +142,7 @@ data_files = [] if IS_LINUX: # XXX use check_for_permissions to install data - # globally. See #3805 + # globally. Or make specific install command. See #3805 data_files = [ ("share/polkit-1/actions", ["pkg/linux/polkit/net.openvpn.gui.leap.policy"]), @@ -147,23 +150,42 @@ if IS_LINUX: ["pkg/linux/resolv-update"]), ] +DOWNLOAD_BASE = ('https://github.com/leapcode/bitmask_client/' + 'archive/%s.tar.gz') +VERSION = versioneer.get_version() +DOWNLOAD_URL = "" + +# get the short version for the download url +short_ver = re.findall('\d+\.\d+\.\d+', VERSION) +if len(short_ver) > 0: + DOWNLOAD_URL = DOWNLOAD_BASE % short_ver[0] + + setup( name="leap.bitmask", package_dir={"": "src"}, - version=versioneer.get_version(), + version=VERSION, cmdclass=cmdclass, - description="The Internet Encryption Toolkit", + description=("The Internet Encryption Toolkit: " + "Encrypted Internet Proxy and Encrypted Mail."), + # XXX unify the long_description on a file of its own, so we + # can reuse it easily. long_description=( - "Desktop Client for the LEAP Platform." + "Bitmask is the multiplatform desktop client for the LEAP Platform." "\n" - "LEAP (LEAP Encryption Access Project) develops " - "a multi-year plan to secure everyday communication, breaking down" - "into discrete services, to be rolled out one at a time.\n" - "The client for the current phase gives support to the EIP Service." - "EIP (the Encrypted Internet Proxy) provides circumvention, location " - "anonymization, and traffic " - "encryption in a hassle-free, automatically self-configuring fashion, " - "and has an enhanced level of security." + "The LEAP Encryption Access Project develops " + "a multi-year plan to secure everyday communication.\n " + "The Encrypted Internet Proxy (EIP) provides circumvention, location " + "anonymization, and traffic encryption in a hassle-free, " + "automatically self-configuring fashion.\n" + "Encrypted Mail offers automatic encryption and decryption for " + "both outgoing and incoming email, adding public key cryptography " + "to your mail without you ever having to worry about key distribution " + "or signature verification. \n" + "The Encrypted Mail services will run local SMTP and IMAP proxies " + "that, once you configure the mail client of your choice, will " + "automatically encrypt and decrypt your email using GPG encryption " + "under the hood." ), classifiers=trove_classifiers, install_requires=parsed_reqs, @@ -171,10 +193,13 @@ setup( tests_require=utils.parse_requirements( reqfiles=['pkg/requirements-testing.pip']), keywords=('Bitmask, LEAP, client, qt, encryption, ' - 'proxy, openvpn, imap, smtp'), + 'proxy, openvpn, imap, smtp, gnupg'), author='The LEAP Encryption Access Project', author_email='info@leap.se', - url='https://leap.se', + maintainer='Kali Kaneko', + maintainer_email='kali@leap.se', + url='https://bitmask.rtfd.org', + download_url=DOWNLOAD_URL, license='GPL-3+', packages=find_packages( 'src', diff --git a/src/leap/bitmask/__init__.py b/src/leap/bitmask/__init__.py index ebdd53c4..a4642e27 100644 --- a/src/leap/bitmask/__init__.py +++ b/src/leap/bitmask/__init__.py @@ -71,5 +71,5 @@ except ImportError: #the setup.py setver pass -__short_version__ = first(re.findall('\d\.\d\.\d', __version__)) +__short_version__ = first(re.findall('\d+\.\d+\.\d+', __version__)) __full_version__ = __appname__ + '/' + str(__version__) -- cgit v1.2.3 From 1cd4ecf0764ddf34de5e0b018edcab331d1ac5df Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Fri, 13 Sep 2013 09:06:31 +0200 Subject: update readme --- README.rst | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/README.rst b/README.rst index c6d37390..ba78dbe7 100644 --- a/README.rst +++ b/README.rst @@ -34,8 +34,8 @@ Bitmask depends on these libraries: Python packages are listed in ``pkg/requirements.pip`` and ``pkg/test-requirements.pip`` -Debian -^^^^^^ +Getting dependencies under debian +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ With a Debian based system, to be able to run Bitmask you need to run the following command:: @@ -47,7 +47,7 @@ Installing After getting the source and installing all the dependencies, proceed to install ``bitmask`` package:: $ make - $ sudo LEAP_VENV_SKIP_PYSIDE=1 python setup.py install + $ sudo python setup.py install Running ------- @@ -60,7 +60,7 @@ If you are testing a new provider and do not have a CA certificate chain tied to $ bitmask --danger -But **DO NOT use it on a regular bases**. +But **DO NOT use it on a regular basis**. **WARNING**: If you use the --danger flag you may be victim to a MITM_ attack without noticing. Use at your own risk. @@ -69,9 +69,13 @@ But **DO NOT use it on a regular bases**. Hacking ======= -The Bitmask git repository is available at:: +Get the source from the main Bitmask repo:: - git://leap.se/bitmask_client + git clone https://leap.se/git/bitmask_client + +The code is also browsable online at:: + + https://leap.se/git/?p=bitmask_client.git Some steps need to be run when setting a development environment for the first time. @@ -94,10 +98,10 @@ And make your working tree available to your pythonpath:: Run Bitmask:: - (bitmask)$ python src/leap/app.py -d + (bitmask)$ bitmask --debug -If you are testing a new provider that doesn't have the proper certificates yet, you can use --danger flag, but **DO NOT use it on a regular bases**. +If you are testing a new provider that doesn't have the proper certificates yet, you can use --danger flag, but **DO NOT use it on a regular basis**. **WARNING**: If you use the --danger flag you may be victim to a MITM_ attack without noticing. Use at your own risk. -- cgit v1.2.3 From 17acf80585c62fddde4ed8359da673b00606ddbe Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 16 Sep 2013 16:46:21 -0400 Subject: explicitely invoke python2 --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index ba78dbe7..a4272c40 100644 --- a/README.rst +++ b/README.rst @@ -47,7 +47,7 @@ Installing After getting the source and installing all the dependencies, proceed to install ``bitmask`` package:: $ make - $ sudo python setup.py install + $ sudo python2 setup.py install Running ------- @@ -94,7 +94,7 @@ Symlink your global pyside libraries:: And make your working tree available to your pythonpath:: - (bitmask)$ python setup.py develop + (bitmask)$ python2 setup.py develop Run Bitmask:: -- cgit v1.2.3 From 91f01388246d05001f241c7c5def095557e835d1 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 16 Sep 2013 18:05:47 -0300 Subject: Wait for visibility to change before update menu. --- changes/bug-3821_inconsistent-hide-show-mainwindow | 1 + src/leap/bitmask/gui/mainwindow.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 changes/bug-3821_inconsistent-hide-show-mainwindow diff --git a/changes/bug-3821_inconsistent-hide-show-mainwindow b/changes/bug-3821_inconsistent-hide-show-mainwindow new file mode 100644 index 00000000..3fb05a85 --- /dev/null +++ b/changes/bug-3821_inconsistent-hide-show-mainwindow @@ -0,0 +1 @@ + o Inconsistent hide/show main window from tray action. Closes #3821. diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 2942d4c8..98cfacb1 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -696,7 +696,9 @@ class MainWindow(QtGui.QMainWindow): qApp.setQuitOnLastWindowClosed(False) self.hide() - self._update_hideshow_menu() + # Wait a bit until the window visibility has changed so + # the menu is set with the correct value. + QtCore.QTimer.singleShot(500, self._update_hideshow_menu) def _center_window(self): """ -- cgit v1.2.3 From bb585a6b4785fa53ef3ab60762b78eab26170279 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 17 Sep 2013 22:32:53 -0300 Subject: Add a proper header for the app.py. --- src/leap/bitmask/app.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/leap/bitmask/app.py b/src/leap/bitmask/app.py index 8c839edc..dae6b357 100644 --- a/src/leap/bitmask/app.py +++ b/src/leap/bitmask/app.py @@ -14,6 +14,31 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +# +# M:::::::MMMMMMMMMM~:::::::::::::::::::::::::::::::::::::~MMMMMMMMMM~:::::::M +# M:::::MMM$$$$$77$MMMMN~:::::::::::::::::::::::::::::~NMMMM$77$$$$$MMM::::::M +# M:::~MMZ$$$$$777777I8MMMM~:::::::::::::::::::::::~MMMMDI777777$$$$$$MM:::::M +# M:::MMZ$$$$$777777IIIIIZMMMM:::::::::::::::::::MMNMZIIIII777777$$$$$$MM::::M +# M::DMN$$$$$777777IIIIIII??7DDNM+:::::::::::=MDDD7???IIIIII777777$$$$$DMN:::M +# M::MM$$$$$7777777IIIIIII????+?88OOMMMMMMMOO88???????IIIIIII777777$$$$$MM:::M +# M::MM$$$$$777777IIIIIIII??????++++7ZZ$$ZI+++++??????IIIIIIII777777$$$$MM~::M +# M:~MM$$$$77777Z8OIIIIIIII??????++++++++++++++??????IIIIIIIO8Z77777$$$$NM+::M +# M::MM$$$777MMMMMMMMMMMZ?II???????+++++++++???????III$MMMMMMMMMMM7777$$DM$::M +# M:~MM$$77MMMI~::::::$MMMM$?I????????????????????I$MMMMZ~::::::+MMM77$$MM~::M +# M::MM$7777MM::::::::::::MMMMI?????????????????IMMMM:::::::::::~MM7777$MM:::M +# M::MM777777MM~:::::::::::::MMMD?I?????????IIDMMM,:::::::::::::MM777777MM:::M +# M::DMD7777IIMM$::::::::::::?MMM?I??????????IMMM$::::::::::::7MM7I77778MN:::M +# M:::MM777IIIIMMMN~:::::::MMMM?II???+++++????IIMMMM::::::::MMMMIIII777MM::::M +# M:::ZMM7IIIIIIIOMMMMMMMMMMZ?III???++++++++??III?$MMMMMMMMMMO?IIIIII7MMO::::M +# M::::MMDIIIIIIIIII?IIIII?IIIII???+++===++++??IIIIIIII?II?IIIIIIIIII7MM:::::M +# M:::::MM7IIIIIIIIIIIIIIIIIIIII??+++IZ$$I+++??IIIIIIIIIIIIIIIIIIIII7MM::::::M +# M::::::MMOIIIIIIIIIIIIIIIIIIII?D888MMMMM8O8D?IIIIIIIIIIIIIIIIIIII$MM:::::::M +# M:::::::MMM?IIIIIIIIIIIIIIII7MNMD:::::::::OMNM$IIIIIIIIIIIIIIII?MMM::::::::M +# M::::::::NMMI?IIIIIIIIIII?OMMM:::::::::::::::MMMO?IIIIIIIIIIIIIMMN:::::::::M +# M::::::::::MMMIIIIIIIII?8MMM:::::::::::::::::::MMM8IIIIIIIIIIMMM:::::::::::M +# M:::::::::::~NMMM7???7MMMM:::::::::::::::::::::::NMMMI??I7MMMM:::::::::::::M +# M::::::::::::::7MMMMMMM+:::::::::::::::::::::::::::?MMMMMMMZ:::::::::::::::M +# (thanks to: http://www.glassgiant.com/ascii/) import logging import signal -- cgit v1.2.3 From 13f5d8fcee038f441dd91ef16dfdb254e1f0dd3f Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Tue, 17 Sep 2013 15:43:01 -0400 Subject: download cert for SMTP if EIP did not do it. includes refactor of common code for download of certificates and config files. --- changes/bug-3847-start-smtp-without-eip | 1 + src/leap/bitmask/crypto/certs.py | 80 +++++++++++++++++ src/leap/bitmask/gui/mainwindow.py | 68 ++++++++------- src/leap/bitmask/services/__init__.py | 99 ++++++++++++++++++++++ src/leap/bitmask/services/eip/eipbootstrapper.py | 93 ++++---------------- src/leap/bitmask/services/eip/eipconfig.py | 8 +- src/leap/bitmask/services/mail/smtpbootstrapper.py | 97 ++++++++++----------- src/leap/bitmask/services/mail/smtpconfig.py | 36 +++++++- src/leap/bitmask/services/soledad/soledadconfig.py | 8 +- 9 files changed, 319 insertions(+), 171 deletions(-) create mode 100644 changes/bug-3847-start-smtp-without-eip create mode 100644 src/leap/bitmask/crypto/certs.py diff --git a/changes/bug-3847-start-smtp-without-eip b/changes/bug-3847-start-smtp-without-eip new file mode 100644 index 00000000..5ed959a4 --- /dev/null +++ b/changes/bug-3847-start-smtp-without-eip @@ -0,0 +1 @@ + o Allow SMTP to start even when provider does not offer EIP. Closes: #3847 diff --git a/src/leap/bitmask/crypto/certs.py b/src/leap/bitmask/crypto/certs.py new file mode 100644 index 00000000..244decfd --- /dev/null +++ b/src/leap/bitmask/crypto/certs.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# certs.py +# Copyright (C) 2013 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# 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 . +""" +Utilities for dealing with client certs +""" +import logging +import os + +from leap.bitmask.crypto.srpauth import SRPAuth +from leap.bitmask.util.constants import REQUEST_TIMEOUT +from leap.common.files import check_and_fix_urw_only +from leap.common.files import mkdir_p + +from leap.common import certs as leap_certs + +logger = logging.getLogger(__name__) + + +def download_client_cert(provider_config, path, session): + """ + Downloads the client certificate for each service. + + :param provider_config: instance of a ProviderConfig + :type provider_config: ProviderConfig + :param path: the path to download the cert to. + :type path: str + :param session: a fetcher.session instance. For the moment we only + support requests.sessions + :type session: requests.sessions.Session + """ + # TODO we should implement the @with_srp_auth decorator + # again. + srp_auth = SRPAuth(provider_config) + session_id = srp_auth.get_session_id() + cookies = None + if session_id: + cookies = {"_session_id": session_id} + cert_uri = "%s/%s/cert" % ( + provider_config.get_api_uri(), + provider_config.get_api_version()) + logger.debug('getting cert from uri: %s' % cert_uri) + + res = session.get(cert_uri, + verify=provider_config + .get_ca_cert_path(), + cookies=cookies, + timeout=REQUEST_TIMEOUT) + res.raise_for_status() + client_cert = res.content + + if not leap_certs.is_valid_pemfile(client_cert): + # XXX raise more specific exception. + raise Exception("The downloaded certificate is not a " + "valid PEM file") + + mkdir_p(os.path.dirname(path)) + + try: + with open(path, "w") as f: + f.write(client_cert) + except IOError as exc: + logger.error( + "Error saving client cert: %r" % (exc,)) + raise + + check_and_fix_urw_only(path) diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 98cfacb1..e1ed21b6 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1057,17 +1057,6 @@ class MainWindow(QtGui.QMainWindow): self._provider_config, self._smtp_config, True) - else: - if self._enabled_services.count(self.MX_SERVICE) > 0: - pass # TODO show MX status - #self._status_panel.set_eip_status( - # self.tr("%s does not support MX") % - # (self._provider_config.get_domain(),), - # error=True) - else: - pass # TODO show MX status - #self._status_panel.set_eip_status( - # self.tr("MX is disabled")) ################################################################### # Service control methods: smtp @@ -1090,7 +1079,12 @@ class MainWindow(QtGui.QMainWindow): logger.error(data[self._smtp_bootstrapper.ERROR_KEY]) return logger.debug("Done bootstrapping SMTP") + self._check_smtp_config() + def _check_smtp_config(self): + """ + Checks smtp config and tries to download smtp client cert if needed. + """ hosts = self._smtp_config.get_hosts() # TODO handle more than one host and define how to choose if len(hosts) > 0: @@ -1098,24 +1092,40 @@ class MainWindow(QtGui.QMainWindow): logger.debug("Using hostname %s for SMTP" % (hostname,)) host = hosts[hostname][self.IP_KEY].encode("utf-8") port = hosts[hostname][self.PORT_KEY] - # TODO move the start to _start_smtp_service - - # TODO Make the encrypted_only configurable - # TODO pick local smtp port in a better way - # TODO remove hard-coded port and let leap.mail set - # the specific default. - - from leap.mail.smtp import setup_smtp_relay - client_cert = self._eip_config.get_client_cert_path( - self._provider_config) - self._smtp_service = setup_smtp_relay( - port=2013, - keymanager=self._keymanager, - smtp_host=host, - smtp_port=port, - smtp_cert=client_cert, - smtp_key=client_cert, - encrypted_only=False) + + client_cert = self._smtp_config.get_client_cert_path( + self._provider_config, + about_to_download=True) + + if not os.path.isfile(client_cert): + self._smtp_bootstrapper._download_client_certificates() + if os.path.isfile(client_cert): + self._start_smtp_service(host, port, client_cert) + else: + logger.warning("Tried to download email client " + "certificate, but could not find any") + + else: + logger.warning("No smtp hosts configured") + + def _start_smtp_service(self, host, port, cert): + """ + Starts the smtp service. + """ + # TODO Make the encrypted_only configurable + # TODO pick local smtp port in a better way + # TODO remove hard-coded port and let leap.mail set + # the specific default. + + from leap.mail.smtp import setup_smtp_relay + self._smtp_service = setup_smtp_relay( + port=2013, + keymanager=self._keymanager, + smtp_host=host, + smtp_port=port, + smtp_cert=cert, + smtp_key=cert, + encrypted_only=False) def _stop_smtp_service(self): """ diff --git a/src/leap/bitmask/services/__init__.py b/src/leap/bitmask/services/__init__.py index 339f9cc6..2646235d 100644 --- a/src/leap/bitmask/services/__init__.py +++ b/src/leap/bitmask/services/__init__.py @@ -17,8 +17,22 @@ """ Services module. """ +import logging +import os + from PySide import QtCore + +from leap.bitmask.crypto.srpauth import SRPAuth +from leap.bitmask.util.constants import REQUEST_TIMEOUT from leap.bitmask.util.privilege_policies import is_missing_policy_permissions +from leap.bitmask.util.request_helpers import get_content + +from leap.common.check import leap_assert +from leap.common.config.baseconfig import BaseConfig +from leap.common.files import get_mtime + +logger = logging.getLogger(__name__) + DEPLOYED = ["openvpn", "mx"] @@ -70,3 +84,88 @@ def get_supported(services): :rtype: list of str """ return filter(lambda s: s in DEPLOYED, services) + + +def download_service_config(provider_config, service_config, + session, + download_if_needed=True): + """ + Downloads config for a given service. + + :param provider_config: an instance of ProviderConfig + :type provider_config: ProviderConfig + + :param service_config: an instance of a particular Service config. + :type service_config: BaseConfig + + :param session: an instance of a fetcher.session + (currently we're using requests only, but it can be + anything that implements that interface) + :type session: requests.sessions.Session + """ + service_name = service_config.name + service_json = "{0}-service.json".format(service_name) + headers = {} + mtime = get_mtime(os.path.join(service_config.get_path_prefix(), + "leap", + "providers", + provider_config.get_domain(), + service_json)) + if download_if_needed and mtime: + headers['if-modified-since'] = mtime + + api_version = provider_config.get_api_version() + + config_uri = "%s/%s/config/%s-service.json" % ( + provider_config.get_api_uri(), + api_version, + service_name) + logger.debug('Downloading %s config from: %s' % ( + service_name.upper(), + config_uri)) + + # XXX make and use @with_srp_auth decorator + srp_auth = SRPAuth(provider_config) + session_id = srp_auth.get_session_id() + cookies = None + if session_id: + cookies = {"_session_id": session_id} + + res = session.get(config_uri, + verify=provider_config.get_ca_cert_path(), + headers=headers, + timeout=REQUEST_TIMEOUT, + cookies=cookies) + res.raise_for_status() + + service_config.set_api_version(api_version) + + # Not modified + service_path = ("leap", "providers", provider_config.get_domain(), + service_json) + if res.status_code == 304: + logger.debug( + "{0} definition has not been modified".format( + service_name.upper())) + service_config.load(os.path.join(*service_path)) + else: + service_definition, mtime = get_content(res) + service_config.load(data=service_definition, mtime=mtime) + service_config.save(service_path) + + +class ServiceConfig(BaseConfig): + """ + Base class used by the different service configs + """ + + _service_name = None + + @property + def name(self): + """ + Getter for the service name. + Derived classes should assign it. + """ + leap_assert(self._service_name is not None) + return self._service_name diff --git a/src/leap/bitmask/services/eip/eipbootstrapper.py b/src/leap/bitmask/services/eip/eipbootstrapper.py index 6393e53a..5a238a1c 100644 --- a/src/leap/bitmask/services/eip/eipbootstrapper.py +++ b/src/leap/bitmask/services/eip/eipbootstrapper.py @@ -14,25 +14,22 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - """ EIP bootstrapping """ - import logging import os from PySide import QtCore from leap.bitmask.config.providerconfig import ProviderConfig -from leap.bitmask.crypto.srpauth import SRPAuth -from leap.bitmask.services.eip.eipconfig import EIPConfig -from leap.bitmask.util.request_helpers import get_content -from leap.bitmask.util.constants import REQUEST_TIMEOUT +from leap.bitmask.crypto.certs import download_client_cert +from leap.bitmask.services import download_service_config from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper -from leap.common import certs +from leap.bitmask.services.eip.eipconfig import EIPConfig +from leap.common import certs as leap_certs from leap.common.check import leap_assert, leap_assert_type -from leap.common.files import check_and_fix_urw_only, get_mtime, mkdir_p +from leap.common.files import check_and_fix_urw_only logger = logging.getLogger(__name__) @@ -63,50 +60,15 @@ class EIPBootstrapper(AbstractBootstrapper): leap_assert(self._provider_config, "We need a provider configuration!") - logger.debug("Downloading EIP config for %s" % (self._provider_config.get_domain(),)) - api_version = self._provider_config.get_api_version() self._eip_config = EIPConfig() - self._eip_config.set_api_version(api_version) - - headers = {} - mtime = get_mtime(os.path.join(self._eip_config - .get_path_prefix(), - "leap", - "providers", - self._provider_config.get_domain(), - "eip-service.json")) - - if self._download_if_needed and mtime: - headers['if-modified-since'] = mtime - - # there is some confusion with this uri, - # it's in 1/config/eip, config/eip and config/1/eip... - config_uri = "%s/%s/config/eip-service.json" % ( - self._provider_config.get_api_uri(), - api_version) - logger.debug('Downloading eip config from: %s' % config_uri) - - res = self._session.get(config_uri, - verify=self._provider_config - .get_ca_cert_path(), - headers=headers, - timeout=REQUEST_TIMEOUT) - res.raise_for_status() - - # Not modified - if res.status_code == 304: - logger.debug("EIP definition has not been modified") - else: - eip_definition, mtime = get_content(res) - - self._eip_config.load(data=eip_definition, mtime=mtime) - self._eip_config.save(["leap", - "providers", - self._provider_config.get_domain(), - "eip-service.json"]) + download_service_config( + self._provider_config, + self._eip_config, + self._session, + self._download_if_needed) def _download_client_certificates(self, *args): """ @@ -124,40 +86,17 @@ class EIPBootstrapper(AbstractBootstrapper): # For re-download if something is wrong with the cert self._download_if_needed = self._download_if_needed and \ - not certs.should_redownload(client_cert_path) + not leap_certs.should_redownload(client_cert_path) if self._download_if_needed and \ - os.path.exists(client_cert_path): + os.path.isfile(client_cert_path): check_and_fix_urw_only(client_cert_path) return - srp_auth = SRPAuth(self._provider_config) - session_id = srp_auth.get_session_id() - cookies = None - if session_id: - cookies = {"_session_id": session_id} - cert_uri = "%s/%s/cert" % ( - self._provider_config.get_api_uri(), - self._provider_config.get_api_version()) - logger.debug('getting cert from uri: %s' % cert_uri) - res = self._session.get(cert_uri, - verify=self._provider_config - .get_ca_cert_path(), - cookies=cookies, - timeout=REQUEST_TIMEOUT) - res.raise_for_status() - client_cert = res.content - - if not certs.is_valid_pemfile(client_cert): - raise Exception(self.tr("The downloaded certificate is not a " - "valid PEM file")) - - mkdir_p(os.path.dirname(client_cert_path)) - - with open(client_cert_path, "w") as f: - f.write(client_cert) - - check_and_fix_urw_only(client_cert_path) + download_client_cert( + self._provider_config, + client_cert_path, + self._session) def run_eip_setup_checks(self, provider_config, diff --git a/src/leap/bitmask/services/eip/eipconfig.py b/src/leap/bitmask/services/eip/eipconfig.py index 1cb7419e..2241290b 100644 --- a/src/leap/bitmask/services/eip/eipconfig.py +++ b/src/leap/bitmask/services/eip/eipconfig.py @@ -26,9 +26,9 @@ import time import ipaddr from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.services import ServiceConfig from leap.bitmask.services.eip.eipspec import get_schema from leap.common.check import leap_assert, leap_assert_type -from leap.common.config.baseconfig import BaseConfig logger = logging.getLogger(__name__) @@ -144,15 +144,17 @@ class VPNGatewaySelector(object): return -local_offset / 3600 -class EIPConfig(BaseConfig): +class EIPConfig(ServiceConfig): """ Provider configuration abstraction class """ + _service_name = "eip" + OPENVPN_ALLOWED_KEYS = ("auth", "cipher", "tls-cipher") OPENVPN_CIPHERS_REGEX = re.compile("[A-Z0-9\-]+") def __init__(self): - BaseConfig.__init__(self) + ServiceConfig.__init__(self) self._api_version = None def _get_schema(self): diff --git a/src/leap/bitmask/services/mail/smtpbootstrapper.py b/src/leap/bitmask/services/mail/smtpbootstrapper.py index 0e83424c..032d6357 100644 --- a/src/leap/bitmask/services/mail/smtpbootstrapper.py +++ b/src/leap/bitmask/services/mail/smtpbootstrapper.py @@ -14,22 +14,21 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - """ SMTP bootstrapping """ - import logging import os from PySide import QtCore from leap.bitmask.config.providerconfig import ProviderConfig -from leap.bitmask.crypto.srpauth import SRPAuth -from leap.bitmask.util.request_helpers import get_content +from leap.bitmask.crypto.certs import download_client_cert +from leap.bitmask.services import download_service_config from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper +from leap.common import certs as leap_certs from leap.common.check import leap_assert, leap_assert_type -from leap.common.files import get_mtime +from leap.common.files import check_and_fix_urw_only logger = logging.getLogger(__name__) @@ -61,55 +60,45 @@ class SMTPBootstrapper(AbstractBootstrapper): logger.debug("Downloading SMTP config for %s" % (self._provider_config.get_domain(),)) - headers = {} - mtime = get_mtime(os.path.join(self._smtp_config - .get_path_prefix(), - "leap", - "providers", - self._provider_config.get_domain(), - "smtp-service.json")) - - if self._download_if_needed and mtime: - headers['if-modified-since'] = mtime - - api_version = self._provider_config.get_api_version() - - # there is some confusion with this uri, - config_uri = "%s/%s/config/smtp-service.json" % ( - self._provider_config.get_api_uri(), api_version) - - logger.debug('Downloading SMTP config from: %s' % config_uri) - - srp_auth = SRPAuth(self._provider_config) - session_id = srp_auth.get_session_id() - cookies = None - if session_id: - cookies = {"_session_id": session_id} - - res = self._session.get(config_uri, - verify=self._provider_config - .get_ca_cert_path(), - headers=headers, - cookies=cookies) - res.raise_for_status() - - self._smtp_config.set_api_version(api_version) - - # Not modified - if res.status_code == 304: - logger.debug("SMTP definition has not been modified") - self._smtp_config.load(os.path.join( - "leap", "providers", - self._provider_config.get_domain(), - "smtp-service.json")) - else: - smtp_definition, mtime = get_content(res) - - self._smtp_config.load(data=smtp_definition, mtime=mtime) - self._smtp_config.save(["leap", - "providers", - self._provider_config.get_domain(), - "smtp-service.json"]) + download_service_config( + self._provider_config, + self._smtp_config, + self._session, + self._download_if_needed) + + def _download_client_certificates(self, *args): + """ + Downloads the SMTP client certificate for the given provider + + We actually are downloading the certificate for the same uri as + for the EIP config, but we duplicate these bits to allow mail + service to be working in a provider that does not offer EIP. + """ + # TODO factor out with eipboostrapper.download_client_certificates + # TODO this shouldn't be a private method, it's called from + # mainwindow. + leap_assert(self._provider_config, "We need a provider configuration!") + leap_assert(self._smtp_config, "We need an smtp configuration!") + + logger.debug("Downloading SMTP client certificate for %s" % + (self._provider_config.get_domain(),)) + + client_cert_path = self._smtp_config.\ + get_client_cert_path(self._provider_config, + about_to_download=True) + + # For re-download if something is wrong with the cert + self._download_if_needed = self._download_if_needed and \ + not leap_certs.should_redownload(client_cert_path) + + if self._download_if_needed and \ + os.path.isfile(client_cert_path): + check_and_fix_urw_only(client_cert_path) + return + + download_client_cert(self._provider_config, + client_cert_path, + self._session) def run_smtp_setup_checks(self, provider_config, diff --git a/src/leap/bitmask/services/mail/smtpconfig.py b/src/leap/bitmask/services/mail/smtpconfig.py index 20041c30..74c9bc94 100644 --- a/src/leap/bitmask/services/mail/smtpconfig.py +++ b/src/leap/bitmask/services/mail/smtpconfig.py @@ -14,25 +14,28 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - """ SMTP configuration """ import logging +import os +from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.services import ServiceConfig from leap.bitmask.services.mail.smtpspec import get_schema -from leap.common.config.baseconfig import BaseConfig +from leap.common.check import leap_assert, leap_assert_type logger = logging.getLogger(__name__) -class SMTPConfig(BaseConfig): +class SMTPConfig(ServiceConfig): """ SMTP configuration abstraction class """ + _service_name = "smtp" def __init__(self): - BaseConfig.__init__(self) + ServiceConfig.__init__(self) def _get_schema(self): """ @@ -47,3 +50,28 @@ class SMTPConfig(BaseConfig): def get_locations(self): return self._safe_get_value("locations") + + def get_client_cert_path(self, + providerconfig=None, + about_to_download=False): + """ + Returns the path to the certificate used by smtp + """ + + leap_assert(providerconfig, "We need a provider") + leap_assert_type(providerconfig, ProviderConfig) + + cert_path = os.path.join(self.get_path_prefix(), + "leap", + "providers", + providerconfig.get_domain(), + "keys", + "client", + "smtp.pem") + + if not about_to_download: + leap_assert(os.path.exists(cert_path), + "You need to download the certificate first") + logger.debug("Using SMTP cert %s" % (cert_path,)) + + return cert_path diff --git a/src/leap/bitmask/services/soledad/soledadconfig.py b/src/leap/bitmask/services/soledad/soledadconfig.py index 7ed21f77..d3cc7da4 100644 --- a/src/leap/bitmask/services/soledad/soledadconfig.py +++ b/src/leap/bitmask/services/soledad/soledadconfig.py @@ -14,25 +14,25 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - """ Soledad configuration """ import logging +from leap.bitmask.services import ServiceConfig from leap.bitmask.services.soledad.soledadspec import get_schema -from leap.common.config.baseconfig import BaseConfig logger = logging.getLogger(__name__) -class SoledadConfig(BaseConfig): +class SoledadConfig(ServiceConfig): """ Soledad configuration abstraction class """ + _service_name = "soledad" def __init__(self): - BaseConfig.__init__(self) + ServiceConfig.__init__(self) def _get_schema(self): """ -- cgit v1.2.3 From b7f5b83bf1d885bdac98df4c014ca1d0dbf369d8 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 18 Sep 2013 11:35:09 -0400 Subject: bump soledad version in next release requirements --- changes/VERSION_COMPAT | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changes/VERSION_COMPAT b/changes/VERSION_COMPAT index cc00ecf7..469ade25 100644 --- a/changes/VERSION_COMPAT +++ b/changes/VERSION_COMPAT @@ -8,3 +8,6 @@ # # BEGIN DEPENDENCY LIST ------------------------- # leap.foo.bar>=x.y.z + +leap.soledad.client>=0.4.0 # because of backward-incompatible changes + # https://github.com/leapcode/soledad/pull/76 -- cgit v1.2.3 From e0734dd4c3c529c99b7c90d8db1dfb9f09551b24 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 18 Sep 2013 13:19:57 -0300 Subject: Remove unused existing code. --- src/leap/bitmask/gui/preferenceswindow.py | 3 --- src/leap/bitmask/gui/wizard.py | 9 --------- 2 files changed, 12 deletions(-) diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py index 1becfb18..6a1fe589 100644 --- a/src/leap/bitmask/gui/preferenceswindow.py +++ b/src/leap/bitmask/gui/preferenceswindow.py @@ -40,9 +40,6 @@ class PreferencesWindow(QtGui.QDialog): """ Window that displays the preferences. """ - - WEAK_PASSWORDS = ("123456", "qweasd", "qwerty", "password") - def __init__(self, parent, srp_auth, leap_settings, standalone): """ :param parent: parent object of the PreferencesWindow. diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index e004e6cf..4a5bc333 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -555,15 +555,6 @@ class Wizard(QtGui.QWizard): if pageId == self.SERVICES_PAGE: self._populate_services() - def _is_need_eip_password_warning(self): - """ - Returns True if we need to add a warning about eip needing - administrative permissions to start. That can be either - because we are running in standalone mode, or because we could - not find the needed privilege escalation mechanisms being operative. - """ - return self.standalone or is_missing_policy_permissions() - def nextId(self): """ Sets the next page id for the wizard based on wether the user -- cgit v1.2.3 From e196338abec4597862142c5e6ac4e57d1c0b27ce Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 18 Sep 2013 12:26:47 -0400 Subject: update obsolete qt4 dep --- docs/testers/howto.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/testers/howto.rst b/docs/testers/howto.rst index 015a4ab2..61d38787 100644 --- a/docs/testers/howto.rst +++ b/docs/testers/howto.rst @@ -25,8 +25,9 @@ Install dependencies ^^^^^^^^^^^^^^^^^^^^ First, install all the base dependencies plus git, virtualenv and development files needed to compile several extensions:: - apt-get install openvpn git-core python-dev python-qt4 python-setuptools python-virtualenv + apt-get install openvpn git-core python-dev python-pyside python-setuptools python-virtualenv +.. TODO Should review these dependencies. ^^ Bootstrap script ^^^^^^^^^^^^^^^^ -- cgit v1.2.3 From e0e85e8c375ed1afe297b1ff047cb5db13a837b0 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 18 Sep 2013 13:18:16 -0400 Subject: fix keyring problem with imports --- changes/bug_3759-fix-keyring-imports | 1 + pkg/requirements.pip | 3 +-- src/leap/bitmask/util/keyring_helpers.py | 19 +++++++++++++++---- 3 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 changes/bug_3759-fix-keyring-imports diff --git a/changes/bug_3759-fix-keyring-imports b/changes/bug_3759-fix-keyring-imports new file mode 100644 index 00000000..ed489633 --- /dev/null +++ b/changes/bug_3759-fix-keyring-imports @@ -0,0 +1 @@ + o Fix keyring imports so we do not get import errors. Closes: #3759 diff --git a/pkg/requirements.pip b/pkg/requirements.pip index 081f3ba9..ce93b2ef 100644 --- a/pkg/requirements.pip +++ b/pkg/requirements.pip @@ -16,8 +16,7 @@ twisted qt4reactor python-gnupg python-daemon # this should not be needed for Windows. - -keyring<=2.9 # See #3759 +keyring leap.common>=0.3.2 leap.soledad.client>=0.3.0 diff --git a/src/leap/bitmask/util/keyring_helpers.py b/src/leap/bitmask/util/keyring_helpers.py index 8f354f28..4b3eb57f 100644 --- a/src/leap/bitmask/util/keyring_helpers.py +++ b/src/leap/bitmask/util/keyring_helpers.py @@ -14,16 +14,21 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - """ Keyring helpers. """ +import logging import keyring +from keyring.backends.file import EncryptedKeyring, PlaintextKeyring + +logger = logging.getLogger(__name__) + + OBSOLETE_KEYRINGS = [ - keyring.backends.file.EncryptedKeyring, - keyring.backends.file.PlaintextKeyring + EncryptedKeyring, + PlaintextKeyring ] @@ -34,4 +39,10 @@ def has_keyring(): :rtype: bool """ kr = keyring.get_keyring() - return kr is not None and kr.__class__ not in OBSOLETE_KEYRINGS + klass = kr.__class__ + logger.debug("Selected keyring: %s" % (klass,)) + + canuse = kr is not None and klass not in OBSOLETE_KEYRINGS + if not canuse: + logger.debug("Not using this keyring since it is obsolete") + return canuse -- cgit v1.2.3 From 404e5a7c0e5907439610b49a42e2bfd9168c8fc4 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 18 Sep 2013 15:41:23 -0300 Subject: Remove the provider domain item from tray menu. --- src/leap/bitmask/gui/mainwindow.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 1dbf39ef..57dbe083 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -251,10 +251,6 @@ class MainWindow(QtGui.QMainWindow): self._systray = None - self._action_eip_provider = QtGui.QAction( - self.tr("No default provider"), self) - self._action_eip_provider.setEnabled(False) - self._action_eip_status = QtGui.QAction( self.tr("Encrypted Internet is OFF"), self) @@ -594,8 +590,6 @@ class MainWindow(QtGui.QMainWindow): "no default provider configured") return - self._action_eip_provider.setText(default_provider) - self._enabled_services = self._settings.get_enabled_services( default_provider) @@ -626,7 +620,6 @@ class MainWindow(QtGui.QMainWindow): systrayMenu = QtGui.QMenu(self) systrayMenu.addAction(self._action_visible) systrayMenu.addSeparator() - systrayMenu.addAction(self._action_eip_provider) systrayMenu.addAction(self._action_eip_status) systrayMenu.addAction(self._action_eip_startstop) systrayMenu.addAction(self._action_mail_status) @@ -1242,9 +1235,6 @@ class MainWindow(QtGui.QMainWindow): provider = "%s@%s" % (self._logged_user, provider) self._status_panel.set_provider(provider) - - self._action_eip_provider.setText(provider_config.get_domain()) - self._status_panel.eip_started() # XXX refactor into status_panel method? -- cgit v1.2.3 From 9bccf57ef16295e1f1e5effcfa8e84cd0418c677 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 18 Sep 2013 16:39:55 -0300 Subject: Update services' status texts. --- src/leap/bitmask/gui/mainwindow.py | 4 ++-- src/leap/bitmask/gui/statuspanel.py | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 57dbe083..997a1103 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -259,13 +259,13 @@ class MainWindow(QtGui.QMainWindow): self._action_eip_status) self._action_mail_status = QtGui.QAction( - self.tr("Encrypted Mail is OFF"), self) + self.tr("Mail is OFF"), self) self._action_mail_status.setEnabled(False) self._status_panel.set_action_mail_status( self._action_mail_status) self._action_eip_startstop = QtGui.QAction( - self.tr("Turn OFF"), self) + self.tr("Turn ON"), self) self._action_eip_startstop.triggered.connect( self._stop_eip) self._action_eip_startstop.setEnabled(False) diff --git a/src/leap/bitmask/gui/statuspanel.py b/src/leap/bitmask/gui/statuspanel.py index 10e6bca3..2aac8a53 100644 --- a/src/leap/bitmask/gui/statuspanel.py +++ b/src/leap/bitmask/gui/statuspanel.py @@ -347,7 +347,7 @@ class StatusPanelWidget(QtGui.QWidget): """ status = self.tr("Encrypted Internet is {0}").format(self._eip_status) status += '\n' - status += self.tr("Encrypted Mail is {0}").format(self._mx_status) + status += self.tr("Mail is {0}").format(self._mx_status) self._systray.setToolTip(status) def set_action_eip_startstop(self, action_eip_startstop): @@ -550,7 +550,7 @@ class StatusPanelWidget(QtGui.QWidget): "RECONNECTING", "ASSIGN_IP"): selected_pixmap = self.CONNECTING_ICON selected_pixmap_tray = self.CONNECTING_ICON_TRAY - tray_message = self.tr("Turning ON") + tray_message = self.tr("Encrypted Internet is STARTING") elif status in ("CONNECTED"): tray_message = self.tr("Encrypted Internet is ON") selected_pixmap = self.CONNECTED_ICON @@ -565,7 +565,7 @@ class StatusPanelWidget(QtGui.QWidget): def _set_mail_status(self, status, ready=False): """ - Sets the Encrypted Mail status in the label and in the tray icon. + Sets the Mail status in the label and in the tray icon. :param status: the status text to display :type status: unicode @@ -575,13 +575,13 @@ class StatusPanelWidget(QtGui.QWidget): self.ui.lblMailStatus.setText(status) self._mx_status = self.tr('OFF') - tray_status = self.tr('Encrypted Mail is OFF') + tray_status = self.tr('Mail is OFF') icon = QtGui.QPixmap(self.MAIL_OFF_ICON) if ready: icon = QtGui.QPixmap(self.MAIL_ON_ICON) self._mx_status = self.tr('ON') - tray_status = self.tr('Encrypted Mail is ON') + tray_status = self.tr('Mail is ON') self.ui.lblMailIcon.setPixmap(icon) self._action_mail_status.setText(tray_status) -- cgit v1.2.3 From 70c65ad05f22c87aa1008ed01154eb7479bdfe71 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 18 Sep 2013 17:24:10 -0300 Subject: Move EIP status and action to submenu in tray. --- src/leap/bitmask/gui/mainwindow.py | 29 ++++++++++------------------- src/leap/bitmask/gui/statuspanel.py | 16 ++++++++-------- 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 997a1103..37bbf1c4 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -251,26 +251,14 @@ class MainWindow(QtGui.QMainWindow): self._systray = None - self._action_eip_status = QtGui.QAction( - self.tr("Encrypted Internet is OFF"), - self) - self._action_eip_status.setEnabled(False) - self._status_panel.set_action_eip_status( - self._action_eip_status) - - self._action_mail_status = QtGui.QAction( - self.tr("Mail is OFF"), self) + self._action_mail_status = QtGui.QAction(self.tr("Mail is OFF"), self) self._action_mail_status.setEnabled(False) - self._status_panel.set_action_mail_status( - self._action_mail_status) + self._status_panel.set_action_mail_status(self._action_mail_status) - self._action_eip_startstop = QtGui.QAction( - self.tr("Turn ON"), self) - self._action_eip_startstop.triggered.connect( - self._stop_eip) + self._action_eip_startstop = QtGui.QAction(self.tr("Turn ON"), self) + self._action_eip_startstop.triggered.connect(self._stop_eip) self._action_eip_startstop.setEnabled(False) - self._status_panel.set_action_eip_startstop( - self._action_eip_startstop) + self._status_panel.set_action_eip_startstop(self._action_eip_startstop) self._action_preferences = QtGui.QAction(self.tr("Preferences"), self) self._action_preferences.triggered.connect(self._show_preferences) @@ -620,8 +608,11 @@ class MainWindow(QtGui.QMainWindow): systrayMenu = QtGui.QMenu(self) systrayMenu.addAction(self._action_visible) systrayMenu.addSeparator() - systrayMenu.addAction(self._action_eip_status) - systrayMenu.addAction(self._action_eip_startstop) + + eip_menu = systrayMenu.addMenu(self.tr("Encrypted Internet is OFF")) + eip_menu.addAction(self._action_eip_startstop) + self._status_panel.set_eip_status_menu(eip_menu) + systrayMenu.addAction(self._action_mail_status) systrayMenu.addSeparator() systrayMenu.addAction(self._action_preferences) diff --git a/src/leap/bitmask/gui/statuspanel.py b/src/leap/bitmask/gui/statuspanel.py index 2aac8a53..39a8079f 100644 --- a/src/leap/bitmask/gui/statuspanel.py +++ b/src/leap/bitmask/gui/statuspanel.py @@ -130,7 +130,7 @@ class StatusPanelWidget(QtGui.QWidget): QtGui.QWidget.__init__(self, parent) self._systray = None - self._action_eip_status = None + self._eip_status_menu = None self.ui = Ui_StatusPanel() self.ui.setupUi(self) @@ -359,15 +359,15 @@ class StatusPanelWidget(QtGui.QWidget): """ self._action_eip_startstop = action_eip_startstop - def set_action_eip_status(self, action_eip_status): + def set_eip_status_menu(self, eip_status_menu): """ - Sets the action_eip_status to use. + Sets the eip_status_menu to use. - :param action_eip_status: action_eip_status to be used - :type action_eip_status: QtGui.QAction + :param eip_status_menu: eip_status_menu to be used + :type eip_status_menu: QtGui.QMenu """ - leap_assert_type(action_eip_status, QtGui.QAction) - self._action_eip_status = action_eip_status + leap_assert_type(eip_status_menu, QtGui.QMenu) + self._eip_status_menu = eip_status_menu def set_action_mail_status(self, action_mail_status): """ @@ -558,7 +558,7 @@ class StatusPanelWidget(QtGui.QWidget): self.set_icon(selected_pixmap) self._systray.setIcon(QtGui.QIcon(selected_pixmap_tray)) - self._action_eip_status.setText(tray_message) + self._eip_status_menu.setTitle(tray_message) def set_provider(self, provider): self.ui.lblProvider.setText(provider) -- cgit v1.2.3 From c48ee72ba2e0b016cb6919a3197831ef4292056d Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 18 Sep 2013 17:41:50 -0300 Subject: Add changelog. Closes #3792. --- changes/feature-3792_systray-improvements | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 changes/feature-3792_systray-improvements diff --git a/changes/feature-3792_systray-improvements b/changes/feature-3792_systray-improvements new file mode 100644 index 00000000..e10a29c2 --- /dev/null +++ b/changes/feature-3792_systray-improvements @@ -0,0 +1,6 @@ + o Tasktray menu changes, closes #3792. + - Remove the provider domain item (e.g. bitmask.net). + - Rename the EIP status menu items to be more descriptive. + - Change the EIP status menu items from disabled menu items + to submenus with children. + - Move the EIP action menu items under the EIP status submenu tree. -- cgit v1.2.3 From 6cd19c3b67d76268bab5f93d3168164ec02f603d Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 18 Sep 2013 14:27:15 -0300 Subject: Move STANDALONE flag to a module and unify paths queries. --- changes/feature-3636_standalone-flag-to-module | 2 + src/leap/bitmask/app.py | 16 ++--- src/leap/bitmask/config/flags.py | 32 ++++++++++ src/leap/bitmask/config/leapsettings.py | 15 ++--- src/leap/bitmask/config/providerconfig.py | 11 ++-- src/leap/bitmask/gui/mainwindow.py | 18 ++---- src/leap/bitmask/gui/preferenceswindow.py | 13 ++--- src/leap/bitmask/gui/wizard.py | 11 +--- src/leap/bitmask/services/__init__.py | 14 ++--- src/leap/bitmask/services/eip/eipbootstrapper.py | 1 + src/leap/bitmask/services/eip/eipconfig.py | 10 ++-- .../bitmask/services/eip/providerbootstrapper.py | 6 +- src/leap/bitmask/services/eip/vpnlaunchers.py | 68 +++++++++------------- src/leap/bitmask/services/eip/vpnprocess.py | 2 +- src/leap/bitmask/services/mail/smtpconfig.py | 10 ++-- .../services/soledad/soledadbootstrapper.py | 24 +++----- src/leap/bitmask/util/__init__.py | 7 +++ src/leap/bitmask/util/log_silencer.py | 9 +-- 18 files changed, 123 insertions(+), 146 deletions(-) create mode 100644 changes/feature-3636_standalone-flag-to-module create mode 100644 src/leap/bitmask/config/flags.py diff --git a/changes/feature-3636_standalone-flag-to-module b/changes/feature-3636_standalone-flag-to-module new file mode 100644 index 00000000..caf16b1a --- /dev/null +++ b/changes/feature-3636_standalone-flag-to-module @@ -0,0 +1,2 @@ + o Move STANDALONE flag to a module and unify get_path_prefix queries. + Closes #3636. diff --git a/src/leap/bitmask/app.py b/src/leap/bitmask/app.py index 8c839edc..4edb2d4c 100644 --- a/src/leap/bitmask/app.py +++ b/src/leap/bitmask/app.py @@ -53,7 +53,7 @@ def install_qtreactor(logger): logger.debug("Qt4 reactor installed") -def add_logger_handlers(debug=False, logfile=None, standalone=False): +def add_logger_handlers(debug=False, logfile=None): """ Create the logger and attach the handlers. @@ -82,7 +82,7 @@ def add_logger_handlers(debug=False, logfile=None, standalone=False): console.setLevel(level) console.setFormatter(formatter) - silencer = log_silencer.SelectiveSilencerFilter(standalone=standalone) + silencer = log_silencer.SelectiveSilencerFilter() console.addFilter(silencer) logger.addHandler(console) logger.debug('Console handler plugged!') @@ -149,12 +149,10 @@ def main(): # Given how paths and bundling works, we need to delay the imports # of certain parts that depend on this path settings. # So first we set all the places where standalone might be queried. - from leap.bitmask.config.providerconfig import ProviderConfig + from leap.bitmask.config import flags from leap.common.config.baseconfig import BaseConfig - from leap.bitmask.services.eip.eipconfig import EIPConfig + flags.STANDALONE = standalone BaseConfig.standalone = standalone - ProviderConfig.standalone = standalone - EIPConfig.standalone = standalone # And then we import all the other stuff from leap.bitmask.gui import locale_rc @@ -167,7 +165,7 @@ def main(): # pylint: avoid unused import assert(locale_rc) - logger = add_logger_handlers(debug, logfile, standalone) + logger = add_logger_handlers(debug, logfile) replace_stdout_stderr_with_logging(logger) if not we_are_the_one_and_only(): @@ -185,9 +183,6 @@ def main(): logger.info('Starting app') - ProviderConfig.standalone = standalone - EIPConfig.standalone = standalone - # We force the style if on KDE so that it doesn't load all the kde # libs, which causes a compatibility issue in some systems. # For more info, see issue #3194 @@ -228,7 +223,6 @@ def main(): window = MainWindow( lambda: twisted_main.quit(app), - standalone=standalone, openvpn_verb=openvpn_verb, bypass_checks=bypass_checks) diff --git a/src/leap/bitmask/config/flags.py b/src/leap/bitmask/config/flags.py new file mode 100644 index 00000000..98395def --- /dev/null +++ b/src/leap/bitmask/config/flags.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# flags.py +# Copyright (C) 2013 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# 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 . +""" +This file is meant to be used to store global flags that affect the +application. + +WARNING: You should NOT use this kind of flags unless you're sure of what + you're doing, and someone else tells you that you're right. + Most of the times there is a better and safer alternative. +""" + +# The STANDALONE flag is used to: +# - define a different set of messages for the application when is running +# inside of a bundle or installed system wide. +# - use a relative or system wide path to find the configuration files. +# - search for binaries inside the bundled app instead of the system ones. +# e.g.: openvpn, gpg +STANDALONE = False diff --git a/src/leap/bitmask/config/leapsettings.py b/src/leap/bitmask/config/leapsettings.py index 7d8b5977..338fa475 100644 --- a/src/leap/bitmask/config/leapsettings.py +++ b/src/leap/bitmask/config/leapsettings.py @@ -24,7 +24,7 @@ import logging from PySide import QtCore from leap.common.check import leap_assert, leap_assert_type -from leap.common.config import get_path_prefix +from leap.bitmask.util import get_path_prefix logger = logging.getLogger(__name__) @@ -71,15 +71,8 @@ class LeapSettings(object): # values GATEWAY_AUTOMATIC = "Automatic" - def __init__(self, standalone=False): - """ - Constructor - - :param standalone: parameter used to define the location of the config. - :type standalone: bool - """ - self._path_prefix = get_path_prefix(standalone=standalone) - settings_path = os.path.join(self._path_prefix, + def __init__(self): + settings_path = os.path.join(get_path_prefix(), "leap", self.CONFIG_NAME) self._settings = QtCore.QSettings(settings_path, @@ -132,7 +125,7 @@ class LeapSettings(object): # other things, not just the directories providers = [] try: - providers_path = os.path.join(self._path_prefix, + providers_path = os.path.join(get_path_prefix(), "leap", "providers") providers = os.listdir(providers_path) except Exception as e: diff --git a/src/leap/bitmask/config/providerconfig.py b/src/leap/bitmask/config/providerconfig.py index a7808399..c8c8a59e 100644 --- a/src/leap/bitmask/config/providerconfig.py +++ b/src/leap/bitmask/config/providerconfig.py @@ -21,10 +21,11 @@ Provider configuration import logging import os -from leap.bitmask.config.provider_spec import leap_provider_spec from leap.common.check import leap_check from leap.common.config.baseconfig import BaseConfig, LocalizedKey +from leap.bitmask.config.provider_spec import leap_provider_spec from leap.bitmask.services import get_service_display_name +from leap.bitmask.util import get_path_prefix logger = logging.getLogger(__name__) @@ -151,13 +152,9 @@ class ProviderConfig(BaseConfig): :type about_to_download: bool """ - cert_path = os.path.join(self.get_path_prefix(), - "leap", - "providers", + cert_path = os.path.join(get_path_prefix(), "leap", "providers", self.get_domain(), - "keys", - "ca", - "cacert.pem") + "keys", "ca", "cacert.pem") if not about_to_download: cert_exists = os.path.exists(cert_path) diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 1dbf39ef..6a1b8bde 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -28,6 +28,7 @@ import keyring from PySide import QtCore, QtGui from twisted.internet import threads +from leap.bitmask.config import flags from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.crypto.srpauth import SRPAuth @@ -107,7 +108,6 @@ class MainWindow(QtGui.QMainWindow): user_stopped_eip = False def __init__(self, quit_callback, - standalone=False, openvpn_verb=1, bypass_checks=False): """ @@ -117,10 +117,6 @@ class MainWindow(QtGui.QMainWindow): the application. :type quit_callback: callable - :param standalone: Set to true if the app should use configs - inside its pwd - :type standalone: bool - :param bypass_checks: Set to true if the app should bypass first round of checks for CA certificates at bootstrap @@ -147,7 +143,7 @@ class MainWindow(QtGui.QMainWindow): self.ui = Ui_MainWindow() self.ui.setupUi(self) - self._settings = LeapSettings(standalone) + self._settings = LeapSettings() self._login_widget = LoginWidget( self._settings, @@ -176,7 +172,6 @@ class MainWindow(QtGui.QMainWindow): # This is loaded only once, there's a bug when doing that more # than once - self._standalone = standalone self._provider_config = ProviderConfig() # Used for automatic start of EIP self._provisional_provider_config = ProviderConfig() @@ -322,8 +317,7 @@ class MainWindow(QtGui.QMainWindow): if self._first_run(): self._wizard_firstrun = True - self._wizard = Wizard(standalone=standalone, - bypass_checks=bypass_checks) + self._wizard = Wizard(bypass_checks=bypass_checks) # Give this window time to finish init and then show the wizard QtCore.QTimer.singleShot(1, self._launch_wizard) self._wizard.accepted.connect(self._finish_init) @@ -428,8 +422,7 @@ class MainWindow(QtGui.QMainWindow): Displays the preferences window. """ - preferences_window = PreferencesWindow( - self, self._srp_auth, self._settings, self._standalone) + preferences_window = PreferencesWindow(self, self._srp_auth) if self._soledad_ready: preferences_window.set_soledad_ready(self._soledad) @@ -981,8 +974,7 @@ class MainWindow(QtGui.QMainWindow): self._provider_config, self._login_widget.get_user(), self._login_widget.get_password(), - download_if_needed=True, - standalone=self._standalone) + download_if_needed=True) self._download_eip_config() diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py index 6a1fe589..2d17f6c2 100644 --- a/src/leap/bitmask/gui/preferenceswindow.py +++ b/src/leap/bitmask/gui/preferenceswindow.py @@ -24,6 +24,7 @@ import logging from functools import partial from PySide import QtCore, QtGui +from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.gui.ui_preferences import Ui_Preferences from leap.soledad.client import NoStorageSecret from leap.bitmask.crypto.srpauth import SRPAuthBadPassword @@ -40,23 +41,18 @@ class PreferencesWindow(QtGui.QDialog): """ Window that displays the preferences. """ - def __init__(self, parent, srp_auth, leap_settings, standalone): + def __init__(self, parent, srp_auth): """ :param parent: parent object of the PreferencesWindow. :parent type: QWidget :param srp_auth: SRPAuth object configured in the main app. :type srp_auth: SRPAuth - :param standalone: If True, the application is running as standalone - and the preferences dialog should display some - messages according to this. - :type standalone: bool """ QtGui.QDialog.__init__(self, parent) self.AUTOMATIC_GATEWAY_LABEL = self.tr("Automatic") self._srp_auth = srp_auth - self._settings = leap_settings - self._standalone = standalone + self._settings = LeapSettings() self._soledad = None # Load UI @@ -322,8 +318,7 @@ class PreferencesWindow(QtGui.QDialog): for service in services: try: checkbox = QtGui.QCheckBox(self) - service_label = get_service_display_name( - service, self._standalone) + service_label = get_service_display_name(service) checkbox.setText(service_label) self.ui.vlServices.addWidget(checkbox) diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index 4a5bc333..45734b81 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -27,6 +27,7 @@ from functools import partial from PySide import QtCore, QtGui from twisted.internet import threads +from leap.bitmask.config import flags from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.crypto.srpregister import SRPRegister from leap.bitmask.util.privilege_policies import is_missing_policy_permissions @@ -58,21 +59,16 @@ class Wizard(QtGui.QWizard): BARE_USERNAME_REGEX = r"^[A-Za-z\d_]+$" - def __init__(self, standalone=False, bypass_checks=False): + def __init__(self, bypass_checks=False): """ Constructor for the main Wizard. - :param standalone: If True, the application is running as standalone - and the wizard should display some messages according to this. - :type standalone: bool :param bypass_checks: Set to true if the app should bypass first round of checks for CA certificates at bootstrap :type bypass_checks: bool """ QtGui.QWizard.__init__(self) - self.standalone = standalone - self.ui = Ui_Wizard() self.ui.setupUi(self) @@ -489,8 +485,7 @@ class Wizard(QtGui.QWizard): try: if service not in self._shown_services: checkbox = QtGui.QCheckBox(self) - service_label = get_service_display_name( - service, self.standalone) + service_label = get_service_display_name(service) checkbox.setText(service_label) self.ui.serviceListLayout.addWidget(checkbox) diff --git a/src/leap/bitmask/services/__init__.py b/src/leap/bitmask/services/__init__.py index 2646235d..afce72f6 100644 --- a/src/leap/bitmask/services/__init__.py +++ b/src/leap/bitmask/services/__init__.py @@ -22,10 +22,12 @@ import os from PySide import QtCore +from leap.bitmask.config import flags from leap.bitmask.crypto.srpauth import SRPAuth from leap.bitmask.util.constants import REQUEST_TIMEOUT from leap.bitmask.util.privilege_policies import is_missing_policy_permissions from leap.bitmask.util.request_helpers import get_content +from leap.bitmask.util import get_path_prefix from leap.common.check import leap_assert from leap.common.config.baseconfig import BaseConfig @@ -37,7 +39,7 @@ logger = logging.getLogger(__name__) DEPLOYED = ["openvpn", "mx"] -def get_service_display_name(service, standalone=False): +def get_service_display_name(service): """ Returns the name to display of the given service. If there is no configured name for that service, then returns the same @@ -45,9 +47,6 @@ def get_service_display_name(service, standalone=False): :param service: the 'machine' service name :type service: str - :param standalone: True if the app is running in a standalone mode, used - to display messages according that. - :type standalone: bool :rtype: str """ @@ -67,7 +66,7 @@ def get_service_display_name(service, standalone=False): # administrative permissions to start. That can be either # because we are running in standalone mode, or because we could # not find the needed privilege escalation mechanisms being operative. - if standalone or is_missing_policy_permissions(): + if flags.STANDALONE or is_missing_policy_permissions(): EIP_LABEL += " " + _tr("(will need admin password to start)") return service_display.get(service, service) @@ -106,9 +105,8 @@ def download_service_config(provider_config, service_config, service_name = service_config.name service_json = "{0}-service.json".format(service_name) headers = {} - mtime = get_mtime(os.path.join(service_config.get_path_prefix(), - "leap", - "providers", + mtime = get_mtime(os.path.join(get_path_prefix(), + "leap", "providers", provider_config.get_domain(), service_json)) if download_if_needed and mtime: diff --git a/src/leap/bitmask/services/eip/eipbootstrapper.py b/src/leap/bitmask/services/eip/eipbootstrapper.py index 5a238a1c..885c4420 100644 --- a/src/leap/bitmask/services/eip/eipbootstrapper.py +++ b/src/leap/bitmask/services/eip/eipbootstrapper.py @@ -28,6 +28,7 @@ from leap.bitmask.services import download_service_config from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper from leap.bitmask.services.eip.eipconfig import EIPConfig from leap.common import certs as leap_certs +from leap.bitmask.util import get_path_prefix from leap.common.check import leap_assert, leap_assert_type from leap.common.files import check_and_fix_urw_only diff --git a/src/leap/bitmask/services/eip/eipconfig.py b/src/leap/bitmask/services/eip/eipconfig.py index 2241290b..466a644c 100644 --- a/src/leap/bitmask/services/eip/eipconfig.py +++ b/src/leap/bitmask/services/eip/eipconfig.py @@ -28,6 +28,7 @@ import ipaddr from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.services import ServiceConfig from leap.bitmask.services.eip.eipspec import get_schema +from leap.bitmask.util import get_path_prefix from leap.common.check import leap_assert, leap_assert_type logger = logging.getLogger(__name__) @@ -238,13 +239,10 @@ class EIPConfig(ServiceConfig): leap_assert(providerconfig, "We need a provider") leap_assert_type(providerconfig, ProviderConfig) - cert_path = os.path.join(self.get_path_prefix(), - "leap", - "providers", + cert_path = os.path.join(get_path_prefix(), + "leap", "providers", providerconfig.get_domain(), - "keys", - "client", - "openvpn.pem") + "keys", "client", "openvpn.pem") if not about_to_download: leap_assert(os.path.exists(cert_path), diff --git a/src/leap/bitmask/services/eip/providerbootstrapper.py b/src/leap/bitmask/services/eip/providerbootstrapper.py index ac3a44db..3b7c9899 100644 --- a/src/leap/bitmask/services/eip/providerbootstrapper.py +++ b/src/leap/bitmask/services/eip/providerbootstrapper.py @@ -28,6 +28,7 @@ from PySide import QtCore from leap.bitmask.config.providerconfig import ProviderConfig, MissingCACert from leap.bitmask.util.request_helpers import get_content +from leap.bitmask.util import get_path_prefix from leap.bitmask.util.constants import REQUEST_TIMEOUT from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper from leap.bitmask.provider.supportedapis import SupportedAPIs @@ -133,9 +134,8 @@ class ProviderBootstrapper(AbstractBootstrapper): headers = {} - provider_json = os.path.join( - ProviderConfig().get_path_prefix(), "leap", "providers", - self._domain, "provider.json") + provider_json = os.path.join(get_path_prefix(), "leap", "providers", + self._domain, "provider.json") mtime = get_mtime(provider_json) if self._download_if_needed and mtime: diff --git a/src/leap/bitmask/services/eip/vpnlaunchers.py b/src/leap/bitmask/services/eip/vpnlaunchers.py index a50da8b9..daa0d81f 100644 --- a/src/leap/bitmask/services/eip/vpnlaunchers.py +++ b/src/leap/bitmask/services/eip/vpnlaunchers.py @@ -34,16 +34,19 @@ from abc import ABCMeta, abstractmethod from functools import partial from time import sleep +from leap.bitmask.config import flags from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.services.eip.eipconfig import EIPConfig, VPNGatewaySelector from leap.bitmask.util import first +from leap.bitmask.util import get_path_prefix from leap.bitmask.util.privilege_policies import LinuxPolicyChecker from leap.bitmask.util import privilege_policies from leap.common.check import leap_assert, leap_assert_type from leap.common.files import which + logger = logging.getLogger(__name__) @@ -98,15 +101,12 @@ class VPNLauncher(object): return [] @abstractmethod - def get_vpn_env(self, providerconfig): + def get_vpn_env(self): """ Returns a dictionary with the custom env for the platform. This is mainly used for setting LD_LIBRARY_PATH to the correct path when distributing a standalone client - :param providerconfig: provider specific configuration - :type providerconfig: ProviderConfig - :rtype: dict """ return {} @@ -220,14 +220,13 @@ def _is_auth_agent_running(): return any(is_running) -def _try_to_launch_agent(standalone=False): +def _try_to_launch_agent(): """ Tries to launch a polkit daemon. """ env = None - if standalone is True: - env = { - "PYTHONPATH": os.path.abspath('../../../../lib/')} + if flags.STANDALONE is True: + env = {"PYTHONPATH": os.path.abspath('../../../../lib/')} try: # We need to quote the command because subprocess call # will do "sh -c 'foo'", so if we do not quoute it we'll end @@ -247,8 +246,7 @@ class LinuxVPNLauncher(VPNLauncher): PKEXEC_BIN = 'pkexec' OPENVPN_BIN = 'openvpn' OPENVPN_BIN_PATH = os.path.join( - ProviderConfig().get_path_prefix(), - "..", "apps", "eip", OPENVPN_BIN) + get_path_prefix(), "..", "apps", "eip", OPENVPN_BIN) SYSTEM_CONFIG = "/etc/leap" UP_DOWN_FILE = "resolv-update" @@ -320,7 +318,7 @@ class LinuxVPNLauncher(VPNLauncher): """ if _is_pkexec_in_system(): if not _is_auth_agent_running(): - _try_to_launch_agent(ProviderConfig.standalone) + _try_to_launch_agent() sleep(0.5) if _is_auth_agent_running(): pkexec_possibilities = which(kls.PKEXEC_BIN) @@ -397,10 +395,9 @@ class LinuxVPNLauncher(VPNLauncher): leap_assert(socket_port, "We need a socket port!") kwargs = {} - if ProviderConfig.standalone: + if flags.STANDALONE: kwargs['path_extension'] = os.path.join( - providerconfig.get_path_prefix(), - "..", "apps", "eip") + get_path_prefix(), "..", "apps", "eip") openvpn_possibilities = which(self.OPENVPN_BIN, **kwargs) @@ -423,7 +420,7 @@ class LinuxVPNLauncher(VPNLauncher): args += ['--verb', '%d' % (openvpn_verb,)] gateways = [] - leap_settings = LeapSettings(ProviderConfig.standalone) + leap_settings = LeapSettings() domain = providerconfig.get_domain() gateway_conf = leap_settings.get_selected_gateway(domain) @@ -513,23 +510,17 @@ class LinuxVPNLauncher(VPNLauncher): return [openvpn] + args - def get_vpn_env(self, providerconfig): + def get_vpn_env(self): """ Returns a dictionary with the custom env for the platform. This is mainly used for setting LD_LIBRARY_PATH to the correct path when distributing a standalone client - :param providerconfig: provider specific configuration - :type providerconfig: ProviderConfig - :rtype: dict """ - leap_assert(providerconfig, "We need a provider config") - leap_assert_type(providerconfig, ProviderConfig) - - return {"LD_LIBRARY_PATH": os.path.join( - providerconfig.get_path_prefix(), - "..", "lib")} + return { + "LD_LIBRARY_PATH": os.path.join(get_path_prefix(), "..", "lib") + } class DarwinVPNLauncher(VPNLauncher): @@ -664,10 +655,9 @@ class DarwinVPNLauncher(VPNLauncher): raise EIPNoTunKextLoaded kwargs = {} - if ProviderConfig.standalone: + if flags.STANDALONE: kwargs['path_extension'] = os.path.join( - providerconfig.get_path_prefix(), - "..", "apps", "eip") + get_path_prefix(), "..", "apps", "eip") openvpn_possibilities = which( self.OPENVPN_BIN, @@ -686,7 +676,7 @@ class DarwinVPNLauncher(VPNLauncher): args += ['--verb', '%d' % (openvpn_verb,)] gateways = [] - leap_settings = LeapSettings(ProviderConfig.standalone) + leap_settings = LeapSettings() domain = providerconfig.get_domain() gateway_conf = leap_settings.get_selected_gateway(domain) @@ -787,20 +777,17 @@ class DarwinVPNLauncher(VPNLauncher): return [command] + cmd_args - def get_vpn_env(self, providerconfig): + def get_vpn_env(self): """ Returns a dictionary with the custom env for the platform. This is mainly used for setting LD_LIBRARY_PATH to the correct path when distributing a standalone client - :param providerconfig: provider specific configuration - :type providerconfig: ProviderConfig - :rtype: dict """ - return {"DYLD_LIBRARY_PATH": os.path.join( - providerconfig.get_path_prefix(), - "..", "lib")} + return { + "DYLD_LIBRARY_PATH": os.path.join(get_path_prefix(), "..", "lib") + } class WindowsVPNLauncher(VPNLauncher): @@ -852,7 +839,7 @@ class WindowsVPNLauncher(VPNLauncher): openvpn_possibilities = which( self.OPENVPN_BIN, - path_extension=os.path.join(providerconfig.get_path_prefix(), + path_extension=os.path.join(get_path_prefix(), "..", "apps", "eip")) if len(openvpn_possibilities) == 0: @@ -869,7 +856,7 @@ class WindowsVPNLauncher(VPNLauncher): args += ['--verb', '%d' % (openvpn_verb,)] gateways = [] - leap_settings = LeapSettings(ProviderConfig.standalone) + leap_settings = LeapSettings() domain = providerconfig.get_domain() gateway_conf = leap_settings.get_selected_gateway(domain) @@ -936,15 +923,12 @@ class WindowsVPNLauncher(VPNLauncher): return [openvpn] + args - def get_vpn_env(self, providerconfig): + def get_vpn_env(self): """ Returns a dictionary with the custom env for the platform. This is mainly used for setting LD_LIBRARY_PATH to the correct path when distributing a standalone client - :param providerconfig: provider specific configuration - :type providerconfig: ProviderConfig - :rtype: dict """ return {} diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index a896b60c..c01da372 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -536,7 +536,7 @@ class VPNManager(object): """ Return a dict containing the vpn environment to be used. """ - return self._launcher.get_vpn_env(self._providerconfig) + return self._launcher.get_vpn_env() def terminate_openvpn(self, shutdown=False): """ diff --git a/src/leap/bitmask/services/mail/smtpconfig.py b/src/leap/bitmask/services/mail/smtpconfig.py index 74c9bc94..09f90314 100644 --- a/src/leap/bitmask/services/mail/smtpconfig.py +++ b/src/leap/bitmask/services/mail/smtpconfig.py @@ -23,6 +23,7 @@ import os from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.services import ServiceConfig from leap.bitmask.services.mail.smtpspec import get_schema +from leap.bitmask.util import get_path_prefix from leap.common.check import leap_assert, leap_assert_type logger = logging.getLogger(__name__) @@ -61,13 +62,10 @@ class SMTPConfig(ServiceConfig): leap_assert(providerconfig, "We need a provider") leap_assert_type(providerconfig, ProviderConfig) - cert_path = os.path.join(self.get_path_prefix(), - "leap", - "providers", + cert_path = os.path.join(get_path_prefix(), + "leap", "providers", providerconfig.get_domain(), - "keys", - "client", - "smtp.pem") + "keys", "client", "smtp.pem") if not about_to_download: leap_assert(os.path.exists(cert_path), diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index 3bbfea85..cac91440 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -26,11 +26,13 @@ import socket from PySide import QtCore from u1db import errors as u1db_errors +from leap.bitmask.config import flags from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.crypto.srpauth import SRPAuth from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper from leap.bitmask.services.soledad.soledadconfig import SoledadConfig from leap.bitmask.util.request_helpers import get_content +from leap.bitmask.util import get_path_prefix from leap.common.check import leap_assert, leap_assert_type from leap.common.files import get_mtime from leap.keymanager import KeyManager, openpgp @@ -120,8 +122,7 @@ class SoledadBootstrapper(AbstractBootstrapper): srp_auth = self.srpauth uuid = srp_auth.get_uid() - prefix = os.path.join(self._soledad_config.get_path_prefix(), - "leap", "soledad") + prefix = os.path.join(get_path_prefix(), "leap", "soledad") secrets_path = "%s/%s.secret" % (prefix, uuid) local_db_path = "%s/%s.db" % (prefix, uuid) @@ -186,11 +187,9 @@ class SoledadBootstrapper(AbstractBootstrapper): headers = {} mtime = get_mtime( - os.path.join( - self._soledad_config.get_path_prefix(), - "leap", "providers", - self._provider_config.get_domain(), - "soledad-service.json")) + os.path.join(get_path_prefix(), "leap", "providers", + self._provider_config.get_domain(), + "soledad-service.json")) if self._download_if_needed and mtime: headers['if-modified-since'] = mtime @@ -256,8 +255,8 @@ class SoledadBootstrapper(AbstractBootstrapper): # TODO: Fix for Windows gpgbin = "/usr/bin/gpg" - if self._standalone: - gpgbin = os.path.join(self._provider_config.get_path_prefix(), + if flags.STANDALONE: + gpgbin = os.path.join(get_path_prefix(), "..", "apps", "mail", "gpg") self._keymanager = KeyManager( @@ -284,8 +283,7 @@ class SoledadBootstrapper(AbstractBootstrapper): provider_config, user, password, - download_if_needed=False, - standalone=False): + download_if_needed=False): """ Starts the checks needed for a new soledad setup @@ -299,9 +297,6 @@ class SoledadBootstrapper(AbstractBootstrapper): files if the have changed since the time it was previously downloaded. :type download_if_needed: bool - :param standalone: If True, it'll look for paths inside the - bundle (like for gpg) - :type standalone: bool """ leap_assert_type(provider_config, ProviderConfig) @@ -310,7 +305,6 @@ class SoledadBootstrapper(AbstractBootstrapper): self._download_if_needed = download_if_needed self._user = user self._password = password - self._standalone = standalone cb_chain = [ (self._download_config, self.download_config), diff --git a/src/leap/bitmask/util/__init__.py b/src/leap/bitmask/util/__init__.py index 78efcb6e..f762a350 100644 --- a/src/leap/bitmask/util/__init__.py +++ b/src/leap/bitmask/util/__init__.py @@ -20,6 +20,13 @@ Some small and handy functions. import datetime import os +from leap.bitmask.config import flags +from leap.common.config import get_path_prefix as common_get_path_prefix + + +def get_path_prefix(): + return common_get_path_prefix(flags.STANDALONE) + def first(things): """ diff --git a/src/leap/bitmask/util/log_silencer.py b/src/leap/bitmask/util/log_silencer.py index 09aa2cff..b9f69ad2 100644 --- a/src/leap/bitmask/util/log_silencer.py +++ b/src/leap/bitmask/util/log_silencer.py @@ -21,7 +21,7 @@ import logging import os import re -from leap.common.config import get_path_prefix +from leap.bitmask.util import get_path_prefix class SelectiveSilencerFilter(logging.Filter): @@ -48,12 +48,11 @@ class SelectiveSilencerFilter(logging.Filter): 'leap.common.events', ) - def __init__(self, standalone=False): + def __init__(self): """ Tries to load silencer rules from the default path, or load from the SILENCER_RULES tuple if not found. """ - self.standalone = standalone self.rules = None if os.path.isfile(self._rules_path): self.rules = self._load_rules() @@ -65,9 +64,7 @@ class SelectiveSilencerFilter(logging.Filter): """ The configuration file for custom ignore rules. """ - return os.path.join( - get_path_prefix(standalone=self.standalone), - "leap", self.CONFIG_NAME) + return os.path.join(get_path_prefix(), "leap", self.CONFIG_NAME) def _load_rules(self): """ -- cgit v1.2.3 From 50cddfdc2a9624a84d624be93bcc01b9b81d39d8 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 16 Sep 2013 19:07:18 -0300 Subject: Use generic username/password message. --- changes/bug-3656_generic-username-password-message | 2 ++ src/leap/bitmask/crypto/srpauth.py | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 changes/bug-3656_generic-username-password-message diff --git a/changes/bug-3656_generic-username-password-message b/changes/bug-3656_generic-username-password-message new file mode 100644 index 00000000..8e6e3e2f --- /dev/null +++ b/changes/bug-3656_generic-username-password-message @@ -0,0 +1,2 @@ + o Use generic bad username/password message instead of specific ones when + the user uses incorrect data during login. Closes #3656. diff --git a/src/leap/bitmask/crypto/srpauth.py b/src/leap/bitmask/crypto/srpauth.py index 776fb2cc..8477ea9e 100644 --- a/src/leap/bitmask/crypto/srpauth.py +++ b/src/leap/bitmask/crypto/srpauth.py @@ -171,6 +171,9 @@ class SRPAuth(QtCore.QObject): self._srp_user = None self._srp_a = None + # Error msg displayed if the username or the password is invalid + self._WRONG_USER_PASS = self.tr("Invalid username or password.") + # User credentials stored for password changing checks self._username = None self._password = None @@ -265,7 +268,7 @@ class SRPAuth(QtCore.QObject): "Status code = %r. Content: %r" % (init_session.status_code, content)) if init_session.status_code == 422: - raise SRPAuthUnknownUser(self.tr("Unknown user")) + raise SRPAuthUnknownUser(self._WRONG_USER_PASS) raise SRPAuthBadStatusCode(self.tr("There was a problem with" " authentication")) @@ -354,7 +357,7 @@ class SRPAuth(QtCore.QObject): "received: %s", (content,)) logger.error("[%s] Wrong password (HAMK): [%s]" % (auth_result.status_code, error)) - raise SRPAuthBadPassword(self.tr("Wrong password")) + raise SRPAuthBadPassword(self._WRONG_USER_PASS) if auth_result.status_code not in (200,): logger.error("No valid response (HAMK): " -- cgit v1.2.3 From 8ff009fde1659a2af4ca4c380ef5a56f18a1c6a7 Mon Sep 17 00:00:00 2001 From: KwadroNaut Date: Thu, 19 Sep 2013 10:15:58 +0200 Subject: Url change of download Actually there should still be a test if it fails! --- pkg/scripts/bitmask_bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/scripts/bitmask_bootstrap.sh b/pkg/scripts/bitmask_bootstrap.sh index 42eb0af9..bd568ebd 100755 --- a/pkg/scripts/bitmask_bootstrap.sh +++ b/pkg/scripts/bitmask_bootstrap.sh @@ -33,7 +33,7 @@ echo "${cc_green}Installing bitmask...${cc_normal}" # change "develop" for any other branch you want. -pip install -e 'git://leap.se/leap_client@develop#egg=leap.bitmask' +pip install -e 'git+https://leap.se/git/bitmask_client@develop#egg=leap.bitmask' cd bitmask-testbuild -- cgit v1.2.3 From 3846820e4ea0d0ce430f0924d9281ccae912eaa7 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 19 Sep 2013 11:29:39 -0300 Subject: Add comments, refactor code, use latest tag. Improve documentation of the script regarding its usage. Support different tags in the needed repositories and use latest tag for each one. Refactor code to be more readable. --- pkg/linux/build_bundle.sh | 119 ++++++++++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 56 deletions(-) diff --git a/pkg/linux/build_bundle.sh b/pkg/linux/build_bundle.sh index 879579f0..520ff256 100755 --- a/pkg/linux/build_bundle.sh +++ b/pkg/linux/build_bundle.sh @@ -1,98 +1,106 @@ -REPOS_ROOT=$1 -VERSION=$2 -TEMPLATE_BUNDLE=$3 -JOINT_CHANGELOG=$4 -DEST=$5 +#!/bin/bash +# +# USAGE NOTES: +# +# This script is meant to be used as follows: +# user@host ~ $ ./build_bundle.sh ~/tmp 0.3.2 ~/tmp/0.3.1/Bitmask-linux64-0.3.1/ /media/Shared/CHANGELOG ~/tmp/bundle_out/ +# +# So we would have: +# REPOS_ROOT -> ~/tmp +# VERSION -> 0.3.2 +# TEMPLATE_BUNDLE -> ~/tmp/0.3.1/Bitmask-linux64-0.3.1/ +# JOINT_CHANGELOG -> /media/Shared/CHANGELOG +# DEST -> ~/tmp/bundle_out/ +# +# We need to set different PATHs in order to use a specific version of PySide, +# supposing that we have our compiled pyside in '~/pyside/sandbox', the above command would be: +# user@host ~ $ PYTHONPATH=~/pyside/sandbox/lib/python2.7/site-packages/ LD_LIBRARY_PATH=~/pyside/sandbox/lib/ PATH=$PATH:~/pyside/sandbox/bin/ ./build_bundle.sh ~/tmp 0.3.2 ~/tmp/0.3.1/Bitmask-linux64-0.3.1/ /media/sf_Shared/CHANGELOG ~/tmp/bundle_out/ + + +# Required arguments +REPOS_ROOT=$1 # Root path for all the needed repositories +VERSION=$2 # Version number that we are building +TEMPLATE_BUNDLE=$3 # A template used to create the new bundle +JOINT_CHANGELOG=$4 # Joint changelog for all the repositories +DEST=$5 # Destination folder for the bundle + +# Helper variables +REPOSITORIES="bitmask_client leap_pycommon soledad keymanager leap_mail" +ARCH=$(uname -m | sed 's/x86_//;s/i[3-6]86/32/') -# clean template +# Bundle structure +LEAP_LIB=$TEMPLATE_BUNDLE/lib/leap/ +BITMASK_BIN=$TEMPLATE_BUNDLE/bitmask +BUNDLE_NAME=Bitmask-linux$ARCH-$VERSION +# clean template rm $TEMPLATE_BUNDLE/CHANGELOG rm $TEMPLATE_BUNDLE/relnotes.txt rm -rf $TEMPLATE_BUNDLE/apps/leap rm -rf $TEMPLATE_BUNDLE/lib/leap/{common,keymanager,soledad,mail} -# checkout VERSION in all repos - -for i in {leap_client,leap_pycommon,soledad,keymanager,leap_mail} - do - cd $REPOS_ROOT/$i +# checkout the latest tag in all repos +for repo in $REPOSITORIES; do + cd $REPOS_ROOT/$repo git fetch - git checkout $VERSION - done + # checkout to the latest annotated tag, supress 'detached head' warning + git checkout --quiet `git describe --abbrev=0` +done -# make ui in client - -cd $REPOS_ROOT/leap_client +# make: compile ui and resources in client +cd $REPOS_ROOT/bitmask_client make -# cp client - -cp -r $REPOS_ROOT/leap_client/src/leap $TEMPLATE_BUNDLE/apps/leap +# copy the latest client code to the template +cp -r $REPOS_ROOT/bitmask_client/src/leap $TEMPLATE_BUNDLE/apps/leap # setup sdist client - -cd $REPOS_ROOT/leap_client +cd $REPOS_ROOT/bitmask_client python setup.py sdist # extract $VERSION and copy _version.py to TEMPLATE_BUNDLE/Bitmask.app/Contents/MacOS/apps/leap/bitmask/_version.py - +# copy _version.py (versioneer) and reqs.txt (requirements) to the bundle template cd dist rm -rf leap.bitmask-$VERSION tar xzf leap.bitmask-$VERSION.tar.gz cp leap.bitmask-$VERSION/src/leap/bitmask/_version.py $TEMPLATE_BUNDLE/apps/leap/bitmask/_version.py cp leap.bitmask-$VERSION/src/leap/bitmask/util/reqs.txt $TEMPLATE_BUNDLE/apps/leap/bitmask/util/reqs.txt -# cp common, soledad(client and common), mail and keymanager in TEMPLATE_BUNDLE/Bitmask.app/Contents/MacOS/lib/leap/ - -LEAP_LIB=$TEMPLATE_BUNDLE/lib/leap/ - +# add the other needed projects to $LEAP_LIB +# e.g. TEMPLATE_BUNDLE/Bitmask.app/Contents/MacOS/lib/leap/ cp -r $REPOS_ROOT/leap_pycommon/src/leap/common $LEAP_LIB cp -r $REPOS_ROOT/soledad/common/src/leap/soledad $LEAP_LIB cp -r $REPOS_ROOT/soledad/client/src/leap/soledad/client $LEAP_LIB/soledad cp -r $REPOS_ROOT/leap_mail/src/leap/mail $LEAP_LIB cp -r $REPOS_ROOT/keymanager/src/leap/keymanager $LEAP_LIB -# cp leap_client launcher to TEMPLATE_BUNDLE/Bitmask.app/Contents/MacOS/Bitmask - -BITMASK_BIN=$TEMPLATE_BUNDLE/bitmask - -cd $REPOS_ROOT/leap_client_launcher/build/ +# copy bitmask launcher to the bundle template +# e.g. TEMPLATE_BUNDLE/Bitmask.app/Contents/MacOS/Bitmask +cd $REPOS_ROOT/bitmask_launcher/build/ make cp src/launcher $BITMASK_BIN -# cp launcher.py to TEMPLATE_BUNDLE/Bitmask.app/Contents/MacOS/apps/ - -cd $REPOS_ROOT/leap_client_launcher/src/ +# copy launcher.py to template bundle +# e.g. TEMPLATE_BUNDLE/Bitmask.app/Contents/MacOS/apps/ +cd $REPOS_ROOT/bitmask_client_launcher/src/ cp launcher.py $TEMPLATE_BUNDLE/apps/ -# cp relnotes to TEMPLATE_BUNDLE - -cp $REPOS_ROOT/leap_client/relnotes.txt $TEMPLATE_BUNDLE - -# cp joint_chglog to TEMPLATE_BUNDLE - +# copy relnotes, joint changelog and LICENSE to TEMPLATE_BUNDLE +cp $REPOS_ROOT/bitmask_client/relnotes.txt $TEMPLATE_BUNDLE cp $JOINT_CHANGELOG $TEMPLATE_BUNDLE/CHANGELOG - -# cp LICENSE to TEMPLATE_BUNDLE - -cp $REPOS_ROOT/leap_client/LICENSE $TEMPLATE_BUNDLE/LICENSE +cp $REPOS_ROOT/bitmask_client/LICENSE $TEMPLATE_BUNDLE/LICENSE # clean *.pyc files cd $TEMPLATE_BUNDLE find . -name "*.pyc" -delete -# remove execution flags (because vbox fs) and set all read permissions -chmod -x CHANGELOG LICENSE README -chmod +r CHANGELOG LICENSE README +# remove execution flags (because vbox fs) and set read permissions for all +chmod 644 CHANGELOG LICENSE README # create tarball - -ARCH=$(uname -m | sed 's/x86_//;s/i[3-6]86/32/') -BUNDLE_NAME=Bitmask-linux$ARCH-$VERSION TMP=/tmp/$BUNDLE_NAME -rm -rf $TMP -mkdir -p $TMP +rm -rf $TMP && mkdir -p $TMP # clean temp dir cp -R $TEMPLATE_BUNDLE/* $TMP cd /tmp tar cjf $DEST/$BUNDLE_NAME.tar.bz2 $BUNDLE_NAME @@ -100,8 +108,7 @@ cd rm -rf $TMP # go back to develop in all repos -for i in {leap_client,leap_pycommon,soledad,keymanager,leap_mail} - do - cd $REPOS_ROOT/$i +for repo in $REPOSITORIES; do + cd $REPOS_ROOT/$repo git checkout develop - done +done -- cgit v1.2.3 From de766834e4a0148d7ca8ededaf84194dc7a5fb44 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 19 Sep 2013 12:55:32 -0300 Subject: Username case problem at login. Closes #3857. --- changes/bug-3857_username-case-problem | 1 + src/leap/bitmask/crypto/srpauth.py | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) create mode 100644 changes/bug-3857_username-case-problem diff --git a/changes/bug-3857_username-case-problem b/changes/bug-3857_username-case-problem new file mode 100644 index 00000000..3b8ef7b2 --- /dev/null +++ b/changes/bug-3857_username-case-problem @@ -0,0 +1 @@ + o Fix username case problem at register/login. Closes #3857. diff --git a/src/leap/bitmask/crypto/srpauth.py b/src/leap/bitmask/crypto/srpauth.py index 776fb2cc..95dd168d 100644 --- a/src/leap/bitmask/crypto/srpauth.py +++ b/src/leap/bitmask/crypto/srpauth.py @@ -200,8 +200,6 @@ class SRPAuth(QtCore.QObject): """ logger.debug("Authentication preprocessing...") - username = username.lower() - self._srp_user = self._srp.User(username, password, self._hashfun, @@ -506,7 +504,7 @@ class SRPAuth(QtCore.QObject): leap_assert(self.get_session_id() is None, "Already logged in") # User credentials stored for password changing checks - self._username = username.lower() + self._username = username self._password = password d = threads.deferToThread(self._authentication_preprocessing, @@ -615,7 +613,7 @@ class SRPAuth(QtCore.QObject): :param password: password for this user :type password: str """ - + username = username.lower() d = self.__instance.authenticate(username, password) d.addCallback(self._gui_notify) d.addErrback(self._errback) -- cgit v1.2.3 From 607d34e9d91b3dcbad756814d6710d18328d4a40 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 19 Sep 2013 17:25:51 -0400 Subject: move out vpn management utility --- src/leap/bitmask/gui/mainwindow.py | 37 ++------------------------- src/leap/bitmask/services/eip/__init__.py | 42 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 35 deletions(-) diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 69e36328..a818a5f8 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1204,7 +1204,8 @@ class MainWindow(QtGui.QMainWindow): provider_config = self._get_best_provider_config() try: - host, port = self._get_socket_host() + # XXX move this to EIPConductor + host, port = get_openvpn_management() self._vpn.start(eipconfig=self._eip_config, providerconfig=provider_config, socket_host=host, @@ -1627,37 +1628,3 @@ class MainWindow(QtGui.QMainWindow): self._quit_callback() logger.debug('Bye.') - - -if __name__ == "__main__": - import signal - - def sigint_handler(*args, **kwargs): - logger.debug('SIGINT catched. shutting down...') - mainwindow = args[0] - mainwindow.quit() - - import sys - - logger = logging.getLogger(name='leap') - logger.setLevel(logging.DEBUG) - console = logging.StreamHandler() - console.setLevel(logging.DEBUG) - formatter = logging.Formatter( - '%(asctime)s ' - '- %(name)s - %(levelname)s - %(message)s') - console.setFormatter(formatter) - logger.addHandler(console) - - app = QtGui.QApplication(sys.argv) - mainwindow = MainWindow() - mainwindow.show() - - timer = QtCore.QTimer() - timer.start(500) - timer.timeout.connect(lambda: None) - - sigint = partial(sigint_handler, mainwindow) - signal.signal(signal.SIGINT, sigint) - - sys.exit(app.exec_()) diff --git a/src/leap/bitmask/services/eip/__init__.py b/src/leap/bitmask/services/eip/__init__.py index e69de29b..dd010027 100644 --- a/src/leap/bitmask/services/eip/__init__.py +++ b/src/leap/bitmask/services/eip/__init__.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# __init__.py +# Copyright (C) 2013 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# 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 . +""" +leap.bitmask.services.eip module initialization +""" +import os +import tempfile + +from leap.bitmask.platform_init import IS_WIN + + +def get_openvpn_management(): + """ + Returns the socket and port to be used for VPN + + :rtype: tuple (str, str) (host, port) + """ + if IS_WIN: + host = "localhost" + port = "9876" + else: + # XXX cleanup this on exit too + # XXX atexit.register ? + host = os.path.join(tempfile.mkdtemp(prefix="leap-tmp"), + 'openvpn.socket') + port = "unix" + + return host, port -- cgit v1.2.3 From 52ea29a6c225cadc396414ca8f7d662b0633f268 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Fri, 20 Sep 2013 15:44:17 -0400 Subject: update relnotes --- relnotes.txt | 113 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 58 insertions(+), 55 deletions(-) diff --git a/relnotes.txt b/relnotes.txt index 7a9696cc..19cfb879 100644 --- a/relnotes.txt +++ b/relnotes.txt @@ -1,101 +1,104 @@ -ANNOUNCING Bitmask, the internet encryption toolkit, release 0.3.2 +ANNOUNCING Bitmask, the internet encryption toolkit, release 0.3.3 The LEAP team is pleased to announce the immediate availability of -version 0.3.2 of Bitmask, the Internet Encryption Toolkit. +version 0.3.3 of Bitmask, the Internet Encryption Toolkit, codename +"the calm after the tempest". https://downloads.leap.se/client/ -LEAP (LEAP Encryption Access Project) develops a plan to secure -everyday communication, breaking down into discrete services. +LEAP (LEAP Encryption Access Project) develops a plan to secure everyday +communication, breaking down into discrete services. -Bitmask is the desktop client to connect to the services offered -by the LEAP Platform. In the current phase the supported services are -Encrypted Internet Proxy and Encrypted Mail. +Bitmask is the desktop client to connect to the services offered by the +LEAP Platform. In the current phase the supported services are Encrypted +Internet Proxy and Encrypted Mail. -The Encrypted Internet Proxy provides circumvention, location anonymization, -and traffic encryption in a hassle-free, automatically self-configuring -fashion. +The Encrypted Internet Proxy provides circumvention, location +anonymization, and traffic encryption in a hassle-free, automatically +self-configuring fashion. -Encrypted Mail offers automatic encryption and decryption for both outgoing -and incoming email, adding public key cryptography to your mail without you -ever having to worry about key distribution or signature verification. +Encrypted Mail offers automatic encryption and decryption for both +outgoing and incoming email, adding public key cryptography to your mail +without you ever having to worry about key distribution or signature +verification. -You can read about this and many other cool things in the user manual and the -developer notes, which can be found online at: +You can read about this and many other cool things in the user manual +and the developer notes, which can be found online at: http://bitmask.rtfd.org/ -WARNING: This is still part of a beta release of our software, a lot of testing and -auditing is still needed, so indeed use it, and feed us back, fork it and contribute -to its development, but by any means DO NOT trust your life to it (yet!). +WARNING: This is still part of a beta release of our software, a lot of +testing and auditing is still needed, so indeed use it, and feed us back, +fork it and contribute to its development, but by any means DO NOT trust +your life to it (yet!). WHAT CAN THIS VERSION OF BITMASK DO FOR ME? -Bitmask 0.3.2 is mostly a bugfix release, with some minor improvements. Mail -service is a bit more polished, and we are slowly making our potential packagers -happy. Refer to the CHANGELOG for the funny details. +Bitmask 0.3.3 is mostly a bugfix release, with some minor improvements. +On this release, we have fixed many UI bugs, and have undergone internal +reorganizations in the code. This release also bumps the requirement +for Soledad, the encrypted data syncronization engine behind Bitmask, +which has experienced a backward-incompatible change. You can refer to +the CHANGELOG for the meat. -You can connect to the Encrypted Internet Proxy service offered by a provider of -your choice, and enjoy a encrypted internet connection that the spying eyes can only -track back to your provider. +As always, you can connect to the Encrypted Internet Proxy service offered +by a provider of your choice, and enjoy a encrypted internet connection +that the spying eyes can only track back to your provider. -The Encrypted Mail services will run local SMTP and IMAP proxies that, once you -configure the mail client of your choice, will automatically encrypt and decrypt -your email using GPG encryption under the hood. +The Encrypted Mail services will run local SMTP and IMAP proxies that, +once you configure the mail client of your choice, will automatically +encrypt and decrypt your email using GPG encryption under the hood. -The first run wizard will help you registering an user with your selected -provider, downloading all the config files needed to connect to the various LEAP -services. +If it is the first time you run Bitmask, the first run wizard will help +you registering an user with your selected provider, downloading all +the config files needed to connect to the various LEAP services. LICENSE -You may use Bitmask under the GNU General Public License, -version 3 or, at your option, any later version. See the file -"LICENSE" for the terms of the GNU General Public -License, version 3. +You may use Bitmask under the GNU General Public License, version 3 or, +at your option, any later version. See the file "LICENSE" for the terms +of the GNU General Public License, version 3. -In addition, as a special exception, the copyright holders give -permission to link the code of portions of this program with the -OpenSSL library under certain conditions as described in each -individual source file, and distribute linked combinations -including the two. +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library +under certain conditions as described in each individual source file, +and distribute linked combinations including the two. INSTALLATION -We distribute the current version of Bitmask as standalone bundles -for GNU/Linux and OSX, but it is likely that you are able to run it under -other systems, specially if you are skillful and patience is one of your -virtues. +We distribute the current version of Bitmask as standalone bundles for +GNU/Linux and OSX, but it is likely that you are able to run it under +other systems, specially if you are skillful and patience is one of +your virtues. Have a look at "docs/user/install.rst". -Packages will be soon provided for debian and ubuntu, and the release of -windows bundles will be resumed shortly. +Packages will be soon provided for debian and ubuntu, and the release +of windows bundles will be resumed shortly. -We will love to hear if you are interested in help making packages available for -any other system. +We will love to hear if you are interested in help making packages +available for any other system. BUGS -You can send the bugs our way by pointing your telnet session to port 443 on -https://leap.se/code. We will do our best to make them follow our -intensive bug-reeducation program. +You can send the bugs our way by pointing your telnet session to port +443 on https://leap.se/code. We will do our best to make them follow +our intensive bug-reeducation program. HACKING You can find us in the #leap-dev channel on the freenode network. -If you are lucky enough, you can also spot us drinking mate, sleepless in -night trains, rooftops, rainforests, lonely islands and, always, beyond -any border. +If you are lucky enough, you can also spot us drinking mate, sleepless +in night trains, rooftops, rainforests, lonely islands and, always, +beyond any border. The LEAP team, -Sep 06, 2013 -Somewhere in the middle of the intertubes. +Sep 20, 2013 Somewhere in the middle of the intertubes. -- cgit v1.2.3 From 51948a6d9ee78929b72b0affdbfce36e65e073c2 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 19 Sep 2013 15:49:30 -0400 Subject: State Machine Builder and eip connection machine This implements an abstract definition of a LEAP state machine, and refactors eip connections to use it. --- changes/feature_3900-eip-state-machine | 1 + src/leap/bitmask/gui/mainwindow.py | 216 +++++++++++++++------------ src/leap/bitmask/gui/statemachines.py | 223 ++++++++++++++++++++++++++++ src/leap/bitmask/gui/statuspanel.py | 162 ++++++++------------ src/leap/bitmask/services/connections.py | 125 ++++++++++++++++ src/leap/bitmask/services/eip/connection.py | 48 ++++++ src/leap/bitmask/services/eip/eipconfig.py | 1 - src/leap/bitmask/services/eip/vpnprocess.py | 1 + src/leap/bitmask/util/averages.py | 92 ++++++++++++ 9 files changed, 674 insertions(+), 195 deletions(-) create mode 100644 changes/feature_3900-eip-state-machine create mode 100644 src/leap/bitmask/gui/statemachines.py create mode 100644 src/leap/bitmask/services/connections.py create mode 100644 src/leap/bitmask/services/eip/connection.py create mode 100644 src/leap/bitmask/util/averages.py diff --git a/changes/feature_3900-eip-state-machine b/changes/feature_3900-eip-state-machine new file mode 100644 index 00000000..63aad3d3 --- /dev/null +++ b/changes/feature_3900-eip-state-machine @@ -0,0 +1 @@ + o Refactors EIPConnection to use LEAPConnection state machine. Closes: #3900 diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index a818a5f8..200d68aa 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -19,24 +19,23 @@ Main window for Bitmask. """ import logging import os -import platform -import tempfile -from functools import partial import keyring from PySide import QtCore, QtGui from twisted.internet import threads -from leap.bitmask.config import flags +from leap.bitmask import __version__ as VERSION from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.crypto.srpauth import SRPAuth from leap.bitmask.gui.loggerwindow import LoggerWindow -from leap.bitmask.gui.preferenceswindow import PreferencesWindow -from leap.bitmask.gui.wizard import Wizard from leap.bitmask.gui.login import LoginWidget +from leap.bitmask.gui.preferenceswindow import PreferencesWindow +from leap.bitmask.gui import statemachines from leap.bitmask.gui.statuspanel import StatusPanelWidget +from leap.bitmask.gui.wizard import Wizard + from leap.bitmask.services.eip.eipbootstrapper import EIPBootstrapper from leap.bitmask.services.eip.eipconfig import EIPConfig from leap.bitmask.services.eip.providerbootstrapper import ProviderBootstrapper @@ -48,6 +47,8 @@ from leap.bitmask.services.mail import imap from leap.bitmask.platform_init import IS_WIN, IS_MAC from leap.bitmask.platform_init.initializers import init_platform +from leap.bitmask.services.eip import get_openvpn_management +from leap.bitmask.services.eip.connection import EIPConnection from leap.bitmask.services.eip.vpnprocess import VPN from leap.bitmask.services.eip.vpnprocess import OpenVPNAlreadyRunning from leap.bitmask.services.eip.vpnprocess import AlienOpenVPNAlreadyRunning @@ -59,7 +60,6 @@ from leap.bitmask.services.eip.vpnlaunchers import \ EIPNoPolkitAuthAgentAvailable from leap.bitmask.services.eip.vpnlaunchers import EIPNoTunKextLoaded -from leap.bitmask import __version__ as VERSION from leap.bitmask.util.keyring_helpers import has_keyring from leap.bitmask.util.leap_log_handler import LeapLogHandler @@ -167,8 +167,14 @@ class MainWindow(QtGui.QMainWindow): self.ui.stackedWidget.setCurrentIndex(self.LOGIN_INDEX) - self._status_panel.start_eip.connect(self._start_eip) - self._status_panel.stop_eip.connect(self._stop_eip) + self._eip_connection = EIPConnection() + + self._eip_connection.qtsigs.connecting_signal.connect( + self._start_eip) + self._eip_connection.qtsigs.disconnecting_signal.connect( + self._stop_eip) + self._status_panel.eip_connection_connected.connect( + self._on_eip_connected) # This is loaded only once, there's a bug when doing that more # than once @@ -206,12 +212,20 @@ class MainWindow(QtGui.QMainWindow): # This thread is similar to the provider bootstrapper self._eip_bootstrapper = EIPBootstrapper() + # EIP signals ---- move to eip conductor. # TODO change the name of "download_config" signal to # something less confusing (config_ready maybe) self._eip_bootstrapper.download_config.connect( self._eip_intermediate_stage) self._eip_bootstrapper.download_client_certificate.connect( self._finish_eip_bootstrap) + self._vpn = VPN(openvpn_verb=openvpn_verb) + self._vpn.qtsigs.state_changed.connect( + self._status_panel.update_vpn_state) + self._vpn.qtsigs.status_changed.connect( + self._status_panel.update_vpn_status) + self._vpn.qtsigs.process_finished.connect( + self._eip_finished) self._soledad_bootstrapper = SoledadBootstrapper() self._soledad_bootstrapper.download_config.connect( @@ -225,14 +239,6 @@ class MainWindow(QtGui.QMainWindow): self._smtp_bootstrapper.download_config.connect( self._smtp_bootstrapped_stage) - self._vpn = VPN(openvpn_verb=openvpn_verb) - self._vpn.qtsigs.state_changed.connect( - self._status_panel.update_vpn_state) - self._vpn.qtsigs.status_changed.connect( - self._status_panel.update_vpn_status) - self._vpn.qtsigs.process_finished.connect( - self._eip_finished) - self.ui.action_log_out.setEnabled(False) self.ui.action_log_out.triggered.connect(self._logout) self.ui.action_about_leap.triggered.connect(self._about) @@ -250,9 +256,7 @@ class MainWindow(QtGui.QMainWindow): self._action_mail_status.setEnabled(False) self._status_panel.set_action_mail_status(self._action_mail_status) - self._action_eip_startstop = QtGui.QAction(self.tr("Turn ON"), self) - self._action_eip_startstop.triggered.connect(self._stop_eip) - self._action_eip_startstop.setEnabled(False) + self._action_eip_startstop = QtGui.QAction("", self) self._status_panel.set_action_eip_startstop(self._action_eip_startstop) self._action_preferences = QtGui.QAction(self.tr("Preferences"), self) @@ -309,6 +313,17 @@ class MainWindow(QtGui.QMainWindow): else: self._finish_init() + # Eip machine is a public attribute where the state machine for + # the eip connection will be available to the different components. + # Remember that this will not live in the +1600LOC mainwindow for + # all the eternity, so at some point we will be moving this to + # the EIPConductor or some other clever component that we will + # instantiate from here. + self.eip_machine = None + + # start event machines + self.start_eip_machine() + def _rejected_wizard(self): """ SLOT @@ -579,6 +594,10 @@ class MainWindow(QtGui.QMainWindow): "providers", default_provider, "provider.json")): + # XXX I think we should not try to re-download config every time, + # it adds some delay. + # Maybe if it's the first run in a session, + # or we can try only if it fails. self._download_eip_config() else: # XXX: Display a proper message to the user @@ -943,6 +962,7 @@ class MainWindow(QtGui.QMainWindow): self._login_widget.set_enabled(True) def _switch_to_status(self): + # TODO this method name is confusing as hell. """ Changes the stackedWidget index to the EIP status one and triggers the eip bootstrapping @@ -954,6 +974,8 @@ class MainWindow(QtGui.QMainWindow): self.ui.stackedWidget.setCurrentIndex(self.EIP_STATUS_INDEX) + # TODO separate UI from logic. + # TODO soledad should check if we want to run only over EIP. self._soledad_bootstrapper.run_soledad_setup_checks( self._provider_config, self._login_widget.get_user(), @@ -1169,26 +1191,36 @@ class MainWindow(QtGui.QMainWindow): ################################################################### # Service control methods: eip - def _get_socket_host(self): + def start_eip_machine(self): """ - Returns the socket and port to be used for VPN - - :rtype: tuple (str, str) (host, port) + Initializes and starts the EIP state machine """ - # TODO make this properly multiplatform - # TODO get this out of gui/ + button = self._status_panel.eip_button + action = self._action_eip_startstop + label = self._status_panel.eip_label + builder = statemachines.ConnectionMachineBuilder(self._eip_connection) + eip_machine = builder.make_machine(button=button, + action=action, + label=label) + self.eip_machine = eip_machine + self.eip_machine.start() - if platform.system() == "Windows": - host = "localhost" - port = "9876" - else: - # XXX cleanup this on exit too - host = os.path.join(tempfile.mkdtemp(prefix="leap-tmp"), - 'openvpn.socket') - port = "unix" + @QtCore.Slot() + def _on_eip_connected(self): + """ + SLOT + TRIGGERS: + self._status_panel.eip_connection_connected + Emits the EIPConnection.qtsigs.connected_signal - return host, port + This is a little workaround for connecting the vpn-connected + signal that currently is beeing processed under status_panel. + After the refactor to EIPConductor this should not be necessary. + """ + logger.debug('EIP connected signal received ...') + self._eip_connection.qtsigs.connected_signal.emit() + @QtCore.Slot() def _start_eip(self): """ SLOT @@ -1199,9 +1231,10 @@ class MainWindow(QtGui.QMainWindow): Starts EIP """ + provider_config = self._get_best_provider_config() + provider = provider_config.get_domain() self._status_panel.eip_pre_up() self.user_stopped_eip = False - provider_config = self._get_best_provider_config() try: # XXX move this to EIPConductor @@ -1210,22 +1243,15 @@ class MainWindow(QtGui.QMainWindow): providerconfig=provider_config, socket_host=host, socket_port=port) - - self._settings.set_defaultprovider( - provider_config.get_domain()) - - provider = provider_config.get_domain() + self._settings.set_defaultprovider(provider) if self._logged_user is not None: provider = "%s@%s" % (self._logged_user, provider) + # XXX move to the state machine too self._status_panel.set_provider(provider) - self._status_panel.eip_started() - # XXX refactor into status_panel method? - self._action_eip_startstop.setText(self.tr("Turn OFF")) - self._action_eip_startstop.disconnect(self) - self._action_eip_startstop.triggered.connect( - self._stop_eip) + # TODO refactor exceptions so they provide translatable + # usef-facing messages. except EIPNoPolkitAuthAgentAvailable: self._status_panel.set_global_status( # XXX this should change to polkit-kde where @@ -1277,26 +1303,7 @@ class MainWindow(QtGui.QMainWindow): else: self._already_started_eip = True - def _set_eipstatus_off(self): - """ - Sets eip status to off - """ - self._status_panel.set_eip_status(self.tr("OFF"), error=True) - self._status_panel.set_eip_status_icon("error") - self._status_panel.set_startstop_enabled(True) - self._status_panel.eip_stopped() - - self._set_action_eipstart_off() - - def _set_action_eipstart_off(self): - """ - Sets eip startstop action to OFF status. - """ - self._action_eip_startstop.setText(self.tr("Turn ON")) - self._action_eip_startstop.disconnect(self) - self._action_eip_startstop.triggered.connect( - self._start_eip) - + @QtCore.Slot() def _stop_eip(self, abnormal=False): """ SLOT @@ -1320,34 +1327,20 @@ class MainWindow(QtGui.QMainWindow): self._set_eipstatus_off() self._already_started_eip = False + + # XXX do via signal self._settings.set_defaultprovider(None) if self._logged_user: self._status_panel.set_provider( "%s@%s" % (self._logged_user, self._get_best_provider_config().get_domain())) - def _get_best_provider_config(self): + def _set_eipstatus_off(self): """ - Returns the best ProviderConfig to use at a moment. We may - have to use self._provider_config or - self._provisional_provider_config depending on the start - status. - - :rtype: ProviderConfig + Sets eip status to off """ - leap_assert(self._provider_config is not None or - self._provisional_provider_config is not None, - "We need a provider config") - - provider_config = None - if self._provider_config.loaded(): - provider_config = self._provider_config - elif self._provisional_provider_config.loaded(): - provider_config = self._provisional_provider_config - else: - leap_assert(False, "We could not find any usable ProviderConfig.") - - return provider_config + self._status_panel.set_eip_status(self.tr("OFF"), error=True) + self._status_panel.set_eip_status_icon("error") def _download_eip_config(self): """ @@ -1361,6 +1354,7 @@ class MainWindow(QtGui.QMainWindow): self._enabled_services.count(self.OPENVPN_SERVICE) > 0 and \ not self._already_started_eip: + # XXX this should be handled by the state machine. self._status_panel.set_eip_status( self.tr("Starting...")) self._eip_bootstrapper.run_eip_setup_checks( @@ -1374,7 +1368,6 @@ class MainWindow(QtGui.QMainWindow): error=True) else: self._status_panel.set_eip_status(self.tr("Disabled")) - self._status_panel.set_startstop_enabled(False) def _finish_eip_bootstrap(self, data): """ @@ -1395,7 +1388,6 @@ class MainWindow(QtGui.QMainWindow): return provider_config = self._get_best_provider_config() - domain = provider_config.get_domain() loaded = self._eip_config.loaded() @@ -1407,13 +1399,41 @@ class MainWindow(QtGui.QMainWindow): loaded = self._eip_config.load(eip_config_path) if loaded: - self._start_eip() + # DO START EIP Connection! + self._eip_connection.qtsigs.do_connect_signal.emit() else: self._status_panel.set_eip_status( self.tr("Could not load Encrypted Internet " "Configuration."), error=True) + # end eip methods ------------------------------------------- + + def _get_best_provider_config(self): + """ + Returns the best ProviderConfig to use at a moment. We may + have to use self._provider_config or + self._provisional_provider_config depending on the start + status. + + :rtype: ProviderConfig + """ + # TODO move this out of gui. + leap_assert(self._provider_config is not None or + self._provisional_provider_config is not None, + "We need a provider config") + + provider_config = None + if self._provider_config.loaded(): + provider_config = self._provider_config + elif self._provisional_provider_config.loaded(): + provider_config = self._provisional_provider_config + else: + leap_assert(False, "We could not find any usable ProviderConfig.") + + return provider_config + + @QtCore.Slot() def _logout(self): """ SLOT @@ -1494,6 +1514,7 @@ class MainWindow(QtGui.QMainWindow): Triggered when the EIP/VPN process finishes to set the UI accordingly. """ + # TODO move to EIPConductor. logger.info("VPN process finished with exitCode %s..." % (exitCode,)) @@ -1528,7 +1549,20 @@ class MainWindow(QtGui.QMainWindow): if exitCode == 0 and IS_MAC: # XXX remove this warning after I fix cocoasudo. logger.warning("The above exit code MIGHT BE WRONG.") - self._stop_eip(abnormal) + + # We emit signals to trigger transitions in the state machine: + qtsigs = self._eip_connection.qtsigs + if abnormal: + signal = qtsigs.connection_died_signal + else: + signal = qtsigs.disconnected_signal + + # XXX verify that the logic kees the same w/o the abnormal flag + # after the refactor to EIPConnection has been completed + # (eipconductor taking the most of the logic under transitions + # that right now are handled under status_panel) + #self._stop_eip(abnormal) + signal.emit() def _on_raise_window_event(self, req): """ diff --git a/src/leap/bitmask/gui/statemachines.py b/src/leap/bitmask/gui/statemachines.py new file mode 100644 index 00000000..c3dd5ed3 --- /dev/null +++ b/src/leap/bitmask/gui/statemachines.py @@ -0,0 +1,223 @@ +# -*- coding: utf-8 -*- +# statemachines.py +# Copyright (C) 2013 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# 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 . +""" +State machines for the Bitmask app. +""" +import logging + +from PySide.QtCore import QStateMachine, QState +from PySide.QtCore import QObject + +from leap.bitmask.services import connections +from leap.common.check import leap_assert_type + +logger = logging.getLogger(__name__) + +_tr = QObject().tr + +# Indexes for the state dict +_ON = "on" +_OFF = "off" +_CON = "connecting" +_DIS = "disconnecting" + + +class IntermediateState(QState): + """ + Intermediate state that emits a custom signal on entry + """ + def __init__(self, signal): + """ + Initializer. + :param signal: the signal to be emitted on entry on this state. + :type signal: QtCore.QSignal + """ + super(IntermediateState, self).__init__() + self._signal = signal + + def onEntry(self, *args): + """ + Emits the signal on entry. + """ + logger.debug('IntermediateState entered. Emitting signal ...') + if self._signal is not None: + self._signal.emit() + + +class ConnectionMachineBuilder(object): + """ + Builder class for state machines made from LEAPConnections. + """ + def __init__(self, connection): + """ + :param connection: an instance of a concrete LEAPConnection + we will be building a state machine for. + :type connection: AbstractLEAPConnection + """ + self._conn = connection + leap_assert_type(self._conn, connections.AbstractLEAPConnection) + + def make_machine(self, button=None, action=None, label=None): + """ + Creates a statemachine associated with the passed controls. + + :param button: the switch button. + :type button: QPushButton + + :param action: the actionh that controls connection switch in a menu. + :type action: QAction + + :param label: the label that displays the connection state + :type label: QLabel + + :returns: a state machine + :rtype: QStateMachine + """ + machine = QStateMachine() + conn = self._conn + + states = self._make_states(button, action, label) + + # transitions: + + states[_OFF].addTransition( + conn.qtsigs.do_connect_signal, + states[_CON]) + + # * Clicking the buttons or actions transitions to the + # intermediate stage. + if button: + states[_OFF].addTransition( + button.clicked, + states[_CON]) + states[_ON].addTransition( + button.clicked, + states[_DIS]) + + if action: + states[_OFF].addTransition( + action.triggered, + states[_CON]) + states[_ON].addTransition( + action.triggered, + states[_DIS]) + + # * We transition to the completed stages when + # we receive the matching signal from the underlying + # conductor. + + states[_CON].addTransition( + conn.qtsigs.connected_signal, + states[_ON]) + states[_DIS].addTransition( + conn.qtsigs.disconnected_signal, + states[_OFF]) + + # * If we receive the connection_died, we transition + # to the off state + states[_ON].addTransition( + conn.qtsigs.connection_died_signal, + states[_OFF]) + + # adding states to the machine + for state in states.itervalues(): + machine.addState(state) + machine.setInitialState(states[_OFF]) + return machine + + def _make_states(self, button, action, label): + """ + Creates the four states for the state machine + + :param button: the switch button. + :type button: QPushButton + + :param action: the actionh that controls connection switch in a menu. + :type action: QAction + + :param label: the label that displays the connection state + :type label: QLabel + + :returns: a dict of states + :rtype: dict + """ + conn = self._conn + states = {} + + # TODO add tooltip + + # OFF State ---------------------- + off = QState() + off_label = _tr("Turn {0}").format( + conn.Connected.short_label) + if button: + off.assignProperty( + button, 'text', off_label) + off.assignProperty( + button, 'enabled', True) + if action: + off.assignProperty( + action, 'text', off_label) + off.setObjectName(_OFF) + states[_OFF] = off + + # CONNECTING State ---------------- + connecting = IntermediateState( + conn.qtsigs.connecting_signal) + on_label = _tr("Turn {0}").format( + conn.Disconnected.short_label) + if button: + connecting.assignProperty( + button, 'text', on_label) + connecting.assignProperty( + button, 'enabled', False) + if action: + connecting.assignProperty( + action, 'text', on_label) + connecting.assignProperty( + action, 'enabled', False) + connecting.setObjectName(_CON) + states[_CON] = connecting + + # ON State ------------------------ + on = QState() + if button: + on.assignProperty( + button, 'text', on_label) + on.assignProperty( + button, 'enabled', True) + if action: + on.assignProperty( + action, 'text', on_label) + on.assignProperty( + action, 'enabled', True) + # TODO set label for ON state + on.setObjectName(_ON) + states[_ON] = on + + # DISCONNECTING State ------------- + disconnecting = IntermediateState( + conn.qtsigs.disconnecting_signal) + if button: + disconnecting.assignProperty( + button, 'enabled', False) + # XXX complete disconnecting + # TODO disable button + disconnecting.setObjectName(_DIS) + states[_DIS] = disconnecting + + return states diff --git a/src/leap/bitmask/gui/statuspanel.py b/src/leap/bitmask/gui/statuspanel.py index 39a8079f..679f00b1 100644 --- a/src/leap/bitmask/gui/statuspanel.py +++ b/src/leap/bitmask/gui/statuspanel.py @@ -14,7 +14,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - """ Status Panel widget implementation """ @@ -25,9 +24,10 @@ from functools import partial from PySide import QtCore, QtGui +from leap.bitmask.services.eip.connection import EIPConnection from leap.bitmask.services.eip.vpnprocess import VPNManager from leap.bitmask.platform_init import IS_WIN, IS_LINUX -from leap.bitmask.util import first +from leap.bitmask.util.averages import RateMovingAverage from leap.common.check import leap_assert, leap_assert_type from leap.common.events import register from leap.common.events import events_pb2 as proto @@ -37,83 +37,10 @@ from ui_statuspanel import Ui_StatusPanel logger = logging.getLogger(__name__) -class RateMovingAverage(object): - """ - Moving window average for calculating - upload and download rates. - """ - SAMPLE_SIZE = 5 - - def __init__(self): - """ - Initializes an empty array of fixed size - """ - self.reset() - - def reset(self): - self._data = [None for i in xrange(self.SAMPLE_SIZE)] - - def append(self, x): - """ - Appends a new data point to the collection. - - :param x: A tuple containing timestamp and traffic points - in the form (timestamp, traffic) - :type x: tuple - """ - self._data.pop(0) - self._data.append(x) - - def get(self): - """ - Gets the collection. - """ - return self._data - - def get_average(self): - """ - Gets the moving average. - """ - data = filter(None, self.get()) - traff = [traffic for (ts, traffic) in data] - times = [ts for (ts, traffic) in data] - - try: - deltatraffic = traff[-1] - first(traff) - deltat = (times[-1] - first(times)).seconds - except IndexError: - deltatraffic = 0 - deltat = 0 - - try: - rate = float(deltatraffic) / float(deltat) / 1024 - except ZeroDivisionError: - rate = 0 - - # In some cases we get negative rates - if rate < 0: - rate = 0 - - return rate - - def get_total(self): - """ - Gets the total accumulated throughput. - """ - try: - return self._data[-1][1] / 1024 - except TypeError: - return 0 - - class StatusPanelWidget(QtGui.QWidget): """ Status widget that displays the current state of the LEAP services """ - - start_eip = QtCore.Signal() - stop_eip = QtCore.Signal() - DISPLAY_TRAFFIC_RATES = True RATE_STR = "%14.2f KB/s" TOTAL_STR = "%14.2f Kb" @@ -121,6 +48,7 @@ class StatusPanelWidget(QtGui.QWidget): MAIL_OFF_ICON = ":/images/mail-unlocked.png" MAIL_ON_ICON = ":/images/mail-locked.png" + eip_connection_connected = QtCore.Signal() _soledad_event = QtCore.Signal(object) _smtp_event = QtCore.Signal(object) _imap_event = QtCore.Signal(object) @@ -135,9 +63,7 @@ class StatusPanelWidget(QtGui.QWidget): self.ui = Ui_StatusPanel() self.ui.setupUi(self) - self.ui.btnEipStartStop.setEnabled(False) - self.ui.btnEipStartStop.clicked.connect( - self.start_eip) + self.eipconnection = EIPConnection() self.hide_status_box() @@ -330,6 +256,8 @@ class StatusPanelWidget(QtGui.QWidget): self.CONNECTED_ICON_TRAY = QtGui.QPixmap(EIP_ICONS_TRAY[1]) self.ERROR_ICON_TRAY = QtGui.QPixmap(EIP_ICONS_TRAY[2]) + # Systray and actions + def set_systray(self, systray): """ Sets the systray object to use. @@ -401,6 +329,25 @@ class StatusPanelWidget(QtGui.QWidget): """ self.ui.globalStatusBox.hide() + # EIP status --- + + @property + def eip_button(self): + return self.ui.btnEipStartStop + + @property + def eip_label(self): + return self.ui.lblEIPStatus + + def eip_pre_up(self): + """ + Triggered when the app activates eip. + Hides the status box and disables the start/stop button. + """ + self.hide_status_box() + self.set_startstop_enabled(False) + + # XXX disable (later) -------------------------- def set_eip_status(self, status, error=False): """ Sets the status label at the VPN stage to status @@ -420,6 +367,7 @@ class StatusPanelWidget(QtGui.QWidget): self.ui.lblEIPStatus.setText(status) self._update_systray_tooltip() + # XXX disable --------------------------------- def set_startstop_enabled(self, value): """ Enable or disable btnEipStartStop and _action_eip_startstop @@ -432,14 +380,7 @@ class StatusPanelWidget(QtGui.QWidget): self.ui.btnEipStartStop.setEnabled(value) self._action_eip_startstop.setEnabled(value) - def eip_pre_up(self): - """ - Triggered when the app activates eip. - Hides the status box and disables the start/stop button. - """ - self.hide_status_box() - self.set_startstop_enabled(False) - + # XXX disable ----------------------------- def eip_started(self): """ Sets the state of the widget to how it should look after EIP @@ -448,27 +389,21 @@ class StatusPanelWidget(QtGui.QWidget): self.ui.btnEipStartStop.setText(self.tr("Turn OFF")) self.ui.btnEipStartStop.disconnect(self) self.ui.btnEipStartStop.clicked.connect( - self.stop_eip) + self.eipconnection.qtsigs.do_connect_signal) + # XXX disable ----------------------------- def eip_stopped(self): """ Sets the state of the widget to how it should look after EIP has stopped """ + # XXX should connect this to EIPConnection.disconnected_signal self._reset_traffic_rates() + # XXX disable ----------------------------- self.ui.btnEipStartStop.setText(self.tr("Turn ON")) self.ui.btnEipStartStop.disconnect(self) self.ui.btnEipStartStop.clicked.connect( - self.start_eip) - - def set_icon(self, icon): - """ - Sets the icon to display for EIP - - :param icon: icon to display - :type icon: QPixmap - """ - self.ui.lblVPNStatusIcon.setPixmap(icon) + self.eipconnection.qtsigs.do_disconnect_signal) def update_vpn_status(self, data): """ @@ -507,14 +442,21 @@ class StatusPanelWidget(QtGui.QWidget): TRIGGER: VPN.state_changed Updates the displayed VPN state based on the data provided by - the VPN thread + the VPN thread. + + Emits: + If the status is connected, we emit EIPConnection.qtsigs. + connected_signal """ status = data[VPNManager.STATUS_STEP_KEY] self.set_eip_status_icon(status) if status == "CONNECTED": + # XXX should be handled by the state machine too. self.set_eip_status(self.tr("ON")) - # Only now we can properly enable the button. - self.set_startstop_enabled(True) + logger.debug("STATUS IS CONNECTED --- emitting signal") + self.eip_connection_connected.emit() + + # XXX should lookup status map in EIPConnection elif status == "AUTH": self.set_eip_status(self.tr("Authenticating...")) elif status == "GET_CONFIG": @@ -528,7 +470,8 @@ class StatusPanelWidget(QtGui.QWidget): elif status == "ALREADYRUNNING": # Put the following calls in Qt's event queue, otherwise # the UI won't update properly - QtCore.QTimer.singleShot(0, self.stop_eip) + QtCore.QTimer.singleShot( + 0, self.eipconnection.qtsigs.do_disconnect_signal) QtCore.QTimer.singleShot(0, partial(self.set_global_status, self.tr("Unable to start VPN, " "it's already " @@ -536,6 +479,15 @@ class StatusPanelWidget(QtGui.QWidget): else: self.set_eip_status(status) + def set_eip_icon(self, icon): + """ + Sets the icon to display for EIP + + :param icon: icon to display + :type icon: QPixmap + """ + self.ui.lblVPNStatusIcon.setPixmap(icon) + def set_eip_status_icon(self, status): """ Given a status step from the VPN thread, set the icon properly @@ -556,13 +508,17 @@ class StatusPanelWidget(QtGui.QWidget): selected_pixmap = self.CONNECTED_ICON selected_pixmap_tray = self.CONNECTED_ICON_TRAY - self.set_icon(selected_pixmap) + self.set_eip_icon(selected_pixmap) self._systray.setIcon(QtGui.QIcon(selected_pixmap_tray)) self._eip_status_menu.setTitle(tray_message) def set_provider(self, provider): self.ui.lblProvider.setText(provider) + # + # mail methods + # + def _set_mail_status(self, status, ready=False): """ Sets the Mail status in the label and in the tray icon. @@ -742,7 +698,7 @@ class StatusPanelWidget(QtGui.QWidget): self.ui.lblUnread.setVisible(req.content != "0") self._set_mail_status(self.tr("ON"), ready=True) else: - leap_assert(False, + leap_assert(False, # XXX ??? "Don't know how to handle this state: %s" % (req.event)) diff --git a/src/leap/bitmask/services/connections.py b/src/leap/bitmask/services/connections.py new file mode 100644 index 00000000..f3ab9e8e --- /dev/null +++ b/src/leap/bitmask/services/connections.py @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- +# connections.py +# Copyright (C) 2013 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# 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 . +""" +Abstract LEAP connections. +""" +# TODO use zope.interface instead +from abc import ABCMeta + +from PySide import QtCore + +from leap.common.check import leap_assert + +_tr = QtCore.QObject().tr + + +class State(object): + """ + Abstract state class + """ + __metaclass__ = ABCMeta + + label = None + short_label = None + +""" +The different services should declare a ServiceConnection class that +inherits from AbstractLEAPConnection, so an instance of such class +can be used to inform the StateMachineBuilder of the particularities +of the state transitions for each particular connection. + +In the future, we will extend this class to allow composites in connections, +so we can apply conditional logic to the transitions. +""" + + +class AbstractLEAPConnection(object): + """ + Abstract LEAP Connection class. + + This class is likely to undergo heavy transformations + in the coming releases, to better accomodate the use cases + of the different connections that we use in the Bitmask + client. + """ + __metaclass__ = ABCMeta + + _connection_name = None + + @property + def name(self): + """ + Name of the connection + """ + con_name = self._connection_name + leap_assert(con_name is not None) + return con_name + + _qtsigs = None + + @property + def qtsigs(self): + """ + Object that encapsulates the Qt Signals emitted + by this connection. + """ + return self._qtsigs + + # XXX for conditional transitions with composites, + # we might want to add + # a field with dependencies: what this connection + # needs for (ON) state. + # XXX Look also at child states in the state machine. + #depends = () + + # Signals that derived classes + # have to implement. + + # Commands + do_connect_signal = None + do_disconnect_signal = None + + # Intermediate stages + connecting_signal = None + disconnecting_signal = None + + # Complete stages + connected_signal = None + disconnected_signal = None + + # Bypass stages + connection_died_signal = None + + class Disconnected(State): + """Disconnected state""" + label = _tr("Disconnected") + short_label = _tr("OFF") + + class Connected(State): + """Connected state""" + label = _tr("Connected") + short_label = _tr("ON") + + class Connecting(State): + """Connecting state""" + label = _tr("Connecting") + short_label = _tr("...") + + class Disconnecting(State): + """Disconnecting state""" + label = _tr("Disconnecting") + short_label = _tr("...") diff --git a/src/leap/bitmask/services/eip/connection.py b/src/leap/bitmask/services/eip/connection.py new file mode 100644 index 00000000..5f05ba07 --- /dev/null +++ b/src/leap/bitmask/services/eip/connection.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# connection.py +# Copyright (C) 2013 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# 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 . +""" +EIP Connection +""" +from PySide import QtCore + +from leap.bitmask.services.connections import AbstractLEAPConnection + + +class EIPConnectionSignals(QtCore.QObject): + """ + Qt Signals used by EIPConnection + """ + # commands + do_connect_signal = QtCore.Signal() + do_disconnect_signal = QtCore.Signal() + + # intermediate stages + # this is currently binded to mainwindow._start_eip + connecting_signal = QtCore.Signal() + # this is currently binded to mainwindow._stop_eip + disconnecting_signal = QtCore.Signal() + + connected_signal = QtCore.Signal() + disconnected_signal = QtCore.Signal() + + connection_died_signal = QtCore.Signal() + + +class EIPConnection(AbstractLEAPConnection): + + def __init__(self): + self._qtsigs = EIPConnectionSignals() diff --git a/src/leap/bitmask/services/eip/eipconfig.py b/src/leap/bitmask/services/eip/eipconfig.py index 466a644c..7d8995b4 100644 --- a/src/leap/bitmask/services/eip/eipconfig.py +++ b/src/leap/bitmask/services/eip/eipconfig.py @@ -14,7 +14,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - """ Provider configuration """ diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index c01da372..15ac812b 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -95,6 +95,7 @@ class VPN(object): self._reactor = reactor self._qtsigs = VPNSignals() + # XXX should get it from config.flags self._openvpn_verb = kwargs.get(self.OPENVPN_VERB, None) @property diff --git a/src/leap/bitmask/util/averages.py b/src/leap/bitmask/util/averages.py new file mode 100644 index 00000000..65953f8f --- /dev/null +++ b/src/leap/bitmask/util/averages.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +# averages.py +# Copyright (C) 2013 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# 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 . +""" +Utility class for moving averages. + +It is used in the status panel widget for displaying up and down +download rates. +""" +from leap.bitmask.util import first + + +class RateMovingAverage(object): + """ + Moving window average for calculating + upload and download rates. + """ + SAMPLE_SIZE = 5 + + def __init__(self): + """ + Initializes an empty array of fixed size + """ + self.reset() + + def reset(self): + self._data = [None for i in xrange(self.SAMPLE_SIZE)] + + def append(self, x): + """ + Appends a new data point to the collection. + + :param x: A tuple containing timestamp and traffic points + in the form (timestamp, traffic) + :type x: tuple + """ + self._data.pop(0) + self._data.append(x) + + def get(self): + """ + Gets the collection. + """ + return self._data + + def get_average(self): + """ + Gets the moving average. + """ + data = filter(None, self.get()) + traff = [traffic for (ts, traffic) in data] + times = [ts for (ts, traffic) in data] + + try: + deltatraffic = traff[-1] - first(traff) + deltat = (times[-1] - first(times)).seconds + except IndexError: + deltatraffic = 0 + deltat = 0 + + try: + rate = float(deltatraffic) / float(deltat) / 1024 + except ZeroDivisionError: + rate = 0 + + # In some cases we get negative rates + if rate < 0: + rate = 0 + + return rate + + def get_total(self): + """ + Gets the total accumulated throughput. + """ + try: + return self._data[-1][1] / 1024 + except TypeError: + return 0 -- cgit v1.2.3 From c342bd2e9adc5351c4a42b9f6fea027c6969fc16 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Fri, 20 Sep 2013 16:13:08 -0400 Subject: include resources --- MANIFEST.in | 3 +++ changes/bug-3825-include-resources | 1 + 2 files changed, 4 insertions(+) create mode 100644 changes/bug-3825-include-resources diff --git a/MANIFEST.in b/MANIFEST.in index 926e1793..876393da 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -9,3 +9,6 @@ include README.rst include CHANGELOG include src/leap/bitmask/util/reqs.txt include src/leap/bitmask/crypto/tests/wrongcert.pem + +include src/leap/bitmask/gui/ui_*.py +include src/leap/bitmask/gui/*_rc.py diff --git a/changes/bug-3825-include-resources b/changes/bug-3825-include-resources new file mode 100644 index 00000000..083fd05d --- /dev/null +++ b/changes/bug-3825-include-resources @@ -0,0 +1 @@ + o Include resource files and ui in the distrubution tarball. Closes: #3825 -- cgit v1.2.3 From c8a035c46b0b64772cf630d6c52d738f59ed6e73 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 20 Sep 2013 17:11:55 -0300 Subject: Fold in changes. --- CHANGELOG | 30 ++++++++++++++++++++++ .../bug-3617_remove-exec-bits-from-text-in-bundle | 1 - changes/bug-3656_generic-username-password-message | 2 -- ...bug-3714_fix-logger-saving-several-line-returns | 2 -- changes/bug-3774_fix-logout-error | 2 -- changes/bug-3778_fix-path-prefix-helper | 1 - changes/bug-3791_prevent-last-window-close-app | 1 - changes/bug-3821_inconsistent-hide-show-mainwindow | 1 - changes/bug-3847-start-smtp-without-eip | 1 - changes/bug-3857_username-case-problem | 1 - changes/bug_3759-fix-keyring-imports | 1 - .../bug_3803-do-not-install-resolv-update-globally | 1 - changes/bug_fix-first | 1 - changes/feature-3636_standalone-flag-to-module | 2 -- ...-3758_show-eip-and-mx-status-in-systray-tooltip | 2 -- changes/feature-3792_systray-improvements | 6 ----- changes/feature_3417_update-repo-in-docs | 1 - changes/feature_3816-add-version-flag | 1 - changes/feature_3900-eip-state-machine | 1 - 19 files changed, 30 insertions(+), 28 deletions(-) delete mode 100644 changes/bug-3617_remove-exec-bits-from-text-in-bundle delete mode 100644 changes/bug-3656_generic-username-password-message delete mode 100644 changes/bug-3714_fix-logger-saving-several-line-returns delete mode 100644 changes/bug-3774_fix-logout-error delete mode 100644 changes/bug-3778_fix-path-prefix-helper delete mode 100644 changes/bug-3791_prevent-last-window-close-app delete mode 100644 changes/bug-3821_inconsistent-hide-show-mainwindow delete mode 100644 changes/bug-3847-start-smtp-without-eip delete mode 100644 changes/bug-3857_username-case-problem delete mode 100644 changes/bug_3759-fix-keyring-imports delete mode 100644 changes/bug_3803-do-not-install-resolv-update-globally delete mode 100644 changes/bug_fix-first delete mode 100644 changes/feature-3636_standalone-flag-to-module delete mode 100644 changes/feature-3758_show-eip-and-mx-status-in-systray-tooltip delete mode 100644 changes/feature-3792_systray-improvements delete mode 100644 changes/feature_3417_update-repo-in-docs delete mode 100644 changes/feature_3816-add-version-flag delete mode 100644 changes/feature_3900-eip-state-machine diff --git a/CHANGELOG b/CHANGELOG index e94943ae..15db6cd2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,33 @@ +0.3.3 Sep 20 -- "the calm after the tempest" release: + o Remove execution bits in text files in bundle. Closes #3617. + o Use generic bad username/password message instead of specific ones when + the user uses incorrect data during login. Closes #3656. + o Fix LoggerWindow saving more than one line return per line in the logs + file. Closes #3714. + o Fix keyring imports so we do not get import errors. Closes: #3759 + o Catch logout problem, display a user message and allow log back in after a + successful logout if there was a logout error before. Closes #3774. + o Fix path prefix helper for the bundle and add regresion tests. Closes #3778. + o Prevent dialogs closing the app when it has been minimized to the tray. Closes #3791. + o Do not try to install resolv-update globally. Closes: #3803 + o Inconsistent hide/show main window from tray action. Closes #3821. + o Allow SMTP to start even when provider does not offer EIP. Closes: #3847 + o Fix username case problem at register/login. Closes #3857. + o Catch IndexError on `first` utility. + o Update git repo name in docs. Closes: #3417 + o Move STANDALONE flag to a module and unify get_path_prefix queries. + Closes #3636. + o Display the Encrypted Internet and Encrypted Email status in the systray + tooltip. Closes #3758. + o Tasktray menu changes, closes #3792. + - Remove the provider domain item (e.g. bitmask.net). + - Rename the EIP status menu items to be more descriptive. + - Change the EIP status menu items from disabled menu items + to submenus with children. + - Move the EIP action menu items under the EIP status submenu tree. + o Adds --version flag. Closes: #3816 + o Refactors EIPConnection to use LEAPConnection state machine. Closes: #3900 + 0.3.2 Sep 6 -- the "no crashes or anything" release: o Fix up script in non-bundle linuces. Closes: #3450 o Logout stops imap and smtp services. Closes: #3553 diff --git a/changes/bug-3617_remove-exec-bits-from-text-in-bundle b/changes/bug-3617_remove-exec-bits-from-text-in-bundle deleted file mode 100644 index caf3a62e..00000000 --- a/changes/bug-3617_remove-exec-bits-from-text-in-bundle +++ /dev/null @@ -1 +0,0 @@ - o Remove execution bits in text files in bundle. Closes #3617. diff --git a/changes/bug-3656_generic-username-password-message b/changes/bug-3656_generic-username-password-message deleted file mode 100644 index 8e6e3e2f..00000000 --- a/changes/bug-3656_generic-username-password-message +++ /dev/null @@ -1,2 +0,0 @@ - o Use generic bad username/password message instead of specific ones when - the user uses incorrect data during login. Closes #3656. diff --git a/changes/bug-3714_fix-logger-saving-several-line-returns b/changes/bug-3714_fix-logger-saving-several-line-returns deleted file mode 100644 index 455c5a95..00000000 --- a/changes/bug-3714_fix-logger-saving-several-line-returns +++ /dev/null @@ -1,2 +0,0 @@ - o Fix LoggerWindow saving more than one line return per line in the logs - file. Closes #3714. diff --git a/changes/bug-3774_fix-logout-error b/changes/bug-3774_fix-logout-error deleted file mode 100644 index ce0951f0..00000000 --- a/changes/bug-3774_fix-logout-error +++ /dev/null @@ -1,2 +0,0 @@ - o Catch logout problem, display a user message and allow log back in after a - successful logout if there was a logout error before. Closes #3774. diff --git a/changes/bug-3778_fix-path-prefix-helper b/changes/bug-3778_fix-path-prefix-helper deleted file mode 100644 index e7cec539..00000000 --- a/changes/bug-3778_fix-path-prefix-helper +++ /dev/null @@ -1 +0,0 @@ - o Fix path prefix helper for the bundle and add regresion tests. Closes #3778. diff --git a/changes/bug-3791_prevent-last-window-close-app b/changes/bug-3791_prevent-last-window-close-app deleted file mode 100644 index 3eeee72a..00000000 --- a/changes/bug-3791_prevent-last-window-close-app +++ /dev/null @@ -1 +0,0 @@ - o Prevent dialogs closing the app when it has been minimized to the tray. Closes #3791. diff --git a/changes/bug-3821_inconsistent-hide-show-mainwindow b/changes/bug-3821_inconsistent-hide-show-mainwindow deleted file mode 100644 index 3fb05a85..00000000 --- a/changes/bug-3821_inconsistent-hide-show-mainwindow +++ /dev/null @@ -1 +0,0 @@ - o Inconsistent hide/show main window from tray action. Closes #3821. diff --git a/changes/bug-3847-start-smtp-without-eip b/changes/bug-3847-start-smtp-without-eip deleted file mode 100644 index 5ed959a4..00000000 --- a/changes/bug-3847-start-smtp-without-eip +++ /dev/null @@ -1 +0,0 @@ - o Allow SMTP to start even when provider does not offer EIP. Closes: #3847 diff --git a/changes/bug-3857_username-case-problem b/changes/bug-3857_username-case-problem deleted file mode 100644 index 3b8ef7b2..00000000 --- a/changes/bug-3857_username-case-problem +++ /dev/null @@ -1 +0,0 @@ - o Fix username case problem at register/login. Closes #3857. diff --git a/changes/bug_3759-fix-keyring-imports b/changes/bug_3759-fix-keyring-imports deleted file mode 100644 index ed489633..00000000 --- a/changes/bug_3759-fix-keyring-imports +++ /dev/null @@ -1 +0,0 @@ - o Fix keyring imports so we do not get import errors. Closes: #3759 diff --git a/changes/bug_3803-do-not-install-resolv-update-globally b/changes/bug_3803-do-not-install-resolv-update-globally deleted file mode 100644 index f6e06d5f..00000000 --- a/changes/bug_3803-do-not-install-resolv-update-globally +++ /dev/null @@ -1 +0,0 @@ - o Do not try to install resolv-update globally. Closes: #3803 diff --git a/changes/bug_fix-first b/changes/bug_fix-first deleted file mode 100644 index 0ef5188c..00000000 --- a/changes/bug_fix-first +++ /dev/null @@ -1 +0,0 @@ - o Catch IndexError on `first` utility. diff --git a/changes/feature-3636_standalone-flag-to-module b/changes/feature-3636_standalone-flag-to-module deleted file mode 100644 index caf16b1a..00000000 --- a/changes/feature-3636_standalone-flag-to-module +++ /dev/null @@ -1,2 +0,0 @@ - o Move STANDALONE flag to a module and unify get_path_prefix queries. - Closes #3636. diff --git a/changes/feature-3758_show-eip-and-mx-status-in-systray-tooltip b/changes/feature-3758_show-eip-and-mx-status-in-systray-tooltip deleted file mode 100644 index edbb3ea0..00000000 --- a/changes/feature-3758_show-eip-and-mx-status-in-systray-tooltip +++ /dev/null @@ -1,2 +0,0 @@ - o Display the Encrypted Internet and Encrypted Email status in the systray - tooltip. Closes #3758. diff --git a/changes/feature-3792_systray-improvements b/changes/feature-3792_systray-improvements deleted file mode 100644 index e10a29c2..00000000 --- a/changes/feature-3792_systray-improvements +++ /dev/null @@ -1,6 +0,0 @@ - o Tasktray menu changes, closes #3792. - - Remove the provider domain item (e.g. bitmask.net). - - Rename the EIP status menu items to be more descriptive. - - Change the EIP status menu items from disabled menu items - to submenus with children. - - Move the EIP action menu items under the EIP status submenu tree. diff --git a/changes/feature_3417_update-repo-in-docs b/changes/feature_3417_update-repo-in-docs deleted file mode 100644 index 065b9497..00000000 --- a/changes/feature_3417_update-repo-in-docs +++ /dev/null @@ -1 +0,0 @@ - o Update git repo name in docs. Closes: #3417 diff --git a/changes/feature_3816-add-version-flag b/changes/feature_3816-add-version-flag deleted file mode 100644 index cfbd2f67..00000000 --- a/changes/feature_3816-add-version-flag +++ /dev/null @@ -1 +0,0 @@ - o Adds --version flag. Closes: #3816 diff --git a/changes/feature_3900-eip-state-machine b/changes/feature_3900-eip-state-machine deleted file mode 100644 index 63aad3d3..00000000 --- a/changes/feature_3900-eip-state-machine +++ /dev/null @@ -1 +0,0 @@ - o Refactors EIPConnection to use LEAPConnection state machine. Closes: #3900 -- cgit v1.2.3 From 5a37ab6bb95d227357fe5e832e32a7187e2b6a11 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 20 Sep 2013 17:14:55 -0300 Subject: Bump soledad.client version requirement. --- changes/VERSION_COMPAT | 3 --- pkg/requirements.pip | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/changes/VERSION_COMPAT b/changes/VERSION_COMPAT index 469ade25..cc00ecf7 100644 --- a/changes/VERSION_COMPAT +++ b/changes/VERSION_COMPAT @@ -8,6 +8,3 @@ # # BEGIN DEPENDENCY LIST ------------------------- # leap.foo.bar>=x.y.z - -leap.soledad.client>=0.4.0 # because of backward-incompatible changes - # https://github.com/leapcode/soledad/pull/76 diff --git a/pkg/requirements.pip b/pkg/requirements.pip index ce93b2ef..154e51b4 100644 --- a/pkg/requirements.pip +++ b/pkg/requirements.pip @@ -19,7 +19,7 @@ python-daemon # this should not be needed for Windows. keyring leap.common>=0.3.2 -leap.soledad.client>=0.3.0 +leap.soledad.client>=0.4.0 leap.keymanager>=0.2.0 leap.mail>=0.3.2 -- cgit v1.2.3