From 4e5731c58becec8043cb2de5c3b9214f1f8cc849 Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Mon, 4 Nov 2013 19:26:15 -0300
Subject: Support html logs in the logger window.

Escape special characters to display them correctly in the logger window.

[Closes #4146]
---
 src/leap/bitmask/gui/loggerwindow.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'src')

diff --git a/src/leap/bitmask/gui/loggerwindow.py b/src/leap/bitmask/gui/loggerwindow.py
index ad2ceded..6ef58558 100644
--- a/src/leap/bitmask/gui/loggerwindow.py
+++ b/src/leap/bitmask/gui/loggerwindow.py
@@ -19,6 +19,7 @@
 History log window
 """
 import logging
+import cgi
 
 from PySide import QtGui
 
@@ -90,7 +91,7 @@ class LoggerWindow(QtGui.QDialog):
             logging.CRITICAL: "background: red; color: white; font: bold;"
         }
         level = log[LeapLogHandler.RECORD_KEY].levelno
-        message = log[LeapLogHandler.MESSAGE_KEY]
+        message = cgi.escape(log[LeapLogHandler.MESSAGE_KEY])
 
         if self._logs_to_display[level]:
             open_tag = "<tr style='" + html_style[level] + "'>"
-- 
cgit v1.2.3


From 104c48b6eb3d6c2a092fae4d50ddd54d0130609b Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Tue, 5 Nov 2013 14:10:33 -0300
Subject: Move string encoding to srpregister.

---
 src/leap/bitmask/crypto/srpregister.py | 3 ++-
 src/leap/bitmask/gui/wizard.py         | 4 +---
 2 files changed, 3 insertions(+), 4 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/crypto/srpregister.py b/src/leap/bitmask/crypto/srpregister.py
index 5c0a8efc..61f1899a 100644
--- a/src/leap/bitmask/crypto/srpregister.py
+++ b/src/leap/bitmask/crypto/srpregister.py
@@ -108,7 +108,8 @@ class SRPRegister(QtCore.QObject):
         :rparam: (ok, request)
         """
 
-        username = username.lower()
+        username = username.lower().encode('utf-8')
+        password = password.encode('utf-8')
 
         salt, verifier = self._srp.create_salted_verification_key(
             username,
diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py
index 6ba65410..e9c1d86c 100644
--- a/src/leap/bitmask/gui/wizard.py
+++ b/src/leap/bitmask/gui/wizard.py
@@ -226,9 +226,7 @@ class Wizard(QtGui.QWizard):
                 self._registration_finished)
 
             threads.deferToThread(
-                partial(register.register_user,
-                        username.encode("utf8"),
-                        password.encode("utf8")))
+                partial(register.register_user, username, password))
 
             self._username = username
             self._password = password
-- 
cgit v1.2.3


From 5ae44d80876aa9c1e60280fbf437ee687d9bc3c8 Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Tue, 5 Nov 2013 14:59:30 -0300
Subject: Handle Timeout errors during register.

Also catch all request exceptions to avoid failures.

[Closes #4358]
---
 src/leap/bitmask/crypto/srpregister.py | 3 +--
 src/leap/bitmask/gui/wizard.py         | 3 ++-
 2 files changed, 3 insertions(+), 3 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/crypto/srpregister.py b/src/leap/bitmask/crypto/srpregister.py
index 61f1899a..e110df68 100644
--- a/src/leap/bitmask/crypto/srpregister.py
+++ b/src/leap/bitmask/crypto/srpregister.py
@@ -141,8 +141,7 @@ class SRPRegister(QtCore.QObject):
                                      verify=self._provider_config.
                                      get_ca_cert_path())
 
-        except (requests.exceptions.SSLError,
-                requests.exceptions.ConnectionError) as exc:
+        except requests.exceptions.RequestExceptions as exc:
             logger.error(exc.message)
             ok = False
         else:
diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py
index e9c1d86c..8de5802e 100644
--- a/src/leap/bitmask/gui/wizard.py
+++ b/src/leap/bitmask/gui/wizard.py
@@ -280,7 +280,8 @@ class Wizard(QtGui.QWizard):
             old_username = self._username
             self._username = None
             self._password = None
-            error_msg = self.tr("Unknown error")
+            error_msg = self.tr("Something has gone wrong. "
+                                "Please try again.")
             try:
                 content, _ = get_content(req)
                 json_content = json.loads(content)
-- 
cgit v1.2.3


From ac5c63a2636b1f764633283d18f04e0fc63a7b4f Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Tue, 5 Nov 2013 15:20:16 -0300
Subject: Fix typo

---
 src/leap/bitmask/crypto/srpregister.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src')

diff --git a/src/leap/bitmask/crypto/srpregister.py b/src/leap/bitmask/crypto/srpregister.py
index e110df68..02a1ea63 100644
--- a/src/leap/bitmask/crypto/srpregister.py
+++ b/src/leap/bitmask/crypto/srpregister.py
@@ -141,7 +141,7 @@ class SRPRegister(QtCore.QObject):
                                      verify=self._provider_config.
                                      get_ca_cert_path())
 
-        except requests.exceptions.RequestExceptions as exc:
+        except requests.exceptions.RequestException as exc:
             logger.error(exc.message)
             ok = False
         else:
-- 
cgit v1.2.3


From f04c992c2d06185aaca3f06bcb72a434fae33acf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= <chiiph@leap.se>
Date: Wed, 6 Nov 2013 11:18:49 -0300
Subject: Various minor OSX fixes

---
 src/leap/bitmask/gui/mainwindow.py    | 10 ++++------
 src/leap/bitmask/gui/statemachines.py |  2 +-
 2 files changed, 5 insertions(+), 7 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index 5eb9e6dc..549097ae 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -334,7 +334,7 @@ class MainWindow(QtGui.QMainWindow):
         self.eip_machine = None
         # start event machines
         self.start_eip_machine()
-        self._mail_conductor.start_mail_machine(parent=self)
+        self._mail_conductor.start_mail_machine()
 
         if self._first_run():
             self._wizard_firstrun = True
@@ -674,10 +674,9 @@ class MainWindow(QtGui.QMainWindow):
         Toggles the window visibility
         """
         visible = self.isVisible() and self.isActiveWindow()
-        qApp = QtCore.QCoreApplication.instance()
 
         if not visible:
-            qApp.setQuitOnLastWindowClosed(True)
+            QtGui.QApplication.setQuitOnLastWindowClosed(True)
             self.show()
             self.activateWindow()
             self.raise_()
@@ -685,7 +684,7 @@ class MainWindow(QtGui.QMainWindow):
             # 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)
+            QtGui.QApplication.setQuitOnLastWindowClosed(False)
             self.hide()
 
         # Wait a bit until the window visibility has changed so
@@ -1657,8 +1656,7 @@ class MainWindow(QtGui.QMainWindow):
         # UI stuff.
 
         # Set this in case that the app is hidden
-        qApp = QtCore.QCoreApplication.instance()
-        qApp.setQuitOnLastWindowClosed(True)
+        QtGui.QApplication.setQuitOnLastWindowClosed(True)
 
         self._cleanup_and_quit()
 
diff --git a/src/leap/bitmask/gui/statemachines.py b/src/leap/bitmask/gui/statemachines.py
index 386cb75f..93731ce0 100644
--- a/src/leap/bitmask/gui/statemachines.py
+++ b/src/leap/bitmask/gui/statemachines.py
@@ -357,7 +357,7 @@ class ConnectionMachineBuilder(object):
         parent = kwargs.get('parent', None)
 
         # 1. create machine
-        machine = CompositeMachine(parent=parent)
+        machine = CompositeMachine()
 
         # 2. create states
         off = States.Off(conn.qtsigs.disconnected_signal,
-- 
cgit v1.2.3


From 768bdfa653e7ef9829f355822ee0273072520c5f Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Wed, 6 Nov 2013 13:00:13 -0300
Subject: Fix 'cancel' and 'back' misbehavior.

- Check if the 'next' button should be enabled after 'cancel' or 'back'.
- Also, when the radio button is switched from existing to new provider,
check if we need to enable the 'check' button.

[Closes #4148]
---
 src/leap/bitmask/gui/wizard.py | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py
index 8de5802e..5c4a6f8e 100644
--- a/src/leap/bitmask/gui/wizard.py
+++ b/src/leap/bitmask/gui/wizard.py
@@ -111,8 +111,9 @@ class Wizard(QtGui.QWizard):
 
         self.currentIdChanged.connect(self._current_id_changed)
 
-        self.ui.lnProvider.textChanged.connect(
-            self._enable_check)
+        self.ui.lnProvider.textChanged.connect(self._enable_check)
+        self.ui.rbNewProvider.toggled.connect(
+            lambda x: self._enable_check())
 
         self.ui.lblUser.returnPressed.connect(
             self._focus_password)
@@ -193,8 +194,19 @@ class Wizard(QtGui.QWizard):
     def get_services(self):
         return self._selected_services
 
-    def _enable_check(self, text):
-        self.ui.btnCheck.setEnabled(len(self.ui.lnProvider.text()) != 0)
+    @QtCore.Slot()
+    def _enable_check(self):
+        """
+        SLOT
+        TRIGGER:
+            self.ui.lnProvider.textChanged
+
+        Enables/disables the 'check' button in the SELECT_PROVIDER_PAGE
+        depending on the lnProvider content.
+        """
+        enabled = len(self.ui.lnProvider.text()) != 0
+        enabled = enabled and self.ui.rbNewProvider.isChecked()
+        self.ui.btnCheck.setEnabled(enabled)
         self._reset_provider_check()
 
     def _focus_password(self):
@@ -555,8 +567,9 @@ class Wizard(QtGui.QWizard):
         Prepares the pages when they appear
         """
         if pageId == self.SELECT_PROVIDER_PAGE:
