diff options
author | Kali Kaneko <kali@leap.se> | 2013-08-26 14:19:11 +0200 |
---|---|---|
committer | Kali Kaneko <kali@leap.se> | 2013-08-26 14:19:11 +0200 |
commit | dbfaa0c69a3282ce221b4d30de2027ce9ee27a05 (patch) | |
tree | 46433f1326e85206db70edad78e3b6aa9122c04f | |
parent | 655a9a610cfe69530b8f6fde41e9255435374253 (diff) | |
parent | 6259826db4418be0bf05fee4785997575abe8177 (diff) |
Merge branch 'master' into debian-0.3.1
29 files changed, 562 insertions, 67 deletions
@@ -1,3 +1,40 @@ +0.3.1 Aug 23: + o Replace wizard images with the rainbow mask. Closes #3425. + o Update leap.common minimum version needed. + o Set the standalone flag before it's being used. Fixes #3426. + o Stop the twisted reactor adding the stop call to the call chain + instead of stopping it directly. Fixes #3406. + o Allow soledad initialization to retry if it times out. Closes: + #3413 + o Activate window when setting it visible. Also display Hide/Show + message in the tray icon taking into account the window + activation. Fixes #3433. + o Do not start IMAP daemon if mail was not selected among the + services. Fixes #3435. + o Reword RECONNECTING state of openvpn. Fixes #3429. + o Improve OpenVPN detection by searching for a specific leap-only + string in the command line. This makes it possible to run other + VPN instances while also using EIP. Fixes #3268 and #3364. + o OSX: Check for the tun.kext existence in /Library/Extensions + instead of /System/Library/Extensions. Fixes #3271. + o Use DELETE /1/logout to properly logout. Fixes #3510. + o Make the poll interval bigger to improve openvpn's internal + behavior. If it gets queried too many times per second, it's + behavior won't be good. Fixes #3430. + o Transforms usernames to lower case before they are used in the + registration and authentication. Closes #3541. + o Add filter option to the logger window. Closes #3407. + o Add a preference panel that lets you change your password. Closes + #3500 #2798 #3533. + o Move all client code into its own namespace + (leap.bitmask). Closes: #2959 + o Make mail fetch interval in imap service configurable via + environment variable. Closes: #3409 + o Update to new soledad package scheme (common, client and + server). Closes #3487. + o Fetch incoming mail when mail client logs in. Closes: #3525 + o Add first draft of the UI for Encrypted Mail. Closes #3499. + 0.3.0 Aug 9: o Add missing scripts does not stop if a command fails, also warns the user if there was an error. Closes #3294. diff --git a/MANIFEST.in b/MANIFEST.in index a4d18e0b..6334ce45 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,5 +4,5 @@ recursive-include docs api/* config/* dev/* man/* pkg/* testers/* user/* prune docs/_build prune docs/covhtml include versioneer.py -include src/leap/util/reqs.txt -include src/leap/crypto/tests/wrongcert.pem +include src/leap/bitmask/util/reqs.txt +include src/leap/bitmask/crypto/tests/wrongcert.pem @@ -19,7 +19,7 @@ TRANSLAT_DIR = data/translations PROJFILE = data/bitmask.pro #UI files to compile -UI_FILES = loggerwindow.ui mainwindow.ui wizard.ui login.ui statuspanel.ui +UI_FILES = loggerwindow.ui mainwindow.ui wizard.ui login.ui statuspanel.ui preferences.ui #Qt resource files to compile RESOURCES = locale.qrc loggerwindow.qrc mainwindow.qrc icons.qrc diff --git a/changes/bug-3425_replace-wizard-images b/changes/bug-3425_replace-wizard-images deleted file mode 100644 index cf5cbd9d..00000000 --- a/changes/bug-3425_replace-wizard-images +++ /dev/null @@ -1 +0,0 @@ - o Replace wizard images with the rainbow mask. Closes #3425. diff --git a/changes/bug-update-requirements b/changes/bug-update-requirements deleted file mode 100644 index e86e6e84..00000000 --- a/changes/bug-update-requirements +++ /dev/null @@ -1 +0,0 @@ - o Update leap.common minimum version needed. diff --git a/changes/bug3426_set_standalone b/changes/bug3426_set_standalone deleted file mode 100644 index 408b893f..00000000 --- a/changes/bug3426_set_standalone +++ /dev/null @@ -1 +0,0 @@ - o Set the standalone flag before it's being used. Fixes #3426.
\ No newline at end of file diff --git a/changes/bug_3406_quit_hangs b/changes/bug_3406_quit_hangs deleted file mode 100644 index 77452780..00000000 --- a/changes/bug_3406_quit_hangs +++ /dev/null @@ -1,2 +0,0 @@ - o Stop the twisted reactor adding the stop call to the call chain - instead of stopping it directly. Fixes #3406.
\ No newline at end of file diff --git a/changes/bug_3413-soledad-init-retries b/changes/bug_3413-soledad-init-retries deleted file mode 100644 index 160121dd..00000000 --- a/changes/bug_3413-soledad-init-retries +++ /dev/null @@ -1 +0,0 @@ - o Allow soledad initialization to retry if it times out. Closes: #3413 diff --git a/changes/bug_better_hideshow_handling b/changes/bug_better_hideshow_handling deleted file mode 100644 index 3538087b..00000000 --- a/changes/bug_better_hideshow_handling +++ /dev/null @@ -1,3 +0,0 @@ - o Activate window when setting it visible. Also display Hide/Show - message in the tray icon taking into account the window - activation. Fixes #3433.
\ No newline at end of file diff --git a/changes/bug_disablemail_completely b/changes/bug_disablemail_completely deleted file mode 100644 index 126da2a7..00000000 --- a/changes/bug_disablemail_completely +++ /dev/null @@ -1,2 +0,0 @@ - o Do not start IMAP daemon if mail was not selected among the - services. Fixes #3435.
\ No newline at end of file diff --git a/changes/bug_handle_reconnecting b/changes/bug_handle_reconnecting deleted file mode 100644 index c6465949..00000000 --- a/changes/bug_handle_reconnecting +++ /dev/null @@ -1 +0,0 @@ - o Reword RECONNECTING state of openvpn. Fixes #3429.
\ No newline at end of file diff --git a/changes/bug_improve_openvpn_detection b/changes/bug_improve_openvpn_detection deleted file mode 100644 index 99f43a07..00000000 --- a/changes/bug_improve_openvpn_detection +++ /dev/null @@ -1,3 +0,0 @@ - o Improve OpenVPN detection by searching for a specific leap-only - string in the command line. This makes it possible to run other - VPN instances while also using EIP. Fixes #3268 and #3364.
\ No newline at end of file diff --git a/changes/bug_load_kext b/changes/bug_load_kext deleted file mode 100644 index ba4a44cf..00000000 --- a/changes/bug_load_kext +++ /dev/null @@ -1,2 +0,0 @@ - o OSX: Check for the tun.kext existence in /Library/Extensions - instead of /System/Library/Extensions. Fixes #3271.
\ No newline at end of file diff --git a/changes/bug_properly_logout b/changes/bug_properly_logout deleted file mode 100644 index a5d0d972..00000000 --- a/changes/bug_properly_logout +++ /dev/null @@ -1 +0,0 @@ - o Use DELETE /1/logout to properly logout. Fixes #3510.
\ No newline at end of file diff --git a/changes/bug_retr_hangs b/changes/bug_retr_hangs deleted file mode 100644 index 8bdf7bac..00000000 --- a/changes/bug_retr_hangs +++ /dev/null @@ -1,3 +0,0 @@ - o Make the poll interval bigger to improve openvpn's internal - behavior. If it gets queried too many times per second, it's - behavior won't be good. Fixes #3430.
\ No newline at end of file diff --git a/changes/bug_username_to_lower b/changes/bug_username_to_lower deleted file mode 100644 index 284567e4..00000000 --- a/changes/bug_username_to_lower +++ /dev/null @@ -1,2 +0,0 @@ - o Transforms usernames to lower case before they are used in the - registration and authentication. Closes #3541.
\ No newline at end of file diff --git a/changes/feature-3407_add-log-filtering b/changes/feature-3407_add-log-filtering deleted file mode 100644 index f4433af4..00000000 --- a/changes/feature-3407_add-log-filtering +++ /dev/null @@ -1 +0,0 @@ - o Add filter option to the logger window. Closes #3407. diff --git a/changes/feature_2959_create_bitmask_namespace b/changes/feature_2959_create_bitmask_namespace deleted file mode 100644 index 9f7e9cd4..00000000 --- a/changes/feature_2959_create_bitmask_namespace +++ /dev/null @@ -1 +0,0 @@ - o Move all client code into its own namespace (leap.bitmask). Closes: #2959 diff --git a/changes/feature_3409-make-imap-poll-configurable b/changes/feature_3409-make-imap-poll-configurable deleted file mode 100644 index 8730b5ab..00000000 --- a/changes/feature_3409-make-imap-poll-configurable +++ /dev/null @@ -1,2 +0,0 @@ - o Make mail fetch interval in imap service configurable via environment - variable. Closes: #3409 diff --git a/changes/feature_3487-split-soledad-into-common-client-and-server b/changes/feature_3487-split-soledad-into-common-client-and-server deleted file mode 100644 index 46983232..00000000 --- a/changes/feature_3487-split-soledad-into-common-client-and-server +++ /dev/null @@ -1,2 +0,0 @@ - o Update to new soledad package scheme (common, client and server). Closes - #3487. diff --git a/changes/feature_3525-login-triggers-fetch b/changes/feature_3525-login-triggers-fetch deleted file mode 100644 index 02fd0978..00000000 --- a/changes/feature_3525-login-triggers-fetch +++ /dev/null @@ -1 +0,0 @@ - o Fetch incoming mail when mail client logs in. Closes: #3525 diff --git a/changes/feature_add_mail_ui b/changes/feature_add_mail_ui deleted file mode 100644 index c7c0f2ce..00000000 --- a/changes/feature_add_mail_ui +++ /dev/null @@ -1 +0,0 @@ - o Add first draft of the UI for Encrypted Mail. Closes #3499.
\ No newline at end of file @@ -52,14 +52,14 @@ trove_classifiers = [ parsed_reqs = utils.parse_requirements() cmdclass = versioneer.get_cmdclass() -leap_launcher = 'bitmask=leap.app:main' +leap_launcher = 'bitmask=leap.bitmask.app:main' from setuptools.command.develop import develop as _develop def copy_reqs(path, withsrc=False): # add a copy of the processed requirements to the package - _reqpath = ('leap', 'util', 'reqs.txt') + _reqpath = ('leap', 'bitmask', 'util', 'reqs.txt') if withsrc: reqsfile = os.path.join(path, 'src', *_reqpath) else: diff --git a/src/leap/bitmask/crypto/srpauth.py b/src/leap/bitmask/crypto/srpauth.py index 7b91205f..41ce130a 100644 --- a/src/leap/bitmask/crypto/srpauth.py +++ b/src/leap/bitmask/crypto/srpauth.py @@ -134,6 +134,8 @@ class SRPAuth(QtCore.QObject): A_KEY = "A" CLIENT_AUTH_KEY = "client_auth" SESSION_ID_KEY = "_session_id" + USER_VERIFIER_KEY = 'user[password_verifier]' + USER_SALT_KEY = 'user[password_salt]' def __init__(self, provider_config): """ @@ -169,6 +171,10 @@ class SRPAuth(QtCore.QObject): self._srp_user = None self._srp_a = None + # User credentials stored for password changing checks + self._username = None + self._password = None + def _safe_unhexlify(self, val): """ Rounds the val to a multiple of 2 and returns the @@ -438,6 +444,51 @@ class SRPAuth(QtCore.QObject): def _threader(self, cb, res, *args, **kwargs): return threads.deferToThread(cb, res, *args, **kwargs) + def change_password(self, current_password, new_password): + """ + Changes the password for the currently logged user if the current + password match. + It requires to be authenticated. + + Might raise: + SRPAuthBadPassword + requests.exceptions.HTTPError + + :param current_password: the current password for the logged user. + :type current_password: str + :param new_password: the new password for the user + :type new_password: str + """ + leap_assert(self.get_uid() is not None) + + if current_password != self._password: + raise SRPAuthBadPassword + + url = "%s/%s/users/%s.json" % ( + self._provider_config.get_api_uri(), + self._provider_config.get_api_version(), + self.get_uid()) + + salt, verifier = self._srp.create_salted_verification_key( + self._username, new_password, self._hashfun, self._ng) + + cookies = {self.SESSION_ID_KEY: self.get_session_id()} + user_data = { + self.USER_VERIFIER_KEY: binascii.hexlify(verifier), + self.USER_SALT_KEY: binascii.hexlify(salt) + } + + change_password = self._session.put( + url, data=user_data, + verify=self._provider_config.get_ca_cert_path(), + cookies=cookies, + timeout=REQUEST_TIMEOUT) + + # In case of non 2xx it raises HTTPError + change_password.raise_for_status() + + self._password = new_password + def authenticate(self, username, password): """ Executes the whole authentication process for a user @@ -454,6 +505,10 @@ 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._password = password + d = threads.deferToThread(self._authentication_preprocessing, username=username, password=password) @@ -565,6 +620,33 @@ class SRPAuth(QtCore.QObject): d.addErrback(self._errback) return d + def change_password(self, current_password, new_password): + """ + Changes the user's password. + + :param current_password: the current password of the user. + :type current_password: str + :param new_password: the new password for the user. + :type new_password: str + + :returns: a defer to interact with. + :rtype: twisted.internet.defer.Deferred + """ + d = threads.deferToThread( + self.__instance.change_password, current_password, new_password) + return d + + def get_username(self): + """ + Returns the username of the currently authenticated user or None if + no user is logged. + + :rtype: str or None + """ + if self.get_uid() is None: + return None + return self.__instance._username + def _gui_notify(self, _): """ Callback that notifies the UI with the proper signal. diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 17275983..c832887a 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -33,6 +33,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.preferenceswindow import PreferencesWindow from leap.bitmask.gui.wizard import Wizard from leap.bitmask.gui.login import LoginWidget from leap.bitmask.gui.statuspanel import StatusPanelWidget @@ -162,6 +163,7 @@ class MainWindow(QtGui.QMainWindow): self._launch_wizard) self.ui.btnShowLog.clicked.connect(self._show_logger_window) + self.ui.btnPreferences.clicked.connect(self._show_preferences) self._status_panel = StatusPanelWidget( self.ui.stackedWidget.widget(self.EIP_STATUS_INDEX)) @@ -286,12 +288,17 @@ class MainWindow(QtGui.QMainWindow): ################################# end Qt Signals connection ######## + # Enable the password change when soledad is ready + self.soledad_ready.connect( + partial(self.ui.btnPreferences.setEnabled, True)) + init_platform() self._wizard = None self._wizard_firstrun = False self._logger_window = None + self._preferences_window = None self._bypass_checks = bypass_checks @@ -403,6 +410,17 @@ class MainWindow(QtGui.QMainWindow): self._logger_window.finished.connect(self._uncheck_logger_button) + def _show_preferences(self): + """ + SLOT + TRIGGERS: + self.ui.action_show_preferences.triggered + self.ui.btnPreferences.clicked + + Displays the preferences window. + """ + PreferencesWindow(self, self._srp_auth, self._soledad).show() + def _uncheck_logger_button(self): """ SLOT @@ -1399,6 +1417,7 @@ class MainWindow(QtGui.QMainWindow): self._login_widget.set_password("") self._login_widget.set_enabled(True) self._login_widget.set_status("") + self.ui.btnPreferences.setEnabled(False) def _intermediate_stage(self, data): """ diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py new file mode 100644 index 00000000..67448768 --- /dev/null +++ b/src/leap/bitmask/gui/preferenceswindow.py @@ -0,0 +1,196 @@ +# -*- coding: utf-8 -*- +# preferenceswindow.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/>. + +""" +Preferences window +""" +import logging + +from functools import partial +from PySide import QtGui + +from leap.bitmask.gui.ui_preferences import Ui_Preferences +from leap.soledad.client import NoStorageSecret +from leap.bitmask.crypto.srpauth import SRPAuthBadPassword + +logger = logging.getLogger(__name__) + + +class PreferencesWindow(QtGui.QDialog): + """ + Window that displays the preferences. + """ + + WEAK_PASSWORDS = ("123456", "qweasd", "qwerty", "password") + + def __init__(self, parent, srp_auth, soledad): + """ + :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 soledad: Soledad object configured in the main app. + :type soledad: Soledad + """ + QtGui.QDialog.__init__(self, parent) + + self._srp_auth = srp_auth + self._soledad = soledad + + # Load UI + self.ui = Ui_Preferences() + self.ui.setupUi(self) + self.ui.lblPasswordChangeStatus.setVisible(False) + + # Connections + self.ui.pbChangePassword.clicked.connect(self._change_password) + + def _basic_password_checks(self, username, password, password2): + """ + Performs basic password checks to avoid really easy passwords. + + :param username: username provided at the registrarion form + :type username: str + :param password: password from the registration form + :type password: str + :param password2: second password from the registration form + :type password: str + + :returns: True and empty message if all the checks pass, + False and an error message otherwise + :rtype: tuple(bool, str) + """ + message = None + + if message is None and password != password2: + message = self.tr("Passwords don't match") + + if message is None and len(password) < 6: + message = self.tr("Password too short") + + if message is None and password in self.WEAK_PASSWORDS: + message = self.tr("Password too easy") + + if message is None and username == password: + message = self.tr("Password equal to username") + + return message is None, message + + def _set_password_change_status(self, status, error=False, success=False): + """ + Sets the status label for the password change. + + :param status: status message to display, can be HTML + :type status: str + """ + if error: + status = "<font color='red'><b>%s</b></font>" % (status,) + elif success: + status = "<font color='green'><b>%s</b></font>" % (status,) + + self.ui.lblPasswordChangeStatus.setVisible(True) + self.ui.lblPasswordChangeStatus.setText(status) + + def _set_changing_password(self, disable): + """ + Enables or disables the widgets in the password change group box. + + :param disable: True if the widgets should be disabled and + it displays the status label that shows that is + changing the password. + False if they should be enabled. + :type disable: bool + """ + if disable: + self._set_password_change_disable(self.tr("Changing password...")) + + self.ui.leCurrentPassword.setEnabled(not disable) + self.ui.leNewPassword.setEnabled(not disable) + self.ui.leNewPassword2.setEnabled(not disable) + self.ui.pbChangePassword.setEnabled(not disable) + + def _change_password(self): + """ + Changes the user's password if the inputboxes are correctly filled. + """ + username = self._srp_auth.get_username() + current_password = self.ui.leCurrentPassword.text() + new_password = self.ui.leNewPassword.text() + new_password2 = self.ui.leNewPassword2.text() + + ok, msg = self._basic_password_checks( + username, new_password, new_password2) + + if not ok: + self._set_changing_password(False) + self._set_password_change_status(msg, error=True) + self.ui.leNewPassword.setFocus() + return + + self._set_changing_password(True) + d = self._srp_auth.change_password(current_password, new_password) + d.addCallback(partial(self._change_password_success, new_password)) + d.addErrback(self._change_password_problem) + + def _change_password_success(self, new_password, _): + """ + Callback used to display a successfully performed action. + + :param new_password: the new password for the user. + :type new_password: str. + :param _: the returned data from self._srp_auth.change_password + Ignored + """ + logger.debug("SRP password changed successfully.") + try: + self._soledad.change_passphrase(str(new_password)) + logger.debug("Soledad password changed successfully.") + except NoStorageSecret: + logger.debug( + "No storage secret for password change in Soledad.") + + self._set_password_change_status( + self.tr("Password changed successfully."), success=True) + self._clear_inputs() + self._set_changing_password(False) + + def _change_password_problem(self, failure): + """ + Errback called if there was a problem with the deferred. + Also is used to display an error message. + + :param failure: the cause of the method failed. + :type failure: twisted.python.Failure + """ + logger.error("Error changing password: %s", (failure, )) + problem = self.tr("There was a problem changing the password.") + + if failure.check(SRPAuthBadPassword): + problem = self.tr("You did not enter a correct current password.") + + self._set_password_change_status(problem, error=True) + + self._set_changing_password(False) + failure.trap(Exception) + + def _clear_inputs(self): + """ + Clear the contents of the inputs. + """ + self.ui.leCurrentPassword.setText("") + self.ui.leNewPassword.setText("") + self.ui.leNewPassword2.setText("") diff --git a/src/leap/bitmask/gui/ui/mainwindow.ui b/src/leap/bitmask/gui/ui/mainwindow.ui index 9c4e6ff0..834a562e 100644 --- a/src/leap/bitmask/gui/ui/mainwindow.ui +++ b/src/leap/bitmask/gui/ui/mainwindow.ui @@ -215,6 +215,16 @@ <item row="18" column="2"> <layout class="QHBoxLayout" name="horizontalLayout"> <item> + <widget class="QPushButton" name="btnPreferences"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Preferences</string> + </property> + </widget> + </item> + <item> <spacer name="horizontalSpacer_10"> <property name="orientation"> <enum>Qt::Horizontal</enum> @@ -310,7 +320,6 @@ <resources> <include location="../../../../../data/resources/mainwindow.qrc"/> <include location="../../../../../data/resources/locale.qrc"/> - <include location="../../../../data/resources/mainwindow.qrc"/> </resources> <connections/> </ui> diff --git a/src/leap/bitmask/gui/ui/preferences.ui b/src/leap/bitmask/gui/ui/preferences.ui new file mode 100644 index 00000000..8c63ccad --- /dev/null +++ b/src/leap/bitmask/gui/ui/preferences.ui @@ -0,0 +1,170 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Preferences</class> + <widget class="QDialog" name="Preferences"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>451</width> + <height>267</height> + </rect> + </property> + <property name="windowTitle"> + <string>Preferences</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="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="gbPasswordChange"> + <property name="title"> + <string>Password Change</string> + </property> + <layout class="QFormLayout" name="formLayout"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::ExpandingFieldsGrow</enum> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="lblCurrentPassword"> + <property name="text"> + <string>&Current password:</string> + </property> + <property name="buddy"> + <cstring>leCurrentPassword</cstring> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="leCurrentPassword"> + <property name="echoMode"> + <enum>QLineEdit::Password</enum> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="lblNewPassword"> + <property name="text"> + <string>&New password:</string> + </property> + <property name="buddy"> + <cstring>leNewPassword</cstring> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="leNewPassword"> + <property name="echoMode"> + <enum>QLineEdit::Password</enum> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="lblNewPassword2"> + <property name="text"> + <string>&Re-enter new password:</string> + </property> + <property name="buddy"> + <cstring>leNewPassword2</cstring> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="leNewPassword2"> + <property name="echoMode"> + <enum>QLineEdit::Password</enum> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QPushButton" name="pbChangePassword"> + <property name="text"> + <string>Change</string> + </property> + </widget> + </item> + <item row="3" column="0" colspan="2"> + <widget class="QLabel" name="lblPasswordChangeStatus"> + <property name="text"> + <string><Password change status></string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="gbGatewaySelector"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="title"> + <string>Select gateway for provider</string> + </property> + <property name="checkable"> + <bool>false</bool> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="lblSelectProvider"> + <property name="text"> + <string>&Select provider:</string> + </property> + <property name="buddy"> + <cstring>cbProviders</cstring> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="cbProviders"> + <item> + <property name="text"> + <string><Select provider></string> + </property> + </item> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Select gateway:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="comboBox"> + <item> + <property name="text"> + <string>Automatic</string> + </property> + </item> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <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> + </layout> + </widget> + <resources> + <include location="../../../../../data/resources/mainwindow.qrc"/> + </resources> + <connections/> +</ui> diff --git a/versioneer.py b/versioneer.py index 57d99419..34e48073 100644 --- a/versioneer.py +++ b/versioneer.py @@ -74,8 +74,8 @@ To use it: version=versioneer.get_version(), cmdclass=versioneer.get_cmdclass(), 4: run 'setup.py update_files', which will create _version.py, and will - append the following to your __init__.py: - from _version import __version__ + modify your __init__.py to define __version__ (by calling a function + from _version.py) 5: modify your MANIFEST.in to include versioneer.py 6: add both versioneer.py and the generated _version.py to your VCS """ @@ -144,7 +144,8 @@ def get_expanded_variables(versionfile_source): # used from _version.py. variables = {} try: - for line in open(versionfile_source,"r").readlines(): + f = open(versionfile_source,"r") + for line in f.readlines(): if line.strip().startswith("git_refnames ="): mo = re.search(r'=\s*"(.*)"', line) if mo: @@ -153,6 +154,7 @@ def get_expanded_variables(versionfile_source): mo = re.search(r'=\s*"(.*)"', line) if mo: variables["full"] = mo.group(1) + f.close() except EnvironmentError: pass return variables @@ -164,20 +166,24 @@ def versions_from_expanded_variables(variables, tag_prefix, verbose=False): print("variables are unexpanded, not using") return {} # unexpanded, so not in an unpacked git-archive tarball refs = set([r.strip() for r in refnames.strip("()").split(",")]) - for ref in list(refs): - if not re.search(r'\d', ref): - if verbose: - print("discarding '%%s', no digits" %% ref) - refs.discard(ref) - # Assume all version tags have a digit. git's %%d expansion - # behaves like git log --decorate=short and strips out the - # refs/heads/ and refs/tags/ prefixes that would let us - # distinguish between branches and tags. By ignoring refnames - # without digits, we filter out many common branch names like - # "release" and "stabilization", as well as "HEAD" and "master". + # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of + # just "foo-1.0". If we see a "tag: " prefix, prefer those. + TAG = "tag: " + tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + if not tags: + # Either we're using git < 1.8.3, or there really are no tags. We use + # a heuristic: assume all version tags have a digit. The old git %%d + # expansion behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us distinguish + # between branches and tags. By ignoring refnames without digits, we + # filter out many common branch names like "release" and + # "stabilization", as well as "HEAD" and "master". + tags = set([r for r in refs if re.search(r'\d', r)]) + if verbose: + print("discarding '%%s', no digits" %% ",".join(refs-tags)) if verbose: - print("remaining refs: %%s" %% ",".join(sorted(refs))) - for ref in sorted(refs): + print("likely tags: %%s" %% ",".join(sorted(tags))) + for ref in sorted(tags): # sorting will prefer e.g. "2.0" over "2.0rc1" if ref.startswith(tag_prefix): r = ref[len(tag_prefix):] @@ -328,7 +334,8 @@ def get_expanded_variables(versionfile_source): # used from _version.py. variables = {} try: - for line in open(versionfile_source,"r").readlines(): + f = open(versionfile_source,"r") + for line in f.readlines(): if line.strip().startswith("git_refnames ="): mo = re.search(r'=\s*"(.*)"', line) if mo: @@ -337,6 +344,7 @@ def get_expanded_variables(versionfile_source): mo = re.search(r'=\s*"(.*)"', line) if mo: variables["full"] = mo.group(1) + f.close() except EnvironmentError: pass return variables @@ -348,20 +356,24 @@ def versions_from_expanded_variables(variables, tag_prefix, verbose=False): print("variables are unexpanded, not using") return {} # unexpanded, so not in an unpacked git-archive tarball refs = set([r.strip() for r in refnames.strip("()").split(",")]) - for ref in list(refs): - if not re.search(r'\d', ref): - if verbose: - print("discarding '%s', no digits" % ref) - refs.discard(ref) - # Assume all version tags have a digit. git's %d expansion - # behaves like git log --decorate=short and strips out the - # refs/heads/ and refs/tags/ prefixes that would let us - # distinguish between branches and tags. By ignoring refnames - # without digits, we filter out many common branch names like - # "release" and "stabilization", as well as "HEAD" and "master". + # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of + # just "foo-1.0". If we see a "tag: " prefix, prefer those. + TAG = "tag: " + tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + if not tags: + # Either we're using git < 1.8.3, or there really are no tags. We use + # a heuristic: assume all version tags have a digit. The old git %d + # expansion behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us distinguish + # between branches and tags. By ignoring refnames without digits, we + # filter out many common branch names like "release" and + # "stabilization", as well as "HEAD" and "master". + tags = set([r for r in refs if re.search(r'\d', r)]) + if verbose: + print("discarding '%s', no digits" % ",".join(refs-tags)) if verbose: - print("remaining refs: %s" % ",".join(sorted(refs))) - for ref in sorted(refs): + print("likely tags: %s" % ",".join(sorted(tags))) + for ref in sorted(tags): # sorting will prefer e.g. "2.0" over "2.0rc1" if ref.startswith(tag_prefix): r = ref[len(tag_prefix):] @@ -513,6 +525,7 @@ def versions_from_file(filename): mo = re.match("version_full = '([^']+)'", line) if mo: versions["full"] = mo.group(1) + f.close() return versions def write_to_version_file(filename, versions): |