-            self._reset_provider_check()
-            self._enable_check("")
+            skip = self.ui.rbExistingProvider.isChecked()
+            self._enable_check()
+            self._skip_provider_checks(skip)
 
         if pageId == self.SETUP_PROVIDER_PAGE:
             self._reset_provider_setup()
-- 
cgit v1.2.3


From 1899d12a134d7657a902bd9d4006098a98e02277 Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Wed, 6 Nov 2013 15:20:44 -0300
Subject: Add hint about the duration of key generation.

[Closes #3958]
---
 src/leap/bitmask/gui/mail_status.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

(limited to 'src')

diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py
index c1e82d4d..d637fd52 100644
--- a/src/leap/bitmask/gui/mail_status.py
+++ b/src/leap/bitmask/gui/mail_status.py
@@ -296,7 +296,9 @@ class MailStatusWidget(QtGui.QWidget):
         # elif req.event == proto.KEYMANAGER_KEY_NOT_FOUND:
         #     ext_status = self.tr("Key not found!")
         elif req.event == proto.KEYMANAGER_STARTED_KEY_GENERATION:
-            ext_status = self.tr("Generating new key, please wait...")
+            ext_status = self.tr(
+                "Generating new key, please wait... \n"
+                "(this may take up to 10 minutes depending on the machine)")
         elif req.event == proto.KEYMANAGER_FINISHED_KEY_GENERATION:
             ext_status = self.tr("Finished generating key!")
         elif req.event == proto.KEYMANAGER_DONE_UPLOADING_KEYS:
-- 
cgit v1.2.3


From 5955b267cdb6e82c57bee74a66ba8fa3d5308c60 Mon Sep 17 00:00:00 2001
From: Kali Kaneko <kali@leap.se>
Date: Wed, 6 Nov 2013 11:15:34 -0200
Subject: Initializes mail service with the user id.

This will be used to properly obtain the private key that now is a
property. It will also be needed for the imap authentication.
---
 src/leap/bitmask/gui/mainwindow.py          | 18 ++++++++-------
 src/leap/bitmask/services/mail/conductor.py | 35 ++++++++++++++++-------------
 2 files changed, 30 insertions(+), 23 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index 5eb9e6dc..2e050d44 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -905,7 +905,6 @@ class MainWindow(QtGui.QMainWindow):
         Once the user is properly authenticated, try starting the EIP
         service
         """
-
         # In general we want to "filter" likely complicated error
         # messages, but in this case, the messages make more sense as
         # they come. Since they are "Unknown user" or "Unknown
@@ -914,19 +913,20 @@ class MainWindow(QtGui.QMainWindow):
 
         if ok:
             self._logged_user = self._login_widget.get_user()
-            # We leave a bit of room for the user to see the
-            # "Succeeded" message and then we switch to the EIP status
-            # panel
-            QtCore.QTimer.singleShot(1000, self._switch_to_status)
+            user = self._logged_user
+            domain = self._provider_config.get_domain()
+            userid = "%s@%s" % (user, domain)
+            logger.debug("USERID: " % userid)
+            self._mail_conductor.userid = userid
             self._login_defer = None
+            self._start_eip_bootstrap()
         else:
             self._login_widget.set_enabled(True)
 
-    def _switch_to_status(self):
-        # TODO this method name is confusing as hell.
+    def _start_eip_bootstrap(self):
         """
         Changes the stackedWidget index to the EIP status one and
-        triggers the eip bootstrapping
+        triggers the eip bootstrapping.
         """
 
         self._login_widget.logged_in()
@@ -949,6 +949,8 @@ class MainWindow(QtGui.QMainWindow):
         else:
             self._mail_status.set_disabled()
 
+        # XXX the config should be downloaded from the start_eip
+        # method.
         self._download_eip_config()
 
     ###################################################################
diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py
index c294381b..4d34a13b 100644
--- a/src/leap/bitmask/services/mail/conductor.py
+++ b/src/leap/bitmask/services/mail/conductor.py
@@ -81,16 +81,12 @@ class IMAPControl(object):
                     "We need a non-null keymanager for initializing imap "
                     "service")
 
-        if self.imap_service is None:
-            # first time.
-            self.imap_service, \
-            self.imap_port, \
+        self.imap_service, self.imap_port, \
             self.imap_factory = imap.start_imap_service(
                 self._soledad,
-                self._keymanager)
-        else:
-            # we have the fetcher. just start it.
-            self.imap_service.start_loop()
+                self._keymanager,
+                userid=self.userid)
+        self.imap_service.start_loop()
 
     def stop_imap_service(self):
         """
@@ -339,11 +335,25 @@ class MailConductor(IMAPControl, SMTPControl):
         SMTPControl.__init__(self)
         self._soledad = soledad
         self._keymanager = keymanager
-
         self._mail_machine = None
-
         self._mail_connection = mail_connection.MailConnection()
 
+        self.userid = None
+
+    @property
+    def userid(self):
+        return self._userid
+
+    @userid.setter
+    def _userid(self, userid):
+        """
+        Sets the user id this conductor is configured for.
+
+        :param userid: the user id, in the form "user@provider"
+        :type userid: str
+        """
+        self._userid = userid
+
     def start_mail_machine(self, **kwargs):
         """
         Starts mail machine.
@@ -354,15 +364,10 @@ class MailConductor(IMAPControl, SMTPControl):
 
         # we have instantiated the connections while building the composite
         # machines, and we have to use the qtsigs instantiated there.
-        # XXX we could probably use a proxy here too to make the thing
-        # transparent.
         self.set_imap_connection(imap.conn)
         self.set_smtp_connection(smtp.conn)
 
         self._mail_machine = mail
-        # XXX -------------------
-        # need to keep a reference?
-        #self._mail_events = mail.events
         self._mail_machine.start()
 
         self._imap_machine = imap
-- 
cgit v1.2.3


From 276810a3767fdba5e3ba543b23afc49f050b46b0 Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Wed, 6 Nov 2013 17:50:42 -0300
Subject: Remember setup provider checks.

Also, on finish:
- hide checks groupBox
- clear domain lineEdit

[Closes #3815]
---
 src/leap/bitmask/gui/wizard.py | 34 ++++++++++++++++++++++++++++++----
 1 file changed, 30 insertions(+), 4 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py
index 5c4a6f8e..8508067e 100644
--- a/src/leap/bitmask/gui/wizard.py
+++ b/src/leap/bitmask/gui/wizard.py
@@ -147,6 +147,24 @@ class Wizard(QtGui.QWizard):
 
         self._load_configured_providers()
 
+        self._provider_checks_ok = False
+        self.finished.connect(self._wizard_finished)
+
+    @QtCore.Slot()
+    def _wizard_finished(self):
+        """
+        SLOT
+        TRIGGER:
+            self.finished
+
+        This method is called when the wizard is accepted or rejected.
+        Here we do the cleanup needed to use the wizard again reusing the
+        instance.
+        """
+        self._provider_checks_ok = False
+        self.ui.lnProvider.setText('')
+        self.ui.grpCheckProvider.setVisible(False)
+
     def _load_configured_providers(self):
         """
         Loads the configured providers into the wizard providers combo box.
@@ -195,7 +213,7 @@ class Wizard(QtGui.QWizard):
         return self._selected_services
 
     @QtCore.Slot()
-    def _enable_check(self):
+    def _enable_check(self, reset=True):
         """
         SLOT
         TRIGGER:
@@ -207,7 +225,9 @@ class Wizard(QtGui.QWizard):
         enabled = len(self.ui.lnProvider.text()) != 0
         enabled = enabled and self.ui.rbNewProvider.isChecked()
         self.ui.btnCheck.setEnabled(enabled)
-        self._reset_provider_check()
+
+        if reset:
+            self._reset_provider_check()
 
     def _focus_password(self):
         """
@@ -350,6 +370,8 @@ class Wizard(QtGui.QWizard):
         if len(self.ui.lnProvider.text()) == 0:
             return
 
+        self._provider_checks_ok = False
+
         self.ui.grpCheckProvider.setVisible(True)
         self.ui.btnCheck.setEnabled(False)
         self.ui.lnProvider.setEnabled(False)
@@ -459,6 +481,7 @@ class Wizard(QtGui.QWizard):
                                                    "provider.json")):
             self._complete_task(data, self.ui.lblProviderInfo,
                                 True, self.SELECT_PROVIDER_PAGE)
+            self._provider_checks_ok = True
         else:
             new_data = {
                 self._provider_bootstrapper.PASSED_KEY: False,
@@ -568,8 +591,11 @@ class Wizard(QtGui.QWizard):
         """
         if pageId == self.SELECT_PROVIDER_PAGE:
             skip = self.ui.rbExistingProvider.isChecked()
-            self._enable_check()
-            self._skip_provider_checks(skip)
+            if not self._provider_checks_ok:
+                self._enable_check()
+                self._skip_provider_checks(skip)
+            else:
+                self._enable_check(reset=False)
 
         if pageId == self.SETUP_PROVIDER_PAGE:
             self._reset_provider_setup()
-- 
cgit v1.2.3


From 9674b93f9d6fbe25e10330a6f807e5b7196c01b0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= <chiiph@leap.se>
Date: Wed, 6 Nov 2013 11:54:03 -0300
Subject: Reject sender if it's not the logged in user

---
 src/leap/bitmask/gui/mainwindow.py          | 1 -
 src/leap/bitmask/services/mail/conductor.py | 3 ++-
 2 files changed, 2 insertions(+), 2 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index a91f4e71..91bbe9cb 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -915,7 +915,6 @@ class MainWindow(QtGui.QMainWindow):
             user = self._logged_user
             domain = self._provider_config.get_domain()
             userid = "%s@%s" % (user, domain)
-            logger.debug("USERID: " % userid)
             self._mail_conductor.userid = userid
             self._login_defer = None
             self._start_eip_bootstrap()
diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py
index 4d34a13b..6dcf0c6f 100644
--- a/src/leap/bitmask/services/mail/conductor.py
+++ b/src/leap/bitmask/services/mail/conductor.py
@@ -200,6 +200,7 @@ class SMTPControl(object):
         from leap.mail.smtp import setup_smtp_relay
         self._smtp_service, self._smtp_port = setup_smtp_relay(
             port=2013,
+            userid=self.userid,
             keymanager=self._keymanager,
             smtp_host=host,
             smtp_port=port,
@@ -345,7 +346,7 @@ class MailConductor(IMAPControl, SMTPControl):
         return self._userid
 
     @userid.setter
-    def _userid(self, userid):
+    def userid(self, userid):
         """
         Sets the user id this conductor is configured for.
 
-- 
cgit v1.2.3


From fb0d8da17541c48ed20d829d706e4cd9d3b4dde6 Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Thu, 7 Nov 2013 09:38:28 -0300
Subject: Remember provider CA checks.

[Closes #3814]
---
 src/leap/bitmask/gui/wizard.py | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py
index 8508067e..5f5224ae 100644
--- a/src/leap/bitmask/gui/wizard.py
+++ b/src/leap/bitmask/gui/wizard.py
@@ -148,6 +148,7 @@ class Wizard(QtGui.QWizard):
         self._load_configured_providers()
 
         self._provider_checks_ok = False
+        self._provider_setup_ok = False
         self.finished.connect(self._wizard_finished)
 
     @QtCore.Slot()
@@ -162,6 +163,7 @@ class Wizard(QtGui.QWizard):
         instance.
         """
         self._provider_checks_ok = False
+        self._provider_setup_ok = False
         self.ui.lnProvider.setText('')
         self.ui.grpCheckProvider.setVisible(False)
 
@@ -372,6 +374,10 @@ class Wizard(QtGui.QWizard):
 
         self._provider_checks_ok = False
 
+        # just in case that the user has already setup a provider and
+        # go 'back' to check a provider
+        self._provider_setup_ok = False
+
         self.ui.grpCheckProvider.setVisible(True)
         self.ui.btnCheck.setEnabled(False)
         self.ui.lnProvider.setEnabled(False)
@@ -533,6 +539,7 @@ class Wizard(QtGui.QWizard):
         """
         self._complete_task(data, self.ui.lblCheckApiCert,
                             True, self.SETUP_PROVIDER_PAGE)
+        self._provider_setup_ok = True
 
     def _service_selection_changed(self, service, state):
         """
@@ -598,14 +605,14 @@ class Wizard(QtGui.QWizard):
                 self._enable_check(reset=False)
 
         if pageId == self.SETUP_PROVIDER_PAGE:
-            self._reset_provider_setup()
-            self.page(pageId).setSubTitle(self.tr("Gathering configuration "
-                                                  "options for %s") %
-                                          (self._provider_config
-                                           .get_name(),))
-            self.ui.lblDownloadCaCert.setPixmap(self.QUESTION_ICON)
-            self._provider_setup_defer = self._provider_bootstrapper.\
-                run_provider_setup_checks(self._provider_config)
+            if not self._provider_setup_ok:
+                self._reset_provider_setup()
+                sub_title = self.tr("Gathering configuration options for {0}")
+                sub_title = sub_title.format(self._provider_config.get_name())
+                self.page(pageId).setSubTitle(sub_title)
+                self.ui.lblDownloadCaCert.setPixmap(self.QUESTION_ICON)
+                self._provider_setup_defer = self._provider_bootstrapper.\
+                    run_provider_setup_checks(self._provider_config)
 
         if pageId == self.PRESENT_PROVIDER_PAGE:
             self.page(pageId).setSubTitle(self.tr("Description of services "
-- 
cgit v1.2.3


From 540734c3aaffcdcd9140f0f6f723a7fac4ab18f0 Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Fri, 8 Nov 2013 16:04:19 -0300
Subject: Use module attributes to store services strings.

---
 src/leap/bitmask/services/__init__.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

(limited to 'src')

diff --git a/src/leap/bitmask/services/__init__.py b/src/leap/bitmask/services/__init__.py
index e62277b6..ba12ba4e 100644
--- a/src/leap/bitmask/services/__init__.py
+++ b/src/leap/bitmask/services/__init__.py
@@ -37,7 +37,9 @@ from leap.common.files import get_mtime
 logger = logging.getLogger(__name__)
 
 
-DEPLOYED = ["openvpn", "mx"]
+EIP_SERVICE = u"openvpn"
+MX_SERVICE = u"mx"
+DEPLOYED = [EIP_SERVICE, MX_SERVICE]
 
 
 def get_service_display_name(service):
-- 
cgit v1.2.3


From f3217d074ff20e6973ec382ad78100c77c6af081 Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Fri, 8 Nov 2013 11:24:13 -0300
Subject: Use display service name instead of hardcode it.

---
 src/leap/bitmask/gui/eip_status.py  | 11 +++++++----
 src/leap/bitmask/gui/mail_status.py | 10 +++++++---
 2 files changed, 14 insertions(+), 7 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/gui/eip_status.py b/src/leap/bitmask/gui/eip_status.py
index 324586c0..fbb8ffe1 100644
--- a/src/leap/bitmask/gui/eip_status.py
+++ b/src/leap/bitmask/gui/eip_status.py
@@ -26,6 +26,7 @@ from PySide import QtCore, QtGui
 
 from leap.bitmask.services.eip.connection import EIPConnection
 from leap.bitmask.services.eip.vpnprocess import VPNManager
+from leap.bitmask.services import get_service_display_name, EIP_SERVICE
 from leap.bitmask.platform_init import IS_LINUX
 from leap.bitmask.util.averages import RateMovingAverage
 from leap.common.check import leap_assert_type
@@ -58,6 +59,7 @@ class EIPStatusWidget(QtGui.QWidget):
 
         # set systray tooltip status
         self._eip_status = ""
+        self._service_name = get_service_display_name(EIP_SERVICE)
 
         self.ui.eip_bandwidth.hide()
 
@@ -245,7 +247,7 @@ class EIPStatusWidget(QtGui.QWidget):
         # probably the best thing would be to make a transitional
         # transition there, but that's more involved.
         self.eip_button.hide()
-        msg = self.tr("You must login to use Encrypted Internet")
+        msg = self.tr("You must login to use {0}".format(self._service_name))
         self.eip_label.setText(msg)
 
     @QtCore.Slot()
@@ -418,14 +420,15 @@ class EIPStatusWidget(QtGui.QWidget):
         """
         selected_pixmap = self.ERROR_ICON
         selected_pixmap_tray = self.ERROR_ICON_TRAY
-        tray_message = self.tr("Encrypted Internet: OFF")
+        tray_message = self.tr("{0}: OFF".format(self._service_name))
         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("Encrypted Internet: Starting...")
+            tray_message = self.tr("{0}: Starting...").format(
+                self._service_name)
         elif status in ("CONNECTED"):
-            tray_message = self.tr("Encrypted Internet: ON")
+            tray_message = self.tr("{0}: ON".format(self._service_name))
             selected_pixmap = self.CONNECTED_ICON
             selected_pixmap_tray = self.CONNECTED_ICON_TRAY
             self._eip_status = 'ON'
diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py
index d637fd52..2ca0fb0a 100644
--- a/src/leap/bitmask/gui/mail_status.py
+++ b/src/leap/bitmask/gui/mail_status.py
@@ -22,6 +22,7 @@ import logging
 from PySide import QtCore, QtGui
 
 from leap.bitmask.platform_init import IS_LINUX
+from leap.bitmask.services import get_service_display_name, MX_SERVICE
 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
@@ -58,6 +59,7 @@ class MailStatusWidget(QtGui.QWidget):
 
         # set systray tooltip status
         self._mx_status = ""
+        self._service_name = get_service_display_name(MX_SERVICE)
 
         # Set the Mail status icons
         self.CONNECTING_ICON = None
@@ -213,7 +215,8 @@ class MailStatusWidget(QtGui.QWidget):
         icon = self.ERROR_ICON
         if ready == 0:
             self.ui.lblMailStatus.setText(
-                self.tr("You must be logged in to use encrypted email."))
+                self.tr("You must be logged in to use {0}.").format(
+                    self._service_name))
         elif ready == 1:
             icon = self.CONNECTING_ICON
             self._mx_status = self.tr('Starting..')
@@ -436,5 +439,6 @@ class MailStatusWidget(QtGui.QWidget):
         Displays the correct UI for the disabled state.
         """
         self._disabled = True
-        self._set_mail_status(
-            self.tr("You must be logged in to use encrypted email."), -1)
+        status = self.tr("You must be logged in to use {0}.").format(
+            self._service_name)
+        self._set_mail_status(status, -1)
-- 
cgit v1.2.3


From 6714b423a4ae879e23a82a60480387186e737ab1 Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Thu, 7 Nov 2013 17:46:02 -0300
Subject: Use custom systray that ease the tooltip use.

- Create a custom SysTray that allows us to set services tooltips
independently.
- Initialize tooltip with service name at start.
- Update required service status on tooltip update.

[Closes #3998]
---
 src/leap/bitmask/gui/eip_status.py  | 17 ++++++-------
 src/leap/bitmask/gui/mail_status.py | 21 ++++++----------
 src/leap/bitmask/gui/mainwindow.py  |  4 ++-
 src/leap/bitmask/gui/systray.py     | 49 +++++++++++++++++++++++++++++++++++++
 4 files changed, 67 insertions(+), 24 deletions(-)
 create mode 100644 src/leap/bitmask/gui/systray.py

(limited to 'src')

diff --git a/src/leap/bitmask/gui/eip_status.py b/src/leap/bitmask/gui/eip_status.py
index fbb8ffe1..c41d9706 100644
--- a/src/leap/bitmask/gui/eip_status.py
+++ b/src/leap/bitmask/gui/eip_status.py
@@ -183,21 +183,22 @@ class EIPStatusWidget(QtGui.QWidget):
 
     def set_systray(self, systray):
         """
-        Sets the systray object to use.
+        Sets the systray object to use and adds the service line for EIP.
 
         :param systray: Systray object
         :type systray: QtGui.QSystemTrayIcon
         """
         leap_assert_type(systray, QtGui.QSystemTrayIcon)
         self._systray = systray
-        self._systray.setToolTip(self.tr("All services are OFF"))
+        eip_status = self.tr("{0}: OFF").format(self._service_name)
+        self._systray.set_service_tooltip(EIP_SERVICE, eip_status)
 
     def _update_systray_tooltip(self):
         """
-        Updates the system tray icon tooltip using the eip and mx status.
+        Updates the system tray tooltip using the eip status.
         """
-        status = self.tr("Encrypted Internet: {0}").format(self._eip_status)
-        self._systray.setToolTip(status)
+        eip_status = u"{0}: {1}".format(self._service_name, self._eip_status)
+        self._systray.set_service_tooltip(EIP_SERVICE, eip_status)
 
     def set_action_eip_startstop(self, action_eip_startstop):
         """
@@ -395,10 +396,8 @@ class EIPStatusWidget(QtGui.QWidget):
             # the UI won't update properly
             QtCore.QTimer.singleShot(
                 0, self.eipconnection.qtsigs.do_disconnect_signal)
-            QtCore.QTimer.singleShot(0, partial(self.set_eip_status,
-                                                self.tr("Unable to start VPN, "
-                                                        "it's already "
-                                                        "running.")))
+            msg = self.tr("Unable to start VPN, it's already running.")
+            QtCore.QTimer.singleShot(0, partial(self.set_eip_status, msg))
         else:
             self.set_eip_status(status)
 
diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py
index 2ca0fb0a..e89fb376 100644
--- a/src/leap/bitmask/gui/mail_status.py
+++ b/src/leap/bitmask/gui/mail_status.py
@@ -152,29 +152,22 @@ class MailStatusWidget(QtGui.QWidget):
 
     def set_systray(self, systray):
         """
-        Sets the systray object to use.
+        Sets the systray object to use and adds the service line for MX.
 
         :param systray: Systray object
         :type systray: QtGui.QSystemTrayIcon
         """
         leap_assert_type(systray, QtGui.QSystemTrayIcon)
         self._systray = systray
-        self._systray.setToolTip(self.tr("All services are OFF"))
+        mx_status = self.tr("{0}: OFF").format(self._service_name)
+        self._systray.set_service_tooltip(MX_SERVICE, mx_status)
 
     def _update_systray_tooltip(self):
         """
-        Updates the system tray icon tooltip using the eip and mx status.
-        """
-        # TODO: Figure out how to handle this with the two status in different
-        # classes
-        # XXX right now we could connect the state transition signals of the
-        # two connection machines (EIP/Mail) to a class that keeps track of the
-        # state -- kali
-        # status = self.tr("Encrypted Internet: {0}").format(self._eip_status)
-        # status += '\n'
-        # status += self.tr("Mail is {0}").format(self._mx_status)
-        # self._systray.setToolTip(status)
-        pass
+        Updates the system tray tooltip using the mx status.
+        """
+        mx_status = u"{0}: {1}".format(self._service_name, self._mx_status)
+        self._systray.set_service_tooltip(MX_SERVICE, mx_status)
 
     def set_action_mail_status(self, action_mail_status):
         """
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index 91bbe9cb..f7142df7 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -36,6 +36,7 @@ from leap.bitmask.gui import statemachines
 from leap.bitmask.gui.eip_status import EIPStatusWidget
 from leap.bitmask.gui.mail_status import MailStatusWidget
 from leap.bitmask.gui.wizard import Wizard
+from leap.bitmask.gui.systray import SysTray
 
 from leap.bitmask import provider
 from leap.bitmask.platform_init import IS_WIN, IS_MAC
@@ -628,12 +629,13 @@ class MainWindow(QtGui.QMainWindow):
         systrayMenu.addAction(self._action_mail_status)
         systrayMenu.addSeparator()
         systrayMenu.addAction(self.ui.action_quit)
-        self._systray = QtGui.QSystemTrayIcon(self)
+        self._systray = SysTray(self)
         self._systray.setContextMenu(systrayMenu)
         self._systray.setIcon(self._eip_status.ERROR_ICON_TRAY)
         self._systray.setVisible(True)
         self._systray.activated.connect(self._tray_activated)
 
+        self._mail_status.set_systray(self._systray)
         self._eip_status.set_systray(self._systray)
 
     def _tray_activated(self, reason=None):
diff --git a/src/leap/bitmask/gui/systray.py b/src/leap/bitmask/gui/systray.py
new file mode 100644
index 00000000..d30b5f32
--- /dev/null
+++ b/src/leap/bitmask/gui/systray.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+# systray.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 <http://www.gnu.org/licenses/>.
+"""
+Custom system tray manager.
+"""
+
+from PySide import QtGui
+
+from leap.common.check import leap_assert_type
+
+
+class SysTray(QtGui.QSystemTrayIcon):
+    """
+    Custom system tray that allows us to use a more 'intelligent' tooltip.
+    """
+
+    def __init__(self, parent=None):
+        QtGui.QSystemTrayIcon.__init__(self, parent)
+        self._services = {}
+
+    def set_service_tooltip(self, service, tooltip):
+        """
+        Sets the service tooltip.
+
+        :param service: service name identifier
+        :type service: unicode
+        :param tooltip: tooltip to display for that service
+        :type tooltip: unicode
+        """
+        leap_assert_type(service, unicode)
+        leap_assert_type(tooltip, unicode)
+
+        self._services[service] = tooltip
+        tooltip = "\n".join(self._services.values())
+        self.setToolTip(tooltip)
-- 
cgit v1.2.3


From 13470807d96cfb6e10bc647aab8111a2b61bb6ea Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Fri, 8 Nov 2013 16:37:48 -0300
Subject: Use service's module strings instead of locals.

---
 src/leap/bitmask/gui/mainwindow.py | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index f7142df7..f3043809 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -45,6 +45,7 @@ from leap.bitmask.provider.providerbootstrapper import ProviderBootstrapper
 
 from leap.bitmask.services.mail import conductor as mail_conductor
 
+from leap.bitmask.services import EIP_SERVICE, MX_SERVICE
 from leap.bitmask.services.eip import eipconfig
 from leap.bitmask.services.eip import get_openvpn_management
 from leap.bitmask.services.eip.eipbootstrapper import EIPBootstrapper
@@ -87,9 +88,6 @@ class MainWindow(QtGui.QMainWindow):
     LOGIN_INDEX = 0
     EIP_STATUS_INDEX = 1
 
-    OPENVPN_SERVICE = "openvpn"
-    MX_SERVICE = "mx"
-
     # Signals
     eip_needs_login = QtCore.Signal([])
     new_updates = QtCore.Signal(object)
@@ -598,8 +596,8 @@ class MainWindow(QtGui.QMainWindow):
                 for service in provider_config.get_services():
                     services.add(service)
 
-        self.ui.eipWidget.setVisible(self.OPENVPN_SERVICE in services)
-        self.ui.mailWidget.setVisible(self.MX_SERVICE in services)
+        self.ui.eipWidget.setVisible(EIP_SERVICE in services)
+        self.ui.mailWidget.setVisible(MX_SERVICE in services)
 
     #
     # systray
@@ -938,7 +936,7 @@ class MainWindow(QtGui.QMainWindow):
         # TODO separate UI from logic.
         # TODO soledad should check if we want to run only over EIP.
         if self._provider_config.provides_mx() and \
-           self._enabled_services.count(self.MX_SERVICE) > 0:
+           self._enabled_services.count(MX_SERVICE) > 0:
             self._mail_status.about_to_start()
 
             self._soledad_bootstrapper.run_soledad_setup_checks(
@@ -1039,7 +1037,7 @@ class MainWindow(QtGui.QMainWindow):
         # TODO for simmetry, this should be called start_smtp_service
         # (and delegate all the checks to the conductor)
         if self._provider_config.provides_mx() and \
-                self._enabled_services.count(self.MX_SERVICE) > 0:
+                self._enabled_services.count(MX_SERVICE) > 0:
             self._mail_conductor.smtp_bootstrapper.run_smtp_setup_checks(
                 self._provider_config,
                 self._mail_conductor.smtp_config,
@@ -1068,7 +1066,7 @@ class MainWindow(QtGui.QMainWindow):
             self.soledad_ready
         """
         if self._provider_config.provides_mx() and \
-                self._enabled_services.count(self.MX_SERVICE) > 0:
+                self._enabled_services.count(MX_SERVICE) > 0:
             self._mail_conductor.start_imap_service()
 
     def _on_mail_client_logged_in(self, req):
@@ -1418,7 +1416,7 @@ class MainWindow(QtGui.QMainWindow):
         provider_config = self._get_best_provider_config()
 
         if provider_config.provides_eip() and \
-                self._enabled_services.count(self.OPENVPN_SERVICE) > 0 and \
+                self._enabled_services.count(EIP_SERVICE) > 0 and \
                 not self._already_started_eip:
 
             # XXX this should be handled by the state machine.
@@ -1429,7 +1427,7 @@ class MainWindow(QtGui.QMainWindow):
                 download_if_needed=True)
             self._already_started_eip = True
         elif not self._already_started_eip:
-            if self._enabled_services.count(self.OPENVPN_SERVICE) > 0:
+            if self._enabled_services.count(EIP_SERVICE) > 0:
                 self._eip_status.set_eip_status(
                     self.tr("Not supported"),
                     error=True)
-- 
cgit v1.2.3


From 6c5a431034cb423a69c8f58a16fbb39a37dec73c Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Fri, 8 Nov 2013 17:23:06 -0300
Subject: Check if we have a systray to use.

This fixes a failure when we run the first run wizard and don't have a
systray ready.
---
 src/leap/bitmask/gui/eip_status.py  | 6 ++++--
 src/leap/bitmask/gui/mail_status.py | 5 +++--
 2 files changed, 7 insertions(+), 4 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/gui/eip_status.py b/src/leap/bitmask/gui/eip_status.py
index c41d9706..1899d6a4 100644
--- a/src/leap/bitmask/gui/eip_status.py
+++ b/src/leap/bitmask/gui/eip_status.py
@@ -197,8 +197,10 @@ class EIPStatusWidget(QtGui.QWidget):
         """
         Updates the system tray tooltip using the eip status.
         """
-        eip_status = u"{0}: {1}".format(self._service_name, self._eip_status)
-        self._systray.set_service_tooltip(EIP_SERVICE, eip_status)
+        if self._systray is not None:
+            eip_status = u"{0}: {1}".format(
+                self._service_name, self._eip_status)
+            self._systray.set_service_tooltip(EIP_SERVICE, eip_status)
 
     def set_action_eip_startstop(self, action_eip_startstop):
         """
diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py
index e89fb376..ec8d8f20 100644
--- a/src/leap/bitmask/gui/mail_status.py
+++ b/src/leap/bitmask/gui/mail_status.py
@@ -166,8 +166,9 @@ class MailStatusWidget(QtGui.QWidget):
         """
         Updates the system tray tooltip using the mx status.
         """
-        mx_status = u"{0}: {1}".format(self._service_name, self._mx_status)
-        self._systray.set_service_tooltip(MX_SERVICE, mx_status)
+        if self._systray is not None:
+            mx_status = u"{0}: {1}".format(self._service_name, self._mx_status)
+            self._systray.set_service_tooltip(MX_SERVICE, mx_status)
 
     def set_action_mail_status(self, action_mail_status):
         """
-- 
cgit v1.2.3


From 59868c95c23e825544b2c986bf7fe6c15538bbe5 Mon Sep 17 00:00:00 2001
From: drebs <drebs@leap.se>
Date: Thu, 7 Nov 2013 17:09:15 -0200
Subject: Fix call to smtp gateway.

---
 src/leap/bitmask/services/mail/conductor.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py
index 6dcf0c6f..a9621b13 100644
--- a/src/leap/bitmask/services/mail/conductor.py
+++ b/src/leap/bitmask/services/mail/conductor.py
@@ -197,8 +197,8 @@ class SMTPControl(object):
         # TODO remove hard-coded port and let leap.mail set
         # the specific default.
         self.smtp_connection.qtsigs.connecting_signal.emit()
-        from leap.mail.smtp import setup_smtp_relay
-        self._smtp_service, self._smtp_port = setup_smtp_relay(
+        from leap.mail.smtp import setup_smtp_gateway
+        self._smtp_service, self._smtp_port = setup_smtp_gateway(
             port=2013,
             userid=self.userid,
             keymanager=self._keymanager,
-- 
cgit v1.2.3


From e34674449f5423b07fed608f7c0d2a4e70e5ff4f Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Mon, 11 Nov 2013 11:54:49 -0300
Subject: Show a more generic message to the user.

---
 src/leap/bitmask/gui/mail_status.py | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py
index ec8d8f20..3c933c9a 100644
--- a/src/leap/bitmask/gui/mail_status.py
+++ b/src/leap/bitmask/gui/mail_status.py
@@ -294,8 +294,7 @@ class MailStatusWidget(QtGui.QWidget):
         #     ext_status = self.tr("Key not found!")
         elif req.event == proto.KEYMANAGER_STARTED_KEY_GENERATION:
             ext_status = self.tr(
-                "Generating new key, please wait... \n"
-                "(this may take up to 10 minutes depending on the machine)")
+                "Generating new key, this may take a few minutes.")
         elif req.event == proto.KEYMANAGER_FINISHED_KEY_GENERATION:
             ext_status = self.tr("Finished generating key!")
         elif req.event == proto.KEYMANAGER_DONE_UPLOADING_KEYS:
-- 
cgit v1.2.3


From 02a72c675107f9d324184265e414600c69763d7a Mon Sep 17 00:00:00 2001
From: drebs <drebs@leap.se>
Date: Mon, 11 Nov 2013 14:40:59 -0200
Subject: Send user's key to nickserver whenever the keymanager is initialized.

---
 src/leap/bitmask/services/soledad/soledadbootstrapper.py | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
index 54ef67eb..ce8bf813 100644
--- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py
+++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
@@ -367,6 +367,8 @@ class SoledadBootstrapper(AbstractBootstrapper):
             api_version=self._provider_config.get_api_version(),
             uid=srp_auth.get_uid(),
             gpgbinary=self._get_gpg_bin_path())
+        # make sure key is in server
+        self._keymanager.send_key(openpgp.OpenPGPKey)
 
     def _gen_key(self, _):
         """
@@ -393,7 +395,7 @@ class SoledadBootstrapper(AbstractBootstrapper):
         try:
             self._keymanager.gen_key(openpgp.OpenPGPKey)
         except Exception as exc:
-            logger.error("error while generating key!")
+            logger.error("Error while generating key!")
             logger.exception(exc)
             raise
 
@@ -401,7 +403,7 @@ class SoledadBootstrapper(AbstractBootstrapper):
         try:
             self._keymanager.send_key(openpgp.OpenPGPKey)
         except Exception as exc:
-            logger.error("error while sending key!")
+            logger.error("Error while sending key!")
             logger.exception(exc)
             raise
 
-- 
cgit v1.2.3


From 1fb82f0ad4a2a397e4b938748e58a64d057599e4 Mon Sep 17 00:00:00 2001
From: Kali Kaneko <kali@leap.se>
Date: Tue, 12 Nov 2013 13:39:26 -0200
Subject: deferToThread initial soledad sync

---
 src/leap/bitmask/services/soledad/soledadbootstrapper.py | 7 +++++++
 1 file changed, 7 insertions(+)

(limited to 'src')

diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
index 54ef67eb..c672c893 100644
--- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py
+++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
@@ -28,6 +28,8 @@ from PySide import QtCore
 from u1db import errors as u1db_errors
 from zope.proxy import sameProxiedObjects
 
+from twisted.internet.threads import deferToThread
+
 from leap.bitmask.config import flags
 from leap.bitmask.config.providerconfig import ProviderConfig
 from leap.bitmask.crypto.srpauth import SRPAuth
@@ -194,7 +196,12 @@ class SoledadBootstrapper(AbstractBootstrapper):
 
         leap_assert(not sameProxiedObjects(self._soledad, None),
                     "Null soledad, error while initializing")
+        self.deferred = deferToThread(self._do_soledad_sync)
 
+    def _do_soledad_sync(self):
+        """
+        Does several retries to get an initial soledad sync.
+        """
         # and now, let's sync
         sync_tries = self.MAX_SYNC_RETRIES
         while sync_tries > 0:
-- 
cgit v1.2.3


From 19df4a679664e76874e970813599c13c94dfd745 Mon Sep 17 00:00:00 2001
From: Kali Kaneko <kali@leap.se>
Date: Tue, 12 Nov 2013 23:28:17 -0200
Subject: re-raise the exceptions on init as expected

---
 src/leap/bitmask/services/mail/conductor.py              |  2 +-
 src/leap/bitmask/services/soledad/soledadbootstrapper.py | 13 +++++++------
 2 files changed, 8 insertions(+), 7 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py
index a9621b13..addf9bef 100644
--- a/src/leap/bitmask/services/mail/conductor.py
+++ b/src/leap/bitmask/services/mail/conductor.py
@@ -98,6 +98,7 @@ class IMAPControl(object):
             logger.debug('Stopping imap service.')
             # Stop the loop call in the fetcher
             self.imap_service.stop()
+            self.imap_service = None
             # Stop listening on the IMAP port
             self.imap_port.stopListening()
             # Stop the protocol
@@ -107,7 +108,6 @@ class IMAPControl(object):
         """
         Fetches incoming mail.
         """
-        # TODO have a mutex over fetch operation.
         if self.imap_service:
             logger.debug('Client connected, fetching mail...')
             self.imap_service.fetch()
diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
index c672c893..b046d279 100644
--- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py
+++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
@@ -207,10 +207,6 @@ class SoledadBootstrapper(AbstractBootstrapper):
         while sync_tries > 0:
             try:
                 self._try_soledad_sync()
-
-                # at this point, sometimes the client
-                # gets stuck and does not progress to
-                # the _gen_key step. XXX investigate.
                 logger.debug("Soledad has been synced.")
                 # so long, and thanks for all the fish
                 return
@@ -266,26 +262,32 @@ class SoledadBootstrapper(AbstractBootstrapper):
         except socket.timeout:
             logger.debug("SOLEDAD initialization TIMED OUT...")
             self.soledad_timeout.emit()
+            raise
         except socket.error as exc:
             logger.warning("Socket error while initializing soledad")
             self.soledad_timeout.emit()
+            raise
         except BootstrapSequenceError as exc:
             logger.warning("Error while initializing soledad")
             self.soledad_timeout.emit()
+            raise
 
         # unrecoverable
         except u1db_errors.Unauthorized:
             logger.error("Error while initializing soledad "
                          "(unauthorized).")
             self.soledad_failed.emit()
+            raise
         except u1db_errors.HTTPError as exc:
             logger.exception("Error whie initializing soledad "
                              "(HTTPError)")
             self.soledad_failed.emit()
+            raise
         except Exception as exc:
             logger.exception("Unhandled error while initializating "
                              "soledad: %r" % (exc,))
             self.soledad_failed.emit()
+            raise
 
     def _try_soledad_sync(self):
         """
@@ -299,9 +301,8 @@ class SoledadBootstrapper(AbstractBootstrapper):
             logger.error("%r" % (exc,))
             raise SoledadSyncError("Failed to sync soledad")
         except Exception as exc:
-            logger.exception("Unhandled error while syncing"
+            logger.exception("Unhandled error while syncing "
                              "soledad: %r" % (exc,))
-            self.soledad_failed.emit()
             raise SoledadSyncError("Failed to sync soledad")
 
     def _download_config(self):
-- 
cgit v1.2.3


From 223d17f74f59121875d2eb42c3a4e4d638ae2f08 Mon Sep 17 00:00:00 2001
From: Kali Kaneko <kali@leap.se>
Date: Wed, 13 Nov 2013 16:42:15 -0200
Subject: do not raise if error while syncing

---
 .../services/soledad/soledadbootstrapper.py        | 37 +++++++++++++++-------
 1 file changed, 25 insertions(+), 12 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
index 70318ab8..e8c7e9ce 100644
--- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py
+++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
@@ -364,19 +364,32 @@ class SoledadBootstrapper(AbstractBootstrapper):
         """
         srp_auth = self.srpauth
         logger.debug('initializing keymanager...')
-        self._keymanager = KeyManager(
-            address,
-            "https://nicknym.%s:6425" % (self._provider_config.get_domain(),),
-            self._soledad,
-            #token=srp_auth.get_token(),  # TODO: enable token usage
-            session_id=srp_auth.get_session_id(),
-            ca_cert_path=self._provider_config.get_ca_cert_path(),
-            api_uri=self._provider_config.get_api_uri(),
-            api_version=self._provider_config.get_api_version(),
-            uid=srp_auth.get_uid(),
-            gpgbinary=self._get_gpg_bin_path())
+        try:
+            self._keymanager = KeyManager(
+                address,
+                "https://nicknym.%s:6425" % (
+                    self._provider_config.get_domain(),),
+                self._soledad,
+                #token=srp_auth.get_token(),  # TODO: enable token usage
+                session_id=srp_auth.get_session_id(),
+                ca_cert_path=self._provider_config.get_ca_cert_path(),
+                api_uri=self._provider_config.get_api_uri(),
+                api_version=self._provider_config.get_api_version(),
+                uid=srp_auth.get_uid(),
+                gpgbinary=self._get_gpg_bin_path())
+        except Exception as exc:
+            logger.exception(exc)
+            raise
+
+        logger.debug('sending key to server...')
+
         # make sure key is in server
-        self._keymanager.send_key(openpgp.OpenPGPKey)
+        try:
+            self._keymanager.send_key(openpgp.OpenPGPKey)
+        except Exception as exc:
+            logger.error("Error sending key to server.")
+            logger.exception(exc)
+            # but we do not raise
 
     def _gen_key(self, _):
         """
-- 
cgit v1.2.3


From 5273f6694bffbba0a07c34f19a5a6630382e4d48 Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Thu, 14 Nov 2013 11:34:46 -0300
Subject: Add advanced key management dialog.

---
 src/leap/bitmask/gui/advanced_key_management.py    | 185 +++++++++++++++++++++
 src/leap/bitmask/gui/ui/advanced_key_management.ui | 153 +++++++++++++++++
 2 files changed, 338 insertions(+)
 create mode 100644 src/leap/bitmask/gui/advanced_key_management.py
 create mode 100644 src/leap/bitmask/gui/ui/advanced_key_management.ui

(limited to 'src')

diff --git a/src/leap/bitmask/gui/advanced_key_management.py b/src/leap/bitmask/gui/advanced_key_management.py
new file mode 100644
index 00000000..2c0fa034
--- /dev/null
+++ b/src/leap/bitmask/gui/advanced_key_management.py
@@ -0,0 +1,185 @@
+# -*- coding: utf-8 -*-
+# advanced_key_management.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 <http://www.gnu.org/licenses/>.
+"""
+Advanced Key Management
+"""
+import logging
+
+from PySide import QtGui
+from zope.proxy import sameProxiedObjects
+
+from leap.keymanager import openpgp
+from leap.keymanager.errors import KeyAddressMismatch, KeyFingerprintMismatch
+from leap.bitmask.services import get_service_display_name, MX_SERVICE
+from ui_advanced_key_management import Ui_AdvancedKeyManagement
+
+logger = logging.getLogger(__name__)
+
+
+class AdvancedKeyManagement(QtGui.QWidget):
+    """
+    Advanced Key Management
+    """
+    def __init__(self, user, keymanager, soledad):
+        """
+        :param user: the current logged in user.
+        :type user: unicode
+        :param keymanager: the existing keymanager instance
+        :type keymanager: KeyManager
+        :param soledad: a loaded instance of Soledad
+        :type soledad: Soledad
+        """
+        QtGui.QWidget.__init__(self)
+
+        self.ui = Ui_AdvancedKeyManagement()
+        self.ui.setupUi(self)
+
+        # if Soledad is not started yet
+        if sameProxiedObjects(soledad, None):
+            self.ui.container.setEnabled(False)
+            msg = self.tr("<span style='color:#0000FF;'>NOTE</span>: "
+                          "To use this, you need to enable/start {0}.")
+            msg = msg.format(get_service_display_name(MX_SERVICE))
+            self.ui.lblStatus.setText(msg)
+            return
+        else:
+            msg = self.tr(
+                "<span style='color:#ff0000;'>WARNING</span>:<br>"
+                "This is an experimental feature, you can lose access to "
+                "existing e-mails.")
+            self.ui.lblStatus.setText(msg)
+
+        self._keymanager = keymanager
+        self._soledad = soledad
+
+        self._key = keymanager.get_key(user, openpgp.OpenPGPKey)
+        self._key_priv = keymanager.get_key(
+            user, openpgp.OpenPGPKey, private=True)
+
+        # show current key information
+        self.ui.leUser.setText(user)
+        self.ui.leKeyID.setText(self._key.key_id)
+        self.ui.leFingerprint.setText(self._key.fingerprint)
+
+        # set up connections
+        self.ui.pbImportKeys.clicked.connect(self._import_keys)
+        self.ui.pbExportKeys.clicked.connect(self._export_keys)
+
+    def _import_keys(self):
+        """
+        Imports the user's key pair.
+        Those keys need to be ascii armored.
+        """
+        fileName, filtr = QtGui.QFileDialog.getOpenFileName(
+            self, self.tr("Open keys file"),
+            options=QtGui.QFileDialog.DontUseNativeDialog)
+
+        if fileName:
+            new_key = ''
+            try:
+                with open(fileName, 'r') as keys_file:
+                    new_key = keys_file.read()
+            except IOError as e:
+                logger.error("IOError importing key. {0!r}".format(e))
+                QtGui.QMessageBox.critical(
+                    self, self.tr("Input/Output error"),
+                    self.tr("There was an error accessing the file.\n"
+                            "Import canceled."))
+                return
+
+            keymanager = self._keymanager
+            try:
+                public_key, private_key = keymanager.parse_openpgp_ascii_key(
+                    new_key)
+            except (KeyAddressMismatch, KeyFingerprintMismatch) as e:
+                logger.error(repr(e))
+                QtGui.QMessageBox.warning(
+                    self, self.tr("Data mismatch"),
+                    self.tr("The public and private key should have the "
+                            "same address and fingerprint.\n"
+                            "Import canceled."))
+                return
+
+            if public_key is None or private_key is None:
+                QtGui.QMessageBox.warning(
+                    self, self.tr("Missing key"),
+                    self.tr("You need to provide the public AND private "
+                            "key in the same file.\n"
+                            "Import canceled."))
+                return
+
+            if public_key.address != self._key.address:
+                logger.error("The key does not match the ID")
+                QtGui.QMessageBox.warning(
+                    self, self.tr("Address mismatch"),
+                    self.tr("The identity for the key needs to be the same "
+                            "as your user address.\n"
+                            "Import canceled."))
+                return
+
+            question = self.tr("Are you sure that you want to replace "
+                               "the current key pair whith the imported?")
+            res = QtGui.QMessageBox.question(
+                None, "Change key pair", question,
+                QtGui.QMessageBox.Yes | QtGui.QMessageBox.No,
+                QtGui.QMessageBox.No)  # default No
+
+            if res == QtGui.QMessageBox.No:
+                return
+
+            keymanager.delete_key(self._key)
+            keymanager.delete_key(self._key_priv)
+            keymanager.put_key(public_key)
+            keymanager.put_key(private_key)
+            keymanager.send_key(openpgp.OpenPGPKey)
+
+            logger.debug('Import ok')
+
+            QtGui.QMessageBox.information(
+                self, self.tr("Import Successful"),
+                self.tr("The key pair was imported successfully."))
+        else:
+            logger.debug('Import canceled by the user.')
+
+    def _export_keys(self):
+        """
+        Exports the user's key pair.
+        """
+        fileName, filtr = QtGui.QFileDialog.getSaveFileName(
+            self, self.tr("Save keys file"),
+            options=QtGui.QFileDialog.DontUseNativeDialog)
+
+        if fileName:
+            try:
+                with open(fileName, 'w') as keys_file:
+                    keys_file.write(self._key.key_data)
+                    keys_file.write(self._key_priv.key_data)
+
+                logger.debug('Export ok')
+                QtGui.QMessageBox.information(
+                    self, self.tr("Export Successful"),
+                    self.tr("The key pair was exported successfully.\n"
+                            "Please, store your private key in a safe place."))
+            except IOError as e:
+                logger.error("IOError exporting key. {0!r}".format(e))
+                QtGui.QMessageBox.critical(
+                    self, self.tr("Input/Output error"),
+                    self.tr("There was an error accessing the file.\n"
+                            "Export canceled."))
+                return
+        else:
+            logger.debug('Export canceled by the user.')
diff --git a/src/leap/bitmask/gui/ui/advanced_key_management.ui b/src/leap/bitmask/gui/ui/advanced_key_management.ui
new file mode 100644
index 00000000..d61aa87e
--- /dev/null
+++ b/src/leap/bitmask/gui/ui/advanced_key_management.ui
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AdvancedKeyManagement</class>
+ <widget class="QWidget" name="AdvancedKeyManagement">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>431</width>
+    <height>188</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Advanced Key Management</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="../../../../../data/resources/mainwindow.qrc">
+    <normaloff>:/images/mask-icon.png</normaloff>:/images/mask-icon.png</iconset>
+  </property>
+  <layout class="QGridLayout" name="gridLayout_3">
+   <item row="0" column="0">
+    <widget class="QWidget" name="container" native="true">
+     <layout class="QGridLayout" name="gridLayout_2">
+      <item row="0" column="0">
+       <widget class="QLabel" name="label">
+        <property name="text">
+         <string>User:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QLineEdit" name="leUser">
+        <property name="enabled">
+         <bool>true</bool>
+        </property>
+        <property name="text">
+         <string>user_name@provider</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignCenter</set>
+        </property>
+        <property name="readOnly">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <widget class="QLabel" name="label_3">
+        <property name="text">
+         <string>Key ID:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QLineEdit" name="leKeyID">
+        <property name="enabled">
+         <bool>true</bool>
+        </property>
+        <property name="text">
+         <string>key ID</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignCenter</set>
+        </property>
+        <property name="readOnly">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="0">
+       <widget class="QLabel" name="label_5">
+        <property name="text">
+         <string>Key fingerprint:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1">
+       <widget class="QLineEdit" name="leFingerprint">
+        <property name="enabled">
+         <bool>true</bool>
+        </property>
+        <property name="text">
+         <string>fingerprint</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignCenter</set>
+        </property>
+        <property name="readOnly">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="1">
+       <spacer name="verticalSpacer">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>40</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="4" column="0" colspan="2">
+       <layout class="QGridLayout" name="gridLayout">
+        <item row="1" column="1">
+         <widget class="QPushButton" name="pbExportKeys">
+          <property name="text">
+           <string>Export current key pair</string>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="0" rowspan="2">
+         <spacer name="horizontalSpacer">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+        <item row="2" column="1">
+         <widget class="QPushButton" name="pbImportKeys">
+          <property name="text">
+           <string>Import custom key pair</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="lblStatus">
+     <property name="text">
+      <string/>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources>
+  <include location="../../../../../data/resources/mainwindow.qrc"/>
+ </resources>
+ <connections/>
+</ui>
-- 
cgit v1.2.3


From 46a9bcbc1242aacad1947087c2d30c7952872d7b Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Thu, 14 Nov 2013 14:28:52 -0300
Subject: Set token to none in logout.

---
 src/leap/bitmask/crypto/srpauth.py | 1 +
 1 file changed, 1 insertion(+)

(limited to 'src')

diff --git a/src/leap/bitmask/crypto/srpauth.py b/src/leap/bitmask/crypto/srpauth.py
index ab98850d..85b9b003 100644
--- a/src/leap/bitmask/crypto/srpauth.py
+++ b/src/leap/bitmask/crypto/srpauth.py
@@ -581,6 +581,7 @@ class SRPAuth(QtCore.QObject):
             else:
                 self.set_session_id(None)
                 self.set_uid(None)
+                self.set_token(None)
                 # Also reset the session
                 self._session = self._fetcher.session()
                 logger.debug("Successfully logged out.")
-- 
cgit v1.2.3


From b0b820d4dc579e3bf5bbfbe68c7911d573aea205 Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Thu, 14 Nov 2013 14:30:57 -0300
Subject: Use services' module names for the service.

---
 src/leap/bitmask/gui/preferenceswindow.py | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py
index acb39b07..3843ccde 100644
--- a/src/leap/bitmask/gui/preferenceswindow.py
+++ b/src/leap/bitmask/gui/preferenceswindow.py
@@ -22,7 +22,9 @@ import os
 import logging
 
 from functools import partial
+
 from PySide import QtCore, QtGui
+from zope.proxy import sameProxiedObjects
 
 from leap.bitmask.config.leapsettings import LeapSettings
 from leap.bitmask.gui.ui_preferences import Ui_Preferences
@@ -31,7 +33,7 @@ from leap.bitmask.crypto.srpauth import SRPAuthBadUserOrPassword
 from leap.bitmask.util.password import basic_password_checks
 from leap.bitmask.services import get_supported
 from leap.bitmask.config.providerconfig import ProviderConfig
-from leap.bitmask.services import get_service_display_name
+from leap.bitmask.services import get_service_display_name, MX_SERVICE
 
 logger = logging.getLogger(__name__)
 
@@ -81,12 +83,13 @@ class PreferencesWindow(QtGui.QDialog):
             # check if provider has 'mx' ...
             domain = provider_config.get_domain()
             self._select_provider_by_name(domain)
+
             if provider_config.provides_mx():
                 enabled_services = self._settings.get_enabled_services(domain)
-                mx_name = get_service_display_name('mx')
+                mx_name = get_service_display_name(MX_SERVICE)
 
                 # ... and if the user have it enabled
-                if 'mx' not in enabled_services:
+                if MX_SERVICE not in enabled_services:
                     msg = self.tr("You need to enable {0} in order to change "
                                   "the password.".format(mx_name))
                     self._set_password_change_status(msg, error=True)
-- 
cgit v1.2.3


From 20d89634f7b891fb4f399da51b3800d42159b9eb Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Thu, 14 Nov 2013 14:34:46 -0300
Subject: Enable password change in proper conditions.

- Send soledad to the constructor and check with sameProxiedObjects
- Check if soledad instance is defined, otherwise wait until
  soledad_ready

[Closes #4449]
---
 src/leap/bitmask/gui/mainwindow.py        |  7 +++----
 src/leap/bitmask/gui/preferenceswindow.py | 26 ++++++++++++++------------
 2 files changed, 17 insertions(+), 16 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index f3043809..c24735d8 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -446,11 +446,10 @@ class MainWindow(QtGui.QMainWindow):
         Displays the preferences window.
         """
         preferences_window = PreferencesWindow(self, self._srp_auth,
-                                               self._provider_config)
-
-        self.soledad_ready.connect(
-            lambda: preferences_window.set_soledad_ready(self._soledad))
+                                               self._provider_config,
+                                               self._soledad)
 
+        self.soledad_ready.connect(preferences_window.set_soledad_ready)
         preferences_window.show()
 
     def _show_eip_preferences(self):
diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py
index 3843ccde..8e9ef95a 100644
--- a/src/leap/bitmask/gui/preferenceswindow.py
+++ b/src/leap/bitmask/gui/preferenceswindow.py
@@ -42,7 +42,7 @@ class PreferencesWindow(QtGui.QDialog):
     """
     Window that displays the preferences.
     """
-    def __init__(self, parent, srp_auth, provider_config):
+    def __init__(self, parent, srp_auth, provider_config, soledad):
         """
         :param parent: parent object of the PreferencesWindow.
         :parent type: QWidget
@@ -50,13 +50,15 @@ class PreferencesWindow(QtGui.QDialog):
         :type srp_auth: SRPAuth
         :param provider_config: ProviderConfig object.
         :type provider_config: ProviderConfig
+        :param soledad: Soledad instance
+        :type soledad: Soledad
         """
         QtGui.QDialog.__init__(self, parent)
         self.AUTOMATIC_GATEWAY_LABEL = self.tr("Automatic")
 
         self._srp_auth = srp_auth
         self._settings = LeapSettings()
-        self._soledad = None
+        self._soledad = soledad
 
         # Load UI
         self.ui = Ui_Preferences()
@@ -94,10 +96,14 @@ class PreferencesWindow(QtGui.QDialog):
                                   "the password.".format(mx_name))
                     self._set_password_change_status(msg, error=True)
                 else:
-                    msg = self.tr(
-                        "You need to wait until {0} is ready in "
-                        "order to change the password.".format(mx_name))
-                    self._set_password_change_status(msg)
+                    if sameProxiedObjects(self._soledad, None):
+                        msg = self.tr(
+                            "You need to wait until {0} is ready in "
+                            "order to change the password.".format(mx_name))
+                        self._set_password_change_status(msg)
+                    else:
+                        # Soledad is bootstrapped
+                        pw_enabled = True
             else:
                 pw_enabled = True
         else:
@@ -107,18 +113,14 @@ class PreferencesWindow(QtGui.QDialog):
 
         self.ui.gbPasswordChange.setEnabled(pw_enabled)
 
-    def set_soledad_ready(self, soledad):
+    def set_soledad_ready(self):
         """
         SLOT
         TRIGGERS:
             parent.soledad_ready
 
-        It sets the soledad object as ready to use.
-
-        :param soledad: Soledad object configured in the main app.
-        :type soledad: Soledad
+        It notifies when the soledad object as ready to use.
         """
-        self._soledad = soledad
         self.ui.lblPasswordChangeStatus.setVisible(False)
         self.ui.gbPasswordChange.setEnabled(True)
 
-- 
cgit v1.2.3


From ed08a7619bd79a594d579b4bfbc7d4bdce3ccd7a Mon Sep 17 00:00:00 2001
From: Ivan Alejandro <ivanalejandro0@gmail.com>
Date: Thu, 14 Nov 2013 11:39:41 -0300
Subject: Add the advanced key management to the main window

---
 src/leap/bitmask/gui/mainwindow.py    | 19 +++++++++++++++++++
 src/leap/bitmask/gui/ui/mainwindow.ui | 13 +++++++++++--
 2 files changed, 30 insertions(+), 2 deletions(-)

(limited to 'src')

diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index f3043809..39a08cfb 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -29,6 +29,7 @@ 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.advanced_key_management import AdvancedKeyManagement
 from leap.bitmask.gui.login import LoginWidget
 from leap.bitmask.gui.preferenceswindow import PreferencesWindow
 from leap.bitmask.gui.eip_preferenceswindow import EIPPreferencesWindow
@@ -252,6 +253,9 @@ class MainWindow(QtGui.QMainWindow):
         self.ui.action_create_new_account.triggered.connect(
             self._launch_wizard)
 
+        self.ui.action_advanced_key_management.triggered.connect(
+            self._show_AKM)
+
         if IS_MAC:
             self.ui.menuFile.menuAction().setText(self.tr("File"))
 
@@ -437,6 +441,20 @@ class MainWindow(QtGui.QMainWindow):
         else:
             self._logger_window.setVisible(not self._logger_window.isVisible())
 
+    def _show_AKM(self):
+        """
+        SLOT
+        TRIGGERS:
+            self.ui.action_advanced_key_management.triggered
+
+        Displays the Advanced Key Management dialog.
+        """
+        domain = self._login_widget.get_selected_provider()
+        logged_user = "{0}@{1}".format(self._logged_user, domain)
+        self._akm = AdvancedKeyManagement(
+            logged_user, self._keymanager, self._soledad)
+        self._akm.show()
+
     def _show_preferences(self):
         """
         SLOT
@@ -1522,6 +1540,7 @@ class MainWindow(QtGui.QMainWindow):
         """
 
         self._soledad_bootstrapper.cancel_bootstrap()
+        setProxiedObject(self._soledad, None)
 
         # XXX: If other defers are doing authenticated stuff, this
         # might conflict with those. CHECK!
diff --git a/src/leap/bitmask/gui/ui/mainwindow.ui b/src/leap/bitmask/gui/ui/mainwindow.ui
index badd291d..3b83788e 100644
--- a/src/leap/bitmask/gui/ui/mainwindow.ui
+++ b/src/leap/bitmask/gui/ui/mainwindow.ui
@@ -75,7 +75,7 @@
          <x>0</x>
          <y>0</y>
          <width>524</width>
-         <height>636</height>
+         <height>651</height>
         </rect>
        </property>
        <layout class="QVBoxLayout" name="verticalLayout">
@@ -380,7 +380,7 @@ background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgb
      <x>0</x>
      <y>0</y>
      <width>524</width>
-     <height>22</height>
+     <height>21</height>
     </rect>
    </property>
    <widget class="QMenu" name="menuFile">
@@ -388,6 +388,7 @@ background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgb
      <string>&amp;Bitmask</string>
     </property>
     <addaction name="action_create_new_account"/>
+    <addaction name="action_advanced_key_management"/>
     <addaction name="separator"/>
     <addaction name="action_quit"/>
    </widget>
@@ -439,6 +440,14 @@ background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgb
     <string>Create a new account...</string>
    </property>
   </action>
+  <action name="action_advanced_key_management">
+   <property name="enabled">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Advanced Key Management</string>
+   </property>
+  </action>
  </widget>
  <resources>
   <include location="../../../../../data/resources/mainwindow.qrc"/>
-- 
cgit v1.2.3