Added capability to encrypt saved passwords with a master password and rearranged some configuration parameters related to security.

Sun, 19 Jun 2011 15:19:46 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sun, 19 Jun 2011 15:19:46 +0200
changeset 1127
b1802ebe0066
parent 1123
4ed80ed7e433
child 1128
b8ab8eac9dde

Added capability to encrypt saved passwords with a master password and rearranged some configuration parameters related to security.

APIs/Python3/eric5.api file | annotate | diff | comparison | revisions
Documentation/Help/source.qch file | annotate | diff | comparison | revisions
Documentation/Help/source.qhp file | annotate | diff | comparison | revisions
Documentation/Source/eric5.E5Gui.E5PasswordMeter.html file | annotate | diff | comparison | revisions
Documentation/Source/eric5.Helpviewer.HelpWindow.html file | annotate | diff | comparison | revisions
Documentation/Source/eric5.Helpviewer.Passwords.PasswordManager.html file | annotate | diff | comparison | revisions
Documentation/Source/eric5.Preferences.ConfigurationDialog.html file | annotate | diff | comparison | revisions
Documentation/Source/eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.html file | annotate | diff | comparison | revisions
Documentation/Source/eric5.Preferences.ConfigurationPages.NetworkPage.html file | annotate | diff | comparison | revisions
Documentation/Source/eric5.Preferences.ConfigurationPages.SecurityPage.html file | annotate | diff | comparison | revisions
Documentation/Source/eric5.Preferences.__init__.html file | annotate | diff | comparison | revisions
Documentation/Source/eric5.UI.UserInterface.html file | annotate | diff | comparison | revisions
Documentation/Source/eric5.Utilities.PasswordChecker.html file | annotate | diff | comparison | revisions
Documentation/Source/eric5.Utilities.__init__.html file | annotate | diff | comparison | revisions
Documentation/Source/eric5.Utilities.crypto.__init__.html file | annotate | diff | comparison | revisions
Documentation/Source/eric5.Utilities.crypto.py3AES.html file | annotate | diff | comparison | revisions
Documentation/Source/eric5.Utilities.crypto.py3PBKDF2.html file | annotate | diff | comparison | revisions
Documentation/Source/eric5.install.html file | annotate | diff | comparison | revisions
Documentation/Source/index-eric5.E5Gui.html file | annotate | diff | comparison | revisions
Documentation/Source/index-eric5.Preferences.ConfigurationPages.html file | annotate | diff | comparison | revisions
Documentation/Source/index-eric5.Utilities.crypto.html file | annotate | diff | comparison | revisions
Documentation/Source/index-eric5.Utilities.html file | annotate | diff | comparison | revisions
E5Gui/E5PasswordMeter.py file | annotate | diff | comparison | revisions
Helpviewer/HelpWindow.py file | annotate | diff | comparison | revisions
Helpviewer/Network/NetworkAccessManager.py file | annotate | diff | comparison | revisions
Helpviewer/Passwords/PasswordManager.py file | annotate | diff | comparison | revisions
Preferences/ConfigurationDialog.py file | annotate | diff | comparison | revisions
Preferences/ConfigurationPages/DebuggerPython3Page.ui file | annotate | diff | comparison | revisions
Preferences/ConfigurationPages/DebuggerPythonPage.ui file | annotate | diff | comparison | revisions
Preferences/ConfigurationPages/HelpWebBrowserPage.py file | annotate | diff | comparison | revisions
Preferences/ConfigurationPages/HelpWebBrowserPage.ui file | annotate | diff | comparison | revisions
Preferences/ConfigurationPages/MasterPasswordEntryDialog.py file | annotate | diff | comparison | revisions
Preferences/ConfigurationPages/MasterPasswordEntryDialog.ui file | annotate | diff | comparison | revisions
Preferences/ConfigurationPages/NetworkPage.py file | annotate | diff | comparison | revisions
Preferences/ConfigurationPages/NetworkPage.ui file | annotate | diff | comparison | revisions
Preferences/ConfigurationPages/SecurityPage.py file | annotate | diff | comparison | revisions
Preferences/ConfigurationPages/SecurityPage.ui file | annotate | diff | comparison | revisions
Preferences/__init__.py file | annotate | diff | comparison | revisions
UI/UserInterface.py file | annotate | diff | comparison | revisions
Utilities/PasswordChecker.py file | annotate | diff | comparison | revisions
Utilities/__init__.py file | annotate | diff | comparison | revisions
Utilities/crypto/__init__.py file | annotate | diff | comparison | revisions
Utilities/crypto/py3AES.py file | annotate | diff | comparison | revisions
Utilities/crypto/py3PBKDF2.py file | annotate | diff | comparison | revisions
changelog file | annotate | diff | comparison | revisions
eric5.e4p file | annotate | diff | comparison | revisions
i18n/eric5_cs.ts file | annotate | diff | comparison | revisions
i18n/eric5_de.ts file | annotate | diff | comparison | revisions
i18n/eric5_en.ts file | annotate | diff | comparison | revisions
i18n/eric5_es.ts file | annotate | diff | comparison | revisions
i18n/eric5_fr.ts file | annotate | diff | comparison | revisions
i18n/eric5_it.ts file | annotate | diff | comparison | revisions
i18n/eric5_ru.ts file | annotate | diff | comparison | revisions
i18n/eric5_tr.ts file | annotate | diff | comparison | revisions
i18n/eric5_zh_CN.GB2312.ts file | annotate | diff | comparison | revisions
icons/default/preferences-security.png file | annotate | diff | comparison | revisions
--- a/APIs/Python3/eric5.api	Thu Jun 16 16:29:27 2011 +0200
+++ b/APIs/Python3/eric5.api	Sun Jun 19 15:19:46 2011 +0200
@@ -1289,6 +1289,13 @@
 eric5.E5Gui.E5PassivePopup.E5PassivePopup.view?4()
 eric5.E5Gui.E5PassivePopup.E5PassivePopup?1(parent=None)
 eric5.E5Gui.E5PassivePopup.POPUP_FLAGS?7
+eric5.E5Gui.E5PasswordMeter.E5PasswordMeter.app?7
+eric5.E5Gui.E5PasswordMeter.E5PasswordMeter.checkPasswordStrength?4(password)
+eric5.E5Gui.E5PasswordMeter.E5PasswordMeter.meter?7
+eric5.E5Gui.E5PasswordMeter.E5PasswordMeter.setMaximum?4(value)
+eric5.E5Gui.E5PasswordMeter.E5PasswordMeter.setMinimum?4(value)
+eric5.E5Gui.E5PasswordMeter.E5PasswordMeter.setValue?4(value)
+eric5.E5Gui.E5PasswordMeter.E5PasswordMeter?1(parent=None)
 eric5.E5Gui.E5SideBar.E5SideBar.East?7
 eric5.E5Gui.E5SideBar.E5SideBar.North?7
 eric5.E5Gui.E5SideBar.E5SideBar.South?7
@@ -2091,6 +2098,7 @@
 eric5.Helpviewer.HelpWindow.HelpWindow.historyManager?4()
 eric5.Helpviewer.HelpWindow.HelpWindow.icon?4(url)
 eric5.Helpviewer.HelpWindow.HelpWindow.mainWindow?4()
+eric5.Helpviewer.HelpWindow.HelpWindow.masterPasswordChanged?4(oldPassword, newPassword)
 eric5.Helpviewer.HelpWindow.HelpWindow.maxMenuFilePathLen?7
 eric5.Helpviewer.HelpWindow.HelpWindow.networkAccessManager?4()
 eric5.Helpviewer.HelpWindow.HelpWindow.newTab?4(link=None, requestData=None)
@@ -2359,6 +2367,7 @@
 eric5.Helpviewer.Passwords.PasswordManager.PasswordManager.close?4()
 eric5.Helpviewer.Passwords.PasswordManager.PasswordManager.fill?4(page)
 eric5.Helpviewer.Passwords.PasswordManager.PasswordManager.getLogin?4(url, realm)
+eric5.Helpviewer.Passwords.PasswordManager.PasswordManager.masterPasswordChanged?4(oldPassword, newPassword)
 eric5.Helpviewer.Passwords.PasswordManager.PasswordManager.post?4(request, data)
 eric5.Helpviewer.Passwords.PasswordManager.PasswordManager.removePassword?4(site)
 eric5.Helpviewer.Passwords.PasswordManager.PasswordManager.save?4()
@@ -4378,6 +4387,7 @@
 eric5.Preferences.ConfigurationDialog.ConfigurationDialog.HelpBrowserMode?7
 eric5.Preferences.ConfigurationDialog.ConfigurationDialog.TrayStarterMode?7
 eric5.Preferences.ConfigurationDialog.ConfigurationDialog.getConfigurationPageName?4()
+eric5.Preferences.ConfigurationDialog.ConfigurationDialog.masterPasswordChanged?7
 eric5.Preferences.ConfigurationDialog.ConfigurationDialog.preferencesChanged?7
 eric5.Preferences.ConfigurationDialog.ConfigurationDialog.setPreferences?4()
 eric5.Preferences.ConfigurationDialog.ConfigurationDialog.showConfigurationPageByName?4(pageName)
@@ -4391,6 +4401,7 @@
 eric5.Preferences.ConfigurationDialog.ConfigurationWidget.getConfigurationPageName?4()
 eric5.Preferences.ConfigurationDialog.ConfigurationWidget.getLexers?4()
 eric5.Preferences.ConfigurationDialog.ConfigurationWidget.getPage?4(pageName)
+eric5.Preferences.ConfigurationDialog.ConfigurationWidget.masterPasswordChanged?7
 eric5.Preferences.ConfigurationDialog.ConfigurationWidget.on_applyButton_clicked?4()
 eric5.Preferences.ConfigurationDialog.ConfigurationWidget.on_buttonBox_clicked?4(button)
 eric5.Preferences.ConfigurationDialog.ConfigurationWidget.on_resetButton_clicked?4()
@@ -4631,9 +4642,16 @@
 eric5.Preferences.ConfigurationPages.InterfacePage.InterfacePage.save?4()
 eric5.Preferences.ConfigurationPages.InterfacePage.InterfacePage?1()
 eric5.Preferences.ConfigurationPages.InterfacePage.create?4(dlg)
+eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.MasterPasswordEntryDialog.getCurrentPassword?4()
+eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.MasterPasswordEntryDialog.getMasterPassword?4()
+eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.MasterPasswordEntryDialog.on_currentPasswordEdit_textChanged?4(txt)
+eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.MasterPasswordEntryDialog.on_newPasswordAgainEdit_textChanged?4(txt)
+eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.MasterPasswordEntryDialog.on_newPasswordEdit_textChanged?4(txt)
+eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.MasterPasswordEntryDialog?1(oldPasswordHash, parent=None)
 eric5.Preferences.ConfigurationPages.MultiProjectPage.MultiProjectPage.save?4()
 eric5.Preferences.ConfigurationPages.MultiProjectPage.MultiProjectPage?1()
 eric5.Preferences.ConfigurationPages.MultiProjectPage.create?4(dlg)
+eric5.Preferences.ConfigurationPages.NetworkPage.NetworkPage.on_clearProxyPasswordsButton_clicked?4()
 eric5.Preferences.ConfigurationPages.NetworkPage.NetworkPage.on_downloadDirButton_clicked?4()
 eric5.Preferences.ConfigurationPages.NetworkPage.NetworkPage.save?4()
 eric5.Preferences.ConfigurationPages.NetworkPage.NetworkPage?1()
@@ -4668,6 +4686,11 @@
 eric5.Preferences.ConfigurationPages.QtPage.QtPage.save?4()
 eric5.Preferences.ConfigurationPages.QtPage.QtPage?1()
 eric5.Preferences.ConfigurationPages.QtPage.create?4(dlg)
+eric5.Preferences.ConfigurationPages.SecurityPage.SecurityPage.on_masterPasswordButton_clicked?4()
+eric5.Preferences.ConfigurationPages.SecurityPage.SecurityPage.on_masterPasswordCheckBox_clicked?4(checked)
+eric5.Preferences.ConfigurationPages.SecurityPage.SecurityPage.save?4()
+eric5.Preferences.ConfigurationPages.SecurityPage.SecurityPage?1(configDialog)
+eric5.Preferences.ConfigurationPages.SecurityPage.create?4(dlg)
 eric5.Preferences.ConfigurationPages.ShellPage.ShellPage.on_linenumbersFontButton_clicked?4()
 eric5.Preferences.ConfigurationPages.ShellPage.ShellPage.on_monospacedFontButton_clicked?4()
 eric5.Preferences.ConfigurationPages.ShellPage.ShellPage.polishPage?4()
@@ -4816,6 +4839,7 @@
 eric5.Preferences.ToolGroupConfigurationDialog.ToolGroupConfigurationDialog?1(toolGroups, currentGroup, parent=None)
 eric5.Preferences.ViewProfileDialog.ViewProfileDialog.getProfiles?4()
 eric5.Preferences.ViewProfileDialog.ViewProfileDialog?1(layout, profiles, separateShell, separateBrowser, parent=None)
+eric5.Preferences.convertPasswords?4(oldPassword, newPassword, prefClass=Prefs)
 eric5.Preferences.exportPreferences?4(prefClass=Prefs)
 eric5.Preferences.getCooperation?4(key, prefClass=Prefs)
 eric5.Preferences.getCorba?4(key, prefClass=Prefs)
@@ -6448,6 +6472,7 @@
 eric5.UI.UserInterface.UserInterface.getToolbar?4(name)
 eric5.UI.UserInterface.UserInterface.getViewProfile?4()
 eric5.UI.UserInterface.UserInterface.launchHelpViewer?4(home, searchWord=None)
+eric5.UI.UserInterface.UserInterface.masterPasswordChanged?7
 eric5.UI.UserInterface.UserInterface.maxFilePathLen?7
 eric5.UI.UserInterface.UserInterface.maxMenuFilePathLen?7
 eric5.UI.UserInterface.UserInterface.maxSbFilePathLen?7
@@ -6580,6 +6605,16 @@
 eric5.Utilities.ModuleParser.readModule?4(module, path=[], inpackage=False, basename="", extensions=None, caching=True)
 eric5.Utilities.ModuleParser.resetParsedModule?4(module, basename="")
 eric5.Utilities.ModuleParser.resetParsedModules?4()
+eric5.Utilities.PasswordChecker.PasswordChecker.Complexity_Good?7
+eric5.Utilities.PasswordChecker.PasswordChecker.Complexity_Strong?7
+eric5.Utilities.PasswordChecker.PasswordChecker.Complexity_VeryStrong?7
+eric5.Utilities.PasswordChecker.PasswordChecker.Complexity_VeryWeak?7
+eric5.Utilities.PasswordChecker.PasswordChecker.Complexity_Weak?7
+eric5.Utilities.PasswordChecker.PasswordChecker.Status_Exceeded?7
+eric5.Utilities.PasswordChecker.PasswordChecker.Status_Failed?7
+eric5.Utilities.PasswordChecker.PasswordChecker.Status_Passed?7
+eric5.Utilities.PasswordChecker.PasswordChecker.checkPassword?4(password)
+eric5.Utilities.PasswordChecker.PasswordChecker?1()
 eric5.Utilities.SingleApplication.SingleApplicationClient.connect?4()
 eric5.Utilities.SingleApplication.SingleApplicationClient.disconnect?4()
 eric5.Utilities.SingleApplication.SingleApplicationClient.errstr?4()
@@ -6610,6 +6645,39 @@
 eric5.Utilities.compile?4(file, codestring="")
 eric5.Utilities.configDir?7
 eric5.Utilities.convertLineEnds?4(text, eol)
+eric5.Utilities.crypto.CryptoMarker?7
+eric5.Utilities.crypto.Delimiter?7
+eric5.Utilities.crypto.EncodeMarker?7
+eric5.Utilities.crypto.MasterPassword?7
+eric5.Utilities.crypto.changeRememberedMaster?4(newPassword)
+eric5.Utilities.crypto.pwConvert?4(pw, encode=True)
+eric5.Utilities.crypto.pwDecode?4(epw)
+eric5.Utilities.crypto.pwDecrypt?4(epw, masterPW=None)
+eric5.Utilities.crypto.pwEncode?4(pw)
+eric5.Utilities.crypto.pwEncrypt?4(pw, masterPW=None)
+eric5.Utilities.crypto.pwRecode?4(epw, oldPassword, newPassword)
+eric5.Utilities.crypto.pwReencrypt?4(epw, oldPassword, newPassword)
+eric5.Utilities.crypto.py3AES.AES.KeySize?7
+eric5.Utilities.crypto.py3AES.AES.Rcon?7
+eric5.Utilities.crypto.py3AES.AES.decrypt?4(iput, key, size)
+eric5.Utilities.crypto.py3AES.AES.encrypt?4(iput, key, size)
+eric5.Utilities.crypto.py3AES.AES.rsbox?7
+eric5.Utilities.crypto.py3AES.AES.sbox?7
+eric5.Utilities.crypto.py3AES.AESModeOfOperation.ModeOfOperation?7
+eric5.Utilities.crypto.py3AES.AESModeOfOperation.aes?7
+eric5.Utilities.crypto.py3AES.AESModeOfOperation.decrypt?4(cipherIn, originalsize, mode, key, size, IV)
+eric5.Utilities.crypto.py3AES.AESModeOfOperation.encrypt?4(input, mode, key, size, IV)
+eric5.Utilities.crypto.py3AES.append_PKCS7_padding?4(b)
+eric5.Utilities.crypto.py3AES.decryptData?4(key, data, mode=AESModeOfOperation.ModeOfOperation["CBC"])
+eric5.Utilities.crypto.py3AES.encryptData?4(key, data, mode=AESModeOfOperation.ModeOfOperation["CBC"])
+eric5.Utilities.crypto.py3AES.strip_PKCS7_padding?4(b)
+eric5.Utilities.crypto.py3PBKDF2.Delimiter?7
+eric5.Utilities.crypto.py3PBKDF2.Hashes?7
+eric5.Utilities.crypto.py3PBKDF2.hashPassword?4(password, digestMod=hashlib.sha512, iterations=10000, saltSize=32)
+eric5.Utilities.crypto.py3PBKDF2.hashPasswordTuple?4(password, digestMod=hashlib.sha512, iterations=10000, saltSize=32)
+eric5.Utilities.crypto.py3PBKDF2.pbkdf2?4(password, salt, iterations, digestMod)
+eric5.Utilities.crypto.py3PBKDF2.rehashPassword?4(password, hashParameters)
+eric5.Utilities.crypto.py3PBKDF2.verifyPassword?4(password, hash)
 eric5.Utilities.decode?4(text)
 eric5.Utilities.decodeBytes?4(buffer)
 eric5.Utilities.decodeString?4(text)
@@ -6653,8 +6721,6 @@
 eric5.Utilities.parseOptionString?4(s)
 eric5.Utilities.parseString?4(s, rx)
 eric5.Utilities.prepareQtMacBundle?4(toolname, version, args)
-eric5.Utilities.pwDecode?4(epw)
-eric5.Utilities.pwEncode?4(pw)
 eric5.Utilities.py2compile?4(file, checkFlakes=False)
 eric5.Utilities.py3flakes.checker.Binding?1(name, source)
 eric5.Utilities.py3flakes.checker.Checker.ASSIGN?4(node)
@@ -7246,7 +7312,7 @@
 eric5.install.configLength?7
 eric5.install.configName?7
 eric5.install.copyToFile?4(name, text)
-eric5.install.copyTree?4(src, dst, filters, excludeDirs=[])
+eric5.install.copyTree?4(src, dst, filters, excludeDirs=[], excludePatterns=[])
 eric5.install.createConfig?4()
 eric5.install.createGlobalPluginsDir?4()
 eric5.install.createInstallConfig?4()
Binary file Documentation/Help/source.qch has changed
--- a/Documentation/Help/source.qhp	Thu Jun 16 16:29:27 2011 +0200
+++ b/Documentation/Help/source.qhp	Sun Jun 19 15:19:46 2011 +0200
@@ -124,6 +124,7 @@
             <section title="eric5.E5Gui.E5ModelMenu" ref="eric5.E5Gui.E5ModelMenu.html" />
             <section title="eric5.E5Gui.E5ModelToolBar" ref="eric5.E5Gui.E5ModelToolBar.html" />
             <section title="eric5.E5Gui.E5PassivePopup" ref="eric5.E5Gui.E5PassivePopup.html" />
+            <section title="eric5.E5Gui.E5PasswordMeter" ref="eric5.E5Gui.E5PasswordMeter.html" />
             <section title="eric5.E5Gui.E5SideBar" ref="eric5.E5Gui.E5SideBar.html" />
             <section title="eric5.E5Gui.E5SingleApplication" ref="eric5.E5Gui.E5SingleApplication.html" />
             <section title="eric5.E5Gui.E5SqueezeLabels" ref="eric5.E5Gui.E5SqueezeLabels.html" />
@@ -607,6 +608,7 @@
               <section title="eric5.Preferences.ConfigurationPages.IconsPage" ref="eric5.Preferences.ConfigurationPages.IconsPage.html" />
               <section title="eric5.Preferences.ConfigurationPages.IconsPreviewDialog" ref="eric5.Preferences.ConfigurationPages.IconsPreviewDialog.html" />
               <section title="eric5.Preferences.ConfigurationPages.InterfacePage" ref="eric5.Preferences.ConfigurationPages.InterfacePage.html" />
+              <section title="eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog" ref="eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.html" />
               <section title="eric5.Preferences.ConfigurationPages.MultiProjectPage" ref="eric5.Preferences.ConfigurationPages.MultiProjectPage.html" />
               <section title="eric5.Preferences.ConfigurationPages.NetworkPage" ref="eric5.Preferences.ConfigurationPages.NetworkPage.html" />
               <section title="eric5.Preferences.ConfigurationPages.PluginManagerPage" ref="eric5.Preferences.ConfigurationPages.PluginManagerPage.html" />
@@ -616,6 +618,7 @@
               <section title="eric5.Preferences.ConfigurationPages.Py3FlakesPage" ref="eric5.Preferences.ConfigurationPages.Py3FlakesPage.html" />
               <section title="eric5.Preferences.ConfigurationPages.PythonPage" ref="eric5.Preferences.ConfigurationPages.PythonPage.html" />
               <section title="eric5.Preferences.ConfigurationPages.QtPage" ref="eric5.Preferences.ConfigurationPages.QtPage.html" />
+              <section title="eric5.Preferences.ConfigurationPages.SecurityPage" ref="eric5.Preferences.ConfigurationPages.SecurityPage.html" />
               <section title="eric5.Preferences.ConfigurationPages.ShellPage" ref="eric5.Preferences.ConfigurationPages.ShellPage.html" />
               <section title="eric5.Preferences.ConfigurationPages.TasksPage" ref="eric5.Preferences.ConfigurationPages.TasksPage.html" />
               <section title="eric5.Preferences.ConfigurationPages.TemplatesPage" ref="eric5.Preferences.ConfigurationPages.TemplatesPage.html" />
@@ -784,12 +787,18 @@
               <section title="eric5.Utilities.ClassBrowsers.pyclbr" ref="eric5.Utilities.ClassBrowsers.pyclbr.html" />
               <section title="eric5.Utilities.ClassBrowsers.rbclbr" ref="eric5.Utilities.ClassBrowsers.rbclbr.html" />
             </section>
+            <section title="eric5.Utilities.crypto" ref="index-eric5.Utilities.crypto.html">
+              <section title="eric5.Utilities.crypto.__init__" ref="eric5.Utilities.crypto.__init__.html" />
+              <section title="eric5.Utilities.crypto.py3AES" ref="eric5.Utilities.crypto.py3AES.html" />
+              <section title="eric5.Utilities.crypto.py3PBKDF2" ref="eric5.Utilities.crypto.py3PBKDF2.html" />
+            </section>
             <section title="eric5.Utilities.py3flakes" ref="index-eric5.Utilities.py3flakes.html">
               <section title="eric5.Utilities.py3flakes.checker" ref="eric5.Utilities.py3flakes.checker.html" />
               <section title="eric5.Utilities.py3flakes.messages" ref="eric5.Utilities.py3flakes.messages.html" />
             </section>
             <section title="eric5.Utilities.AutoSaver" ref="eric5.Utilities.AutoSaver.html" />
             <section title="eric5.Utilities.ModuleParser" ref="eric5.Utilities.ModuleParser.html" />
+            <section title="eric5.Utilities.PasswordChecker" ref="eric5.Utilities.PasswordChecker.html" />
             <section title="eric5.Utilities.SingleApplication" ref="eric5.Utilities.SingleApplication.html" />
             <section title="eric5.Utilities.Startup" ref="eric5.Utilities.Startup.html" />
             <section title="eric5.Utilities.__init__" ref="eric5.Utilities.__init__.html" />
@@ -2452,8 +2461,6 @@
       <keyword name="parseOptionString" id="parseOptionString" ref="eric5.Utilities.__init__.html#parseOptionString" />
       <keyword name="parseString" id="parseString" ref="eric5.Utilities.__init__.html#parseString" />
       <keyword name="prepareQtMacBundle" id="prepareQtMacBundle" ref="eric5.Utilities.__init__.html#prepareQtMacBundle" />
-      <keyword name="pwDecode" id="pwDecode" ref="eric5.Utilities.__init__.html#pwDecode" />
-      <keyword name="pwEncode" id="pwEncode" ref="eric5.Utilities.__init__.html#pwEncode" />
       <keyword name="py2compile" id="py2compile" ref="eric5.Utilities.__init__.html#py2compile" />
       <keyword name="readEncodedFile" id="readEncodedFile" ref="eric5.Utilities.__init__.html#readEncodedFile" />
       <keyword name="readEncodedFileWithHash" id="readEncodedFileWithHash" ref="eric5.Utilities.__init__.html#readEncodedFileWithHash" />
@@ -2483,6 +2490,13 @@
       <keyword name="compileUiFiles" id="compileUiFiles" ref="eric5.Utilities.uic.html#compileUiFiles" />
       <keyword name="compile_ui" id="compile_ui" ref="eric5.Utilities.uic.html#compile_ui" />
       <keyword name="pyName" id="pyName" ref="eric5.Utilities.uic.html#pyName" />
+      <keyword name="PasswordChecker (Module)" id="PasswordChecker (Module)" ref="eric5.Utilities.PasswordChecker.html" />
+      <keyword name="PasswordChecker" id="PasswordChecker" ref="eric5.Utilities.PasswordChecker.html#PasswordChecker" />
+      <keyword name="PasswordChecker (Constructor)" id="PasswordChecker (Constructor)" ref="eric5.Utilities.PasswordChecker.html#PasswordChecker.__init__" />
+      <keyword name="PasswordChecker.__determineBinaryStatus" id="PasswordChecker.__determineBinaryStatus" ref="eric5.Utilities.PasswordChecker.html#PasswordChecker.__determineBinaryStatus" />
+      <keyword name="PasswordChecker.__determineStatus" id="PasswordChecker.__determineStatus" ref="eric5.Utilities.PasswordChecker.html#PasswordChecker.__determineStatus" />
+      <keyword name="PasswordChecker.__strReverse" id="PasswordChecker.__strReverse" ref="eric5.Utilities.PasswordChecker.html#PasswordChecker.__strReverse" />
+      <keyword name="PasswordChecker.checkPassword" id="PasswordChecker.checkPassword" ref="eric5.Utilities.PasswordChecker.html#PasswordChecker.checkPassword" />
       <keyword name="ModuleParser (Module)" id="ModuleParser (Module)" ref="eric5.Utilities.ModuleParser.html" />
       <keyword name="Attribute" id="Attribute" ref="eric5.Utilities.ModuleParser.html#Attribute" />
       <keyword name="Class" id="Class" ref="eric5.Utilities.ModuleParser.html#Class" />
@@ -2894,6 +2908,7 @@
       <keyword name="HelpWindow.historyManager" id="HelpWindow.historyManager" ref="eric5.Helpviewer.HelpWindow.html#HelpWindow.historyManager" />
       <keyword name="HelpWindow.icon" id="HelpWindow.icon" ref="eric5.Helpviewer.HelpWindow.html#HelpWindow.icon" />
       <keyword name="HelpWindow.mainWindow" id="HelpWindow.mainWindow" ref="eric5.Helpviewer.HelpWindow.html#HelpWindow.mainWindow" />
+      <keyword name="HelpWindow.masterPasswordChanged" id="HelpWindow.masterPasswordChanged" ref="eric5.Helpviewer.HelpWindow.html#HelpWindow.masterPasswordChanged" />
       <keyword name="HelpWindow.networkAccessManager" id="HelpWindow.networkAccessManager" ref="eric5.Helpviewer.HelpWindow.html#HelpWindow.networkAccessManager" />
       <keyword name="HelpWindow.newTab" id="HelpWindow.newTab" ref="eric5.Helpviewer.HelpWindow.html#HelpWindow.newTab" />
       <keyword name="HelpWindow.newWindow" id="HelpWindow.newWindow" ref="eric5.Helpviewer.HelpWindow.html#HelpWindow.newWindow" />
@@ -3020,6 +3035,7 @@
       <keyword name="HelpTabWidget.stackedUrlBar" id="HelpTabWidget.stackedUrlBar" ref="eric5.Helpviewer.HelpTabWidget.html#HelpTabWidget.stackedUrlBar" />
       <keyword name="Preferences (Package)" id="Preferences (Package)" ref="index-eric5.Preferences.html" />
       <keyword name="Prefs" id="Prefs" ref="eric5.Preferences.__init__.html#Prefs" />
+      <keyword name="convertPasswords" id="convertPasswords" ref="eric5.Preferences.__init__.html#convertPasswords" />
       <keyword name="exportPreferences" id="exportPreferences" ref="eric5.Preferences.__init__.html#exportPreferences" />
       <keyword name="getCooperation" id="getCooperation" ref="eric5.Preferences.__init__.html#getCooperation" />
       <keyword name="getCorba" id="getCorba" ref="eric5.Preferences.__init__.html#getCorba" />
@@ -3167,6 +3183,7 @@
       <keyword name="ConfigurationWidget" id="ConfigurationWidget" ref="eric5.Preferences.ConfigurationDialog.html#ConfigurationWidget" />
       <keyword name="ConfigurationWindow" id="ConfigurationWindow" ref="eric5.Preferences.ConfigurationDialog.html#ConfigurationWindow" />
       <keyword name="ConfigurationDialog (Constructor)" id="ConfigurationDialog (Constructor)" ref="eric5.Preferences.ConfigurationDialog.html#ConfigurationDialog.__init__" />
+      <keyword name="ConfigurationDialog.__masterPasswordChanged" id="ConfigurationDialog.__masterPasswordChanged" ref="eric5.Preferences.ConfigurationDialog.html#ConfigurationDialog.__masterPasswordChanged" />
       <keyword name="ConfigurationDialog.__preferencesChanged" id="ConfigurationDialog.__preferencesChanged" ref="eric5.Preferences.ConfigurationDialog.html#ConfigurationDialog.__preferencesChanged" />
       <keyword name="ConfigurationDialog.getConfigurationPageName" id="ConfigurationDialog.getConfigurationPageName" ref="eric5.Preferences.ConfigurationDialog.html#ConfigurationDialog.getConfigurationPageName" />
       <keyword name="ConfigurationDialog.setPreferences" id="ConfigurationDialog.setPreferences" ref="eric5.Preferences.ConfigurationDialog.html#ConfigurationDialog.setPreferences" />
@@ -4179,6 +4196,7 @@
       <keyword name="UserInterface.__lastEditorClosed" id="UserInterface.__lastEditorClosed" ref="eric5.UI.UserInterface.html#UserInterface.__lastEditorClosed" />
       <keyword name="UserInterface.__linguist" id="UserInterface.__linguist" ref="eric5.UI.UserInterface.html#UserInterface.__linguist" />
       <keyword name="UserInterface.__linguist4" id="UserInterface.__linguist4" ref="eric5.UI.UserInterface.html#UserInterface.__linguist4" />
+      <keyword name="UserInterface.__masterPasswordChanged" id="UserInterface.__masterPasswordChanged" ref="eric5.UI.UserInterface.html#UserInterface.__masterPasswordChanged" />
       <keyword name="UserInterface.__newProject" id="UserInterface.__newProject" ref="eric5.UI.UserInterface.html#UserInterface.__newProject" />
       <keyword name="UserInterface.__openMiniEditor" id="UserInterface.__openMiniEditor" ref="eric5.UI.UserInterface.html#UserInterface.__openMiniEditor" />
       <keyword name="UserInterface.__openOnStartup" id="UserInterface.__openOnStartup" ref="eric5.UI.UserInterface.html#UserInterface.__openOnStartup" />
@@ -4560,6 +4578,13 @@
       <keyword name="E5Application.registerObject" id="E5Application.registerObject" ref="eric5.E5Gui.E5Application.html#E5Application.registerObject" />
       <keyword name="E5Application.registerPluginObject" id="E5Application.registerPluginObject" ref="eric5.E5Gui.E5Application.html#E5Application.registerPluginObject" />
       <keyword name="E5Application.unregisterPluginObject" id="E5Application.unregisterPluginObject" ref="eric5.E5Gui.E5Application.html#E5Application.unregisterPluginObject" />
+      <keyword name="E5PasswordMeter (Module)" id="E5PasswordMeter (Module)" ref="eric5.E5Gui.E5PasswordMeter.html" />
+      <keyword name="E5PasswordMeter" id="E5PasswordMeter" ref="eric5.E5Gui.E5PasswordMeter.html#E5PasswordMeter" />
+      <keyword name="E5PasswordMeter (Constructor)" id="E5PasswordMeter (Constructor)" ref="eric5.E5Gui.E5PasswordMeter.html#E5PasswordMeter.__init__" />
+      <keyword name="E5PasswordMeter.checkPasswordStrength" id="E5PasswordMeter.checkPasswordStrength" ref="eric5.E5Gui.E5PasswordMeter.html#E5PasswordMeter.checkPasswordStrength" />
+      <keyword name="E5PasswordMeter.setMaximum" id="E5PasswordMeter.setMaximum" ref="eric5.E5Gui.E5PasswordMeter.html#E5PasswordMeter.setMaximum" />
+      <keyword name="E5PasswordMeter.setMinimum" id="E5PasswordMeter.setMinimum" ref="eric5.E5Gui.E5PasswordMeter.html#E5PasswordMeter.setMinimum" />
+      <keyword name="E5PasswordMeter.setValue" id="E5PasswordMeter.setValue" ref="eric5.E5Gui.E5PasswordMeter.html#E5PasswordMeter.setValue" />
       <keyword name="E5TreeSortFilterProxyModel (Module)" id="E5TreeSortFilterProxyModel (Module)" ref="eric5.E5Gui.E5TreeSortFilterProxyModel.html" />
       <keyword name="E5TreeSortFilterProxyModel" id="E5TreeSortFilterProxyModel" ref="eric5.E5Gui.E5TreeSortFilterProxyModel.html#E5TreeSortFilterProxyModel" />
       <keyword name="E5TreeSortFilterProxyModel (Constructor)" id="E5TreeSortFilterProxyModel (Constructor)" ref="eric5.E5Gui.E5TreeSortFilterProxyModel.html#E5TreeSortFilterProxyModel.__init__" />
@@ -6908,6 +6933,52 @@
       <keyword name="Interface (Constructor)" id="Interface (Constructor)" ref="eric5.Utilities.ClassBrowsers.idlclbr.html#Interface.__init__" />
       <keyword name="Module (Constructor)" id="Module (Constructor)" ref="eric5.Utilities.ClassBrowsers.idlclbr.html#Module.__init__" />
       <keyword name="VisibilityMixin (Constructor)" id="VisibilityMixin (Constructor)" ref="eric5.Utilities.ClassBrowsers.idlclbr.html#VisibilityMixin.__init__" />
+      <keyword name="crypto (Package)" id="crypto (Package)" ref="index-eric5.Utilities.crypto.html" />
+      <keyword name="__getMasterPassword" id="__getMasterPassword" ref="eric5.Utilities.crypto.__init__.html#__getMasterPassword" />
+      <keyword name="changeRememberedMaster" id="changeRememberedMaster" ref="eric5.Utilities.crypto.__init__.html#changeRememberedMaster" />
+      <keyword name="pwConvert" id="pwConvert" ref="eric5.Utilities.crypto.__init__.html#pwConvert" />
+      <keyword name="pwDecode" id="pwDecode" ref="eric5.Utilities.crypto.__init__.html#pwDecode" />
+      <keyword name="pwDecrypt" id="pwDecrypt" ref="eric5.Utilities.crypto.__init__.html#pwDecrypt" />
+      <keyword name="pwEncode" id="pwEncode" ref="eric5.Utilities.crypto.__init__.html#pwEncode" />
+      <keyword name="pwEncrypt" id="pwEncrypt" ref="eric5.Utilities.crypto.__init__.html#pwEncrypt" />
+      <keyword name="pwRecode" id="pwRecode" ref="eric5.Utilities.crypto.__init__.html#pwRecode" />
+      <keyword name="pwReencrypt" id="pwReencrypt" ref="eric5.Utilities.crypto.__init__.html#pwReencrypt" />
+      <keyword name="py3AES (Module)" id="py3AES (Module)" ref="eric5.Utilities.crypto.py3AES.html" />
+      <keyword name="AES" id="AES" ref="eric5.Utilities.crypto.py3AES.html#AES" />
+      <keyword name="AESModeOfOperation" id="AESModeOfOperation" ref="eric5.Utilities.crypto.py3AES.html#AESModeOfOperation" />
+      <keyword name="append_PKCS7_padding" id="append_PKCS7_padding" ref="eric5.Utilities.crypto.py3AES.html#append_PKCS7_padding" />
+      <keyword name="decryptData" id="decryptData" ref="eric5.Utilities.crypto.py3AES.html#decryptData" />
+      <keyword name="encryptData" id="encryptData" ref="eric5.Utilities.crypto.py3AES.html#encryptData" />
+      <keyword name="strip_PKCS7_padding" id="strip_PKCS7_padding" ref="eric5.Utilities.crypto.py3AES.html#strip_PKCS7_padding" />
+      <keyword name="AES.__addRoundKey" id="AES.__addRoundKey" ref="eric5.Utilities.crypto.py3AES.html#AES.__addRoundKey" />
+      <keyword name="AES.__aes_invMain" id="AES.__aes_invMain" ref="eric5.Utilities.crypto.py3AES.html#AES.__aes_invMain" />
+      <keyword name="AES.__aes_invRound" id="AES.__aes_invRound" ref="eric5.Utilities.crypto.py3AES.html#AES.__aes_invRound" />
+      <keyword name="AES.__aes_main" id="AES.__aes_main" ref="eric5.Utilities.crypto.py3AES.html#AES.__aes_main" />
+      <keyword name="AES.__aes_round" id="AES.__aes_round" ref="eric5.Utilities.crypto.py3AES.html#AES.__aes_round" />
+      <keyword name="AES.__core" id="AES.__core" ref="eric5.Utilities.crypto.py3AES.html#AES.__core" />
+      <keyword name="AES.__createRoundKey" id="AES.__createRoundKey" ref="eric5.Utilities.crypto.py3AES.html#AES.__createRoundKey" />
+      <keyword name="AES.__expandKey" id="AES.__expandKey" ref="eric5.Utilities.crypto.py3AES.html#AES.__expandKey" />
+      <keyword name="AES.__galois_multiplication" id="AES.__galois_multiplication" ref="eric5.Utilities.crypto.py3AES.html#AES.__galois_multiplication" />
+      <keyword name="AES.__getRconValue" id="AES.__getRconValue" ref="eric5.Utilities.crypto.py3AES.html#AES.__getRconValue" />
+      <keyword name="AES.__getSBoxInvert" id="AES.__getSBoxInvert" ref="eric5.Utilities.crypto.py3AES.html#AES.__getSBoxInvert" />
+      <keyword name="AES.__getSBoxValue" id="AES.__getSBoxValue" ref="eric5.Utilities.crypto.py3AES.html#AES.__getSBoxValue" />
+      <keyword name="AES.__mixColumn" id="AES.__mixColumn" ref="eric5.Utilities.crypto.py3AES.html#AES.__mixColumn" />
+      <keyword name="AES.__mixColumns" id="AES.__mixColumns" ref="eric5.Utilities.crypto.py3AES.html#AES.__mixColumns" />
+      <keyword name="AES.__rotate" id="AES.__rotate" ref="eric5.Utilities.crypto.py3AES.html#AES.__rotate" />
+      <keyword name="AES.__shiftRow" id="AES.__shiftRow" ref="eric5.Utilities.crypto.py3AES.html#AES.__shiftRow" />
+      <keyword name="AES.__shiftRows" id="AES.__shiftRows" ref="eric5.Utilities.crypto.py3AES.html#AES.__shiftRows" />
+      <keyword name="AES.__subBytes" id="AES.__subBytes" ref="eric5.Utilities.crypto.py3AES.html#AES.__subBytes" />
+      <keyword name="AES.decrypt" id="AES.decrypt" ref="eric5.Utilities.crypto.py3AES.html#AES.decrypt" />
+      <keyword name="AES.encrypt" id="AES.encrypt" ref="eric5.Utilities.crypto.py3AES.html#AES.encrypt" />
+      <keyword name="AESModeOfOperation.__extractBytes" id="AESModeOfOperation.__extractBytes" ref="eric5.Utilities.crypto.py3AES.html#AESModeOfOperation.__extractBytes" />
+      <keyword name="AESModeOfOperation.decrypt" id="AESModeOfOperation.decrypt" ref="eric5.Utilities.crypto.py3AES.html#AESModeOfOperation.decrypt" />
+      <keyword name="AESModeOfOperation.encrypt" id="AESModeOfOperation.encrypt" ref="eric5.Utilities.crypto.py3AES.html#AESModeOfOperation.encrypt" />
+      <keyword name="py3PBKDF2 (Module)" id="py3PBKDF2 (Module)" ref="eric5.Utilities.crypto.py3PBKDF2.html" />
+      <keyword name="hashPassword" id="hashPassword" ref="eric5.Utilities.crypto.py3PBKDF2.html#hashPassword" />
+      <keyword name="hashPasswordTuple" id="hashPasswordTuple" ref="eric5.Utilities.crypto.py3PBKDF2.html#hashPasswordTuple" />
+      <keyword name="pbkdf2" id="pbkdf2" ref="eric5.Utilities.crypto.py3PBKDF2.html#pbkdf2" />
+      <keyword name="rehashPassword" id="rehashPassword" ref="eric5.Utilities.crypto.py3PBKDF2.html#rehashPassword" />
+      <keyword name="verifyPassword" id="verifyPassword" ref="eric5.Utilities.crypto.py3PBKDF2.html#verifyPassword" />
       <keyword name="py3flakes (Package)" id="py3flakes (Package)" ref="index-eric5.Utilities.py3flakes.html" />
       <keyword name="checker (Module)" id="checker (Module)" ref="eric5.Utilities.py3flakes.checker.html" />
       <keyword name="Argument" id="Argument" ref="eric5.Utilities.py3flakes.checker.html#Argument" />
@@ -7022,6 +7093,7 @@
       <keyword name="PasswordManager.close" id="PasswordManager.close" ref="eric5.Helpviewer.Passwords.PasswordManager.html#PasswordManager.close" />
       <keyword name="PasswordManager.fill" id="PasswordManager.fill" ref="eric5.Helpviewer.Passwords.PasswordManager.html#PasswordManager.fill" />
       <keyword name="PasswordManager.getLogin" id="PasswordManager.getLogin" ref="eric5.Helpviewer.Passwords.PasswordManager.html#PasswordManager.getLogin" />
+      <keyword name="PasswordManager.masterPasswordChanged" id="PasswordManager.masterPasswordChanged" ref="eric5.Helpviewer.Passwords.PasswordManager.html#PasswordManager.masterPasswordChanged" />
       <keyword name="PasswordManager.post" id="PasswordManager.post" ref="eric5.Helpviewer.Passwords.PasswordManager.html#PasswordManager.post" />
       <keyword name="PasswordManager.removePassword" id="PasswordManager.removePassword" ref="eric5.Helpviewer.Passwords.PasswordManager.html#PasswordManager.removePassword" />
       <keyword name="PasswordManager.save" id="PasswordManager.save" ref="eric5.Helpviewer.Passwords.PasswordManager.html#PasswordManager.save" />
@@ -7980,6 +8052,7 @@
       <keyword name="NetworkPage" id="NetworkPage" ref="eric5.Preferences.ConfigurationPages.NetworkPage.html#NetworkPage" />
       <keyword name="create" id="create" ref="eric5.Preferences.ConfigurationPages.NetworkPage.html#create" />
       <keyword name="NetworkPage (Constructor)" id="NetworkPage (Constructor)" ref="eric5.Preferences.ConfigurationPages.NetworkPage.html#NetworkPage.__init__" />
+      <keyword name="NetworkPage.on_clearProxyPasswordsButton_clicked" id="NetworkPage.on_clearProxyPasswordsButton_clicked" ref="eric5.Preferences.ConfigurationPages.NetworkPage.html#NetworkPage.on_clearProxyPasswordsButton_clicked" />
       <keyword name="NetworkPage.on_downloadDirButton_clicked" id="NetworkPage.on_downloadDirButton_clicked" ref="eric5.Preferences.ConfigurationPages.NetworkPage.html#NetworkPage.on_downloadDirButton_clicked" />
       <keyword name="NetworkPage.save" id="NetworkPage.save" ref="eric5.Preferences.ConfigurationPages.NetworkPage.html#NetworkPage.save" />
       <keyword name="HelpWebBrowserPage (Module)" id="HelpWebBrowserPage (Module)" ref="eric5.Preferences.ConfigurationPages.HelpWebBrowserPage.html" />
@@ -8148,6 +8221,15 @@
       <keyword name="ShellPage.on_monospacedFontButton_clicked" id="ShellPage.on_monospacedFontButton_clicked" ref="eric5.Preferences.ConfigurationPages.ShellPage.html#ShellPage.on_monospacedFontButton_clicked" />
       <keyword name="ShellPage.polishPage" id="ShellPage.polishPage" ref="eric5.Preferences.ConfigurationPages.ShellPage.html#ShellPage.polishPage" />
       <keyword name="ShellPage.save" id="ShellPage.save" ref="eric5.Preferences.ConfigurationPages.ShellPage.html#ShellPage.save" />
+      <keyword name="MasterPasswordEntryDialog (Module)" id="MasterPasswordEntryDialog (Module)" ref="eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.html" />
+      <keyword name="MasterPasswordEntryDialog" id="MasterPasswordEntryDialog" ref="eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.html#MasterPasswordEntryDialog" />
+      <keyword name="MasterPasswordEntryDialog (Constructor)" id="MasterPasswordEntryDialog (Constructor)" ref="eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.html#MasterPasswordEntryDialog.__init__" />
+      <keyword name="MasterPasswordEntryDialog.__updateUI" id="MasterPasswordEntryDialog.__updateUI" ref="eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.html#MasterPasswordEntryDialog.__updateUI" />
+      <keyword name="MasterPasswordEntryDialog.getCurrentPassword" id="MasterPasswordEntryDialog.getCurrentPassword" ref="eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.html#MasterPasswordEntryDialog.getCurrentPassword" />
+      <keyword name="MasterPasswordEntryDialog.getMasterPassword" id="MasterPasswordEntryDialog.getMasterPassword" ref="eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.html#MasterPasswordEntryDialog.getMasterPassword" />
+      <keyword name="MasterPasswordEntryDialog.on_currentPasswordEdit_textChanged" id="MasterPasswordEntryDialog.on_currentPasswordEdit_textChanged" ref="eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.html#MasterPasswordEntryDialog.on_currentPasswordEdit_textChanged" />
+      <keyword name="MasterPasswordEntryDialog.on_newPasswordAgainEdit_textChanged" id="MasterPasswordEntryDialog.on_newPasswordAgainEdit_textChanged" ref="eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.html#MasterPasswordEntryDialog.on_newPasswordAgainEdit_textChanged" />
+      <keyword name="MasterPasswordEntryDialog.on_newPasswordEdit_textChanged" id="MasterPasswordEntryDialog.on_newPasswordEdit_textChanged" ref="eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.html#MasterPasswordEntryDialog.on_newPasswordEdit_textChanged" />
       <keyword name="DebuggerGeneralPage (Module)" id="DebuggerGeneralPage (Module)" ref="eric5.Preferences.ConfigurationPages.DebuggerGeneralPage.html" />
       <keyword name="DebuggerGeneralPage" id="DebuggerGeneralPage" ref="eric5.Preferences.ConfigurationPages.DebuggerGeneralPage.html#DebuggerGeneralPage" />
       <keyword name="create" id="create" ref="eric5.Preferences.ConfigurationPages.DebuggerGeneralPage.html#create" />
@@ -8198,6 +8280,13 @@
       <keyword name="create" id="create" ref="eric5.Preferences.ConfigurationPages.ApplicationPage.html#create" />
       <keyword name="ApplicationPage (Constructor)" id="ApplicationPage (Constructor)" ref="eric5.Preferences.ConfigurationPages.ApplicationPage.html#ApplicationPage.__init__" />
       <keyword name="ApplicationPage.save" id="ApplicationPage.save" ref="eric5.Preferences.ConfigurationPages.ApplicationPage.html#ApplicationPage.save" />
+      <keyword name="SecurityPage (Module)" id="SecurityPage (Module)" ref="eric5.Preferences.ConfigurationPages.SecurityPage.html" />
+      <keyword name="SecurityPage" id="SecurityPage" ref="eric5.Preferences.ConfigurationPages.SecurityPage.html#SecurityPage" />
+      <keyword name="create" id="create" ref="eric5.Preferences.ConfigurationPages.SecurityPage.html#create" />
+      <keyword name="SecurityPage (Constructor)" id="SecurityPage (Constructor)" ref="eric5.Preferences.ConfigurationPages.SecurityPage.html#SecurityPage.__init__" />
+      <keyword name="SecurityPage.on_masterPasswordButton_clicked" id="SecurityPage.on_masterPasswordButton_clicked" ref="eric5.Preferences.ConfigurationPages.SecurityPage.html#SecurityPage.on_masterPasswordButton_clicked" />
+      <keyword name="SecurityPage.on_masterPasswordCheckBox_clicked" id="SecurityPage.on_masterPasswordCheckBox_clicked" ref="eric5.Preferences.ConfigurationPages.SecurityPage.html#SecurityPage.on_masterPasswordCheckBox_clicked" />
+      <keyword name="SecurityPage.save" id="SecurityPage.save" ref="eric5.Preferences.ConfigurationPages.SecurityPage.html#SecurityPage.save" />
       <keyword name="EditorSpellCheckingPage (Module)" id="EditorSpellCheckingPage (Module)" ref="eric5.Preferences.ConfigurationPages.EditorSpellCheckingPage.html" />
       <keyword name="EditorSpellCheckingPage" id="EditorSpellCheckingPage" ref="eric5.Preferences.ConfigurationPages.EditorSpellCheckingPage.html#EditorSpellCheckingPage" />
       <keyword name="create" id="create" ref="eric5.Preferences.ConfigurationPages.EditorSpellCheckingPage.html#create" />
@@ -10967,6 +11056,7 @@
       <file>eric5.E5Gui.E5ModelMenu.html</file>
       <file>eric5.E5Gui.E5ModelToolBar.html</file>
       <file>eric5.E5Gui.E5PassivePopup.html</file>
+      <file>eric5.E5Gui.E5PasswordMeter.html</file>
       <file>eric5.E5Gui.E5SideBar.html</file>
       <file>eric5.E5Gui.E5SingleApplication.html</file>
       <file>eric5.E5Gui.E5SqueezeLabels.html</file>
@@ -11336,6 +11426,7 @@
       <file>eric5.Preferences.ConfigurationPages.IconsPage.html</file>
       <file>eric5.Preferences.ConfigurationPages.IconsPreviewDialog.html</file>
       <file>eric5.Preferences.ConfigurationPages.InterfacePage.html</file>
+      <file>eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.html</file>
       <file>eric5.Preferences.ConfigurationPages.MultiProjectPage.html</file>
       <file>eric5.Preferences.ConfigurationPages.NetworkPage.html</file>
       <file>eric5.Preferences.ConfigurationPages.PluginManagerPage.html</file>
@@ -11345,6 +11436,7 @@
       <file>eric5.Preferences.ConfigurationPages.Py3FlakesPage.html</file>
       <file>eric5.Preferences.ConfigurationPages.PythonPage.html</file>
       <file>eric5.Preferences.ConfigurationPages.QtPage.html</file>
+      <file>eric5.Preferences.ConfigurationPages.SecurityPage.html</file>
       <file>eric5.Preferences.ConfigurationPages.ShellPage.html</file>
       <file>eric5.Preferences.ConfigurationPages.TasksPage.html</file>
       <file>eric5.Preferences.ConfigurationPages.TemplatesPage.html</file>
@@ -11487,9 +11579,13 @@
       <file>eric5.Utilities.ClassBrowsers.pyclbr.html</file>
       <file>eric5.Utilities.ClassBrowsers.rbclbr.html</file>
       <file>eric5.Utilities.ModuleParser.html</file>
+      <file>eric5.Utilities.PasswordChecker.html</file>
       <file>eric5.Utilities.SingleApplication.html</file>
       <file>eric5.Utilities.Startup.html</file>
       <file>eric5.Utilities.__init__.html</file>
+      <file>eric5.Utilities.crypto.__init__.html</file>
+      <file>eric5.Utilities.crypto.py3AES.html</file>
+      <file>eric5.Utilities.crypto.py3PBKDF2.html</file>
       <file>eric5.Utilities.py3flakes.checker.html</file>
       <file>eric5.Utilities.py3flakes.messages.html</file>
       <file>eric5.Utilities.uic.html</file>
@@ -11617,6 +11713,7 @@
       <file>index-eric5.Tools.html</file>
       <file>index-eric5.UI.html</file>
       <file>index-eric5.Utilities.ClassBrowsers.html</file>
+      <file>index-eric5.Utilities.crypto.html</file>
       <file>index-eric5.Utilities.html</file>
       <file>index-eric5.Utilities.py3flakes.html</file>
       <file>index-eric5.UtilitiesPython2.html</file>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Documentation/Source/eric5.E5Gui.E5PasswordMeter.html	Sun Jun 19 15:19:46 2011 +0200
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'
+'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html><head>
+<title>eric5.E5Gui.E5PasswordMeter</title>
+<style>
+body {
+    background: #EDECE6;
+    margin: 0em 1em 10em 1em;
+    color: black;
+}
+
+h1 { color: white; background: #85774A; }
+h2 { color: white; background: #85774A; }
+h3 { color: white; background: #9D936E; }
+h4 { color: white; background: #9D936E; }
+    
+a { color: #BA6D36; }
+
+</style>
+</head>
+<body><a NAME="top" ID="top"></a>
+<h1>eric5.E5Gui.E5PasswordMeter</h1>
+<p>
+Module implementing a custom widget indicating the strength of a password.
+</p>
+<h3>Global Attributes</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+<table>
+<tr>
+<td><a href="#E5PasswordMeter">E5PasswordMeter</a></td>
+<td>Class implementing a custom widget indicating the strength of a password.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr /><hr />
+<a NAME="E5PasswordMeter" ID="E5PasswordMeter"></a>
+<h2>E5PasswordMeter</h2>
+<p>
+    Class implementing a custom widget indicating the strength of a password.
+</p>
+<h3>Derived from</h3>
+QProgressBar
+<h3>Class Attributes</h3>
+<table>
+<tr><td>app</td></tr><tr><td>meter</td></tr>
+</table>
+<h3>Methods</h3>
+<table>
+<tr>
+<td><a href="#E5PasswordMeter.__init__">E5PasswordMeter</a></td>
+<td>Constructor</td>
+</tr><tr>
+<td><a href="#E5PasswordMeter.checkPasswordStrength">checkPasswordStrength</a></td>
+<td>Public slot to check the password strength and update the progress bar accordingly.</td>
+</tr><tr>
+<td><a href="#E5PasswordMeter.setMaximum">setMaximum</a></td>
+<td>Public method to set the maximum value.</td>
+</tr><tr>
+<td><a href="#E5PasswordMeter.setMinimum">setMinimum</a></td>
+<td>Public method to set the minimal value.</td>
+</tr><tr>
+<td><a href="#E5PasswordMeter.setValue">setValue</a></td>
+<td>Public method to set the value.</td>
+</tr>
+</table>
+<a NAME="E5PasswordMeter.__init__" ID="E5PasswordMeter.__init__"></a>
+<h4>E5PasswordMeter (Constructor)</h4>
+<b>E5PasswordMeter</b>(<i>parent=None</i>)
+<p>
+        Constructor
+</p><dl>
+<dt><i>parent</i></dt>
+<dd>
+reference to the parent widget (QWidget)
+</dd>
+</dl><a NAME="E5PasswordMeter.checkPasswordStrength" ID="E5PasswordMeter.checkPasswordStrength"></a>
+<h4>E5PasswordMeter.checkPasswordStrength</h4>
+<b>checkPasswordStrength</b>(<i>password</i>)
+<p>
+        Public slot to check the password strength and update the
+        progress bar accordingly.
+</p><dl>
+<dt><i>password</i></dt>
+<dd>
+password to be checked (string)
+</dd>
+</dl><a NAME="E5PasswordMeter.setMaximum" ID="E5PasswordMeter.setMaximum"></a>
+<h4>E5PasswordMeter.setMaximum</h4>
+<b>setMaximum</b>(<i>value</i>)
+<p>
+        Public method to set the maximum value.
+</p><p>
+        Overwritten to do nothing.
+</p><a NAME="E5PasswordMeter.setMinimum" ID="E5PasswordMeter.setMinimum"></a>
+<h4>E5PasswordMeter.setMinimum</h4>
+<b>setMinimum</b>(<i>value</i>)
+<p>
+        Public method to set the minimal value.
+</p><p>
+        Overwritten to do nothing.
+</p><a NAME="E5PasswordMeter.setValue" ID="E5PasswordMeter.setValue"></a>
+<h4>E5PasswordMeter.setValue</h4>
+<b>setValue</b>(<i>value</i>)
+<p>
+        Public method to set the value.
+</p><p>
+        Overwritten to do nothing.
+</p>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- a/Documentation/Source/eric5.Helpviewer.HelpWindow.html	Thu Jun 16 16:29:27 2011 +0200
+++ b/Documentation/Source/eric5.Helpviewer.HelpWindow.html	Sun Jun 19 15:19:46 2011 +0200
@@ -367,6 +367,9 @@
 <td><a href="#HelpWindow.mainWindow">mainWindow</a></td>
 <td>Class method to get a reference to the main window.</td>
 </tr><tr>
+<td><a href="#HelpWindow.masterPasswordChanged">masterPasswordChanged</a></td>
+<td>Public slot to handle the change of the master password.</td>
+</tr><tr>
 <td><a href="#HelpWindow.networkAccessManager">networkAccessManager</a></td>
 <td>Class method to get a reference to the network access manager.</td>
 </tr><tr>
@@ -1149,6 +1152,19 @@
 <dd>
 reference to the main window (HelpWindow)
 </dd>
+</dl><a NAME="HelpWindow.masterPasswordChanged" ID="HelpWindow.masterPasswordChanged"></a>
+<h4>HelpWindow.masterPasswordChanged</h4>
+<b>masterPasswordChanged</b>(<i>oldPassword, newPassword</i>)
+<p>
+        Public slot to handle the change of the master password.
+</p><dl>
+<dt><i>oldPassword</i></dt>
+<dd>
+current master password (string)
+</dd><dt><i>newPassword</i></dt>
+<dd>
+new master password (string)
+</dd>
 </dl><a NAME="HelpWindow.networkAccessManager" ID="HelpWindow.networkAccessManager"></a>
 <h4>HelpWindow.networkAccessManager</h4>
 <b>networkAccessManager</b>(<i></i>)
--- a/Documentation/Source/eric5.Helpviewer.Passwords.PasswordManager.html	Thu Jun 16 16:29:27 2011 +0200
+++ b/Documentation/Source/eric5.Helpviewer.Passwords.PasswordManager.html	Sun Jun 19 15:19:46 2011 +0200
@@ -171,6 +171,9 @@
 <td><a href="#PasswordManager.getLogin">getLogin</a></td>
 <td>Public method to get the login credentials.</td>
 </tr><tr>
+<td><a href="#PasswordManager.masterPasswordChanged">masterPasswordChanged</a></td>
+<td>Public slot to handle the change of the master password.</td>
+</tr><tr>
 <td><a href="#PasswordManager.post">post</a></td>
 <td>Public method to check, if the data to be sent contains login data.</td>
 </tr><tr>
@@ -326,6 +329,19 @@
 <dd>
 tuple containing the user name (string) and password (string)
 </dd>
+</dl><a NAME="PasswordManager.masterPasswordChanged" ID="PasswordManager.masterPasswordChanged"></a>
+<h4>PasswordManager.masterPasswordChanged</h4>
+<b>masterPasswordChanged</b>(<i>oldPassword, newPassword</i>)
+<p>
+        Public slot to handle the change of the master password.
+</p><dl>
+<dt><i>oldPassword</i></dt>
+<dd>
+current master password (string)
+</dd><dt><i>newPassword</i></dt>
+<dd>
+new master password (string)
+</dd>
 </dl><a NAME="PasswordManager.post" ID="PasswordManager.post"></a>
 <h4>PasswordManager.post</h4>
 <b>post</b>(<i>request, data</i>)
--- a/Documentation/Source/eric5.Preferences.ConfigurationDialog.html	Thu Jun 16 16:29:27 2011 +0200
+++ b/Documentation/Source/eric5.Preferences.ConfigurationDialog.html	Sun Jun 19 15:19:46 2011 +0200
@@ -55,7 +55,11 @@
     Class for the dialog variant.
 </p><h4>Signals</h4>
 <dl>
-<dt>preferencesChanged()</dt>
+<dt>masterPasswordChanged(str, str)</dt>
+<dd>
+emitted after the master
+        password has been changed with the old and the new password
+</dd><dt>preferencesChanged()</dt>
 <dd>
 emitted after settings have been changed
 </dd>
@@ -72,6 +76,9 @@
 <td><a href="#ConfigurationDialog.__init__">ConfigurationDialog</a></td>
 <td>Constructor</td>
 </tr><tr>
+<td><a href="#ConfigurationDialog.__masterPasswordChanged">__masterPasswordChanged</a></td>
+<td>Private slot to handle the change of the master password.</td>
+</tr><tr>
 <td><a href="#ConfigurationDialog.__preferencesChanged">__preferencesChanged</a></td>
 <td>Private slot to handle a change of the preferences.</td>
 </tr><tr>
@@ -109,6 +116,19 @@
 mode of the configuration dialog
             (DefaultMode, HelpBrowserMode, TrayStarterMode)
 </dd>
+</dl><a NAME="ConfigurationDialog.__masterPasswordChanged" ID="ConfigurationDialog.__masterPasswordChanged"></a>
+<h4>ConfigurationDialog.__masterPasswordChanged</h4>
+<b>__masterPasswordChanged</b>(<i>oldPassword, newPassword</i>)
+<p>
+        Private slot to handle the change of the master password.
+</p><dl>
+<dt><i>oldPassword</i></dt>
+<dd>
+current master password (string)
+</dd><dt><i>newPassword</i></dt>
+<dd>
+new master password (string)
+</dd>
 </dl><a NAME="ConfigurationDialog.__preferencesChanged" ID="ConfigurationDialog.__preferencesChanged"></a>
 <h4>ConfigurationDialog.__preferencesChanged</h4>
 <b>__preferencesChanged</b>(<i></i>)
@@ -201,7 +221,11 @@
     Class implementing a dialog for the configuration of eric5.
 </p><h4>Signals</h4>
 <dl>
-<dt>preferencesChanged()</dt>
+<dt>masterPasswordChanged(str, str)</dt>
+<dd>
+emitted after the master
+        password has been changed with the old and the new password
+</dd><dt>preferencesChanged()</dt>
 <dd>
 emitted after settings have been changed
 </dd>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Documentation/Source/eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.html	Sun Jun 19 15:19:46 2011 +0200
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'
+'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html><head>
+<title>eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog</title>
+<style>
+body {
+    background: #EDECE6;
+    margin: 0em 1em 10em 1em;
+    color: black;
+}
+
+h1 { color: white; background: #85774A; }
+h2 { color: white; background: #85774A; }
+h3 { color: white; background: #9D936E; }
+h4 { color: white; background: #9D936E; }
+    
+a { color: #BA6D36; }
+
+</style>
+</head>
+<body><a NAME="top" ID="top"></a>
+<h1>eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog</h1>
+<p>
+Module implementing a dialog to enter or change the master password.
+</p>
+<h3>Global Attributes</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+<table>
+<tr>
+<td><a href="#MasterPasswordEntryDialog">MasterPasswordEntryDialog</a></td>
+<td>Class implementing a dialog to enter or change the master password.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr /><hr />
+<a NAME="MasterPasswordEntryDialog" ID="MasterPasswordEntryDialog"></a>
+<h2>MasterPasswordEntryDialog</h2>
+<p>
+    Class implementing a dialog to enter or change the master password.
+</p>
+<h3>Derived from</h3>
+QDialog, Ui_MasterPasswordEntryDialog
+<h3>Class Attributes</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+<table>
+<tr>
+<td><a href="#MasterPasswordEntryDialog.__init__">MasterPasswordEntryDialog</a></td>
+<td>Constructor</td>
+</tr><tr>
+<td><a href="#MasterPasswordEntryDialog.__updateUI">__updateUI</a></td>
+<td>Private slot to update the variable parts of the UI.</td>
+</tr><tr>
+<td><a href="#MasterPasswordEntryDialog.getCurrentPassword">getCurrentPassword</a></td>
+<td>Public method to get the current master password.</td>
+</tr><tr>
+<td><a href="#MasterPasswordEntryDialog.getMasterPassword">getMasterPassword</a></td>
+<td>Public method to get the new master password.</td>
+</tr><tr>
+<td><a href="#MasterPasswordEntryDialog.on_currentPasswordEdit_textChanged">on_currentPasswordEdit_textChanged</a></td>
+<td>Private slot to handle changes of the current password.</td>
+</tr><tr>
+<td><a href="#MasterPasswordEntryDialog.on_newPasswordAgainEdit_textChanged">on_newPasswordAgainEdit_textChanged</a></td>
+<td>Private slot to handle changes of the new again password.</td>
+</tr><tr>
+<td><a href="#MasterPasswordEntryDialog.on_newPasswordEdit_textChanged">on_newPasswordEdit_textChanged</a></td>
+<td>Private slot to handle changes of the new password.</td>
+</tr>
+</table>
+<a NAME="MasterPasswordEntryDialog.__init__" ID="MasterPasswordEntryDialog.__init__"></a>
+<h4>MasterPasswordEntryDialog (Constructor)</h4>
+<b>MasterPasswordEntryDialog</b>(<i>oldPasswordHash, parent=None</i>)
+<p>
+        Constructor
+</p><dl>
+<dt><i>oldPasswordHash</i></dt>
+<dd>
+hash of the current password (string)
+</dd><dt><i>parent</i></dt>
+<dd>
+reference to the parent widget (QWidget)
+</dd>
+</dl><a NAME="MasterPasswordEntryDialog.__updateUI" ID="MasterPasswordEntryDialog.__updateUI"></a>
+<h4>MasterPasswordEntryDialog.__updateUI</h4>
+<b>__updateUI</b>(<i></i>)
+<p>
+        Private slot to update the variable parts of the UI.
+</p><a NAME="MasterPasswordEntryDialog.getCurrentPassword" ID="MasterPasswordEntryDialog.getCurrentPassword"></a>
+<h4>MasterPasswordEntryDialog.getCurrentPassword</h4>
+<b>getCurrentPassword</b>(<i></i>)
+<p>
+        Public method to get the current master password.
+</p><a NAME="MasterPasswordEntryDialog.getMasterPassword" ID="MasterPasswordEntryDialog.getMasterPassword"></a>
+<h4>MasterPasswordEntryDialog.getMasterPassword</h4>
+<b>getMasterPassword</b>(<i></i>)
+<p>
+        Public method to get the new master password.
+</p><a NAME="MasterPasswordEntryDialog.on_currentPasswordEdit_textChanged" ID="MasterPasswordEntryDialog.on_currentPasswordEdit_textChanged"></a>
+<h4>MasterPasswordEntryDialog.on_currentPasswordEdit_textChanged</h4>
+<b>on_currentPasswordEdit_textChanged</b>(<i>txt</i>)
+<p>
+        Private slot to handle changes of the current password.
+</p><dl>
+<dt><i>txt</i></dt>
+<dd>
+content of the edit widget (string)
+</dd>
+</dl><a NAME="MasterPasswordEntryDialog.on_newPasswordAgainEdit_textChanged" ID="MasterPasswordEntryDialog.on_newPasswordAgainEdit_textChanged"></a>
+<h4>MasterPasswordEntryDialog.on_newPasswordAgainEdit_textChanged</h4>
+<b>on_newPasswordAgainEdit_textChanged</b>(<i>txt</i>)
+<p>
+        Private slot to handle changes of the new again password.
+</p><dl>
+<dt><i>txt</i></dt>
+<dd>
+content of the edit widget (string)
+</dd>
+</dl><a NAME="MasterPasswordEntryDialog.on_newPasswordEdit_textChanged" ID="MasterPasswordEntryDialog.on_newPasswordEdit_textChanged"></a>
+<h4>MasterPasswordEntryDialog.on_newPasswordEdit_textChanged</h4>
+<b>on_newPasswordEdit_textChanged</b>(<i>txt</i>)
+<p>
+        Private slot to handle changes of the new password.
+</p><dl>
+<dt><i>txt</i></dt>
+<dd>
+content of the edit widget (string)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- a/Documentation/Source/eric5.Preferences.ConfigurationPages.NetworkPage.html	Thu Jun 16 16:29:27 2011 +0200
+++ b/Documentation/Source/eric5.Preferences.ConfigurationPages.NetworkPage.html	Sun Jun 19 15:19:46 2011 +0200
@@ -60,6 +60,9 @@
 <td><a href="#NetworkPage.__init__">NetworkPage</a></td>
 <td>Constructor</td>
 </tr><tr>
+<td><a href="#NetworkPage.on_clearProxyPasswordsButton_clicked">on_clearProxyPasswordsButton_clicked</a></td>
+<td>Private slot to clear the saved proxy passwords.</td>
+</tr><tr>
 <td><a href="#NetworkPage.on_downloadDirButton_clicked">on_downloadDirButton_clicked</a></td>
 <td>Private slot to handle the directory selection via dialog.</td>
 </tr><tr>
@@ -72,6 +75,11 @@
 <b>NetworkPage</b>(<i></i>)
 <p>
         Constructor
+</p><a NAME="NetworkPage.on_clearProxyPasswordsButton_clicked" ID="NetworkPage.on_clearProxyPasswordsButton_clicked"></a>
+<h4>NetworkPage.on_clearProxyPasswordsButton_clicked</h4>
+<b>on_clearProxyPasswordsButton_clicked</b>(<i></i>)
+<p>
+        Private slot to clear the saved proxy passwords.
 </p><a NAME="NetworkPage.on_downloadDirButton_clicked" ID="NetworkPage.on_downloadDirButton_clicked"></a>
 <h4>NetworkPage.on_downloadDirButton_clicked</h4>
 <b>on_downloadDirButton_clicked</b>(<i></i>)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Documentation/Source/eric5.Preferences.ConfigurationPages.SecurityPage.html	Sun Jun 19 15:19:46 2011 +0200
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'
+'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html><head>
+<title>eric5.Preferences.ConfigurationPages.SecurityPage</title>
+<style>
+body {
+    background: #EDECE6;
+    margin: 0em 1em 10em 1em;
+    color: black;
+}
+
+h1 { color: white; background: #85774A; }
+h2 { color: white; background: #85774A; }
+h3 { color: white; background: #9D936E; }
+h4 { color: white; background: #9D936E; }
+    
+a { color: #BA6D36; }
+
+</style>
+</head>
+<body><a NAME="top" ID="top"></a>
+<h1>eric5.Preferences.ConfigurationPages.SecurityPage</h1>
+<p>
+Module implementing the Security configuration page.
+</p>
+<h3>Global Attributes</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+<table>
+<tr>
+<td><a href="#SecurityPage">SecurityPage</a></td>
+<td>Class implementing the Security configuration page.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+<table>
+<tr>
+<td><a href="#create">create</a></td>
+<td>Module function to create the configuration page.</td>
+</tr>
+</table>
+<hr /><hr />
+<a NAME="SecurityPage" ID="SecurityPage"></a>
+<h2>SecurityPage</h2>
+<p>
+    Class implementing the Security configuration page.
+</p>
+<h3>Derived from</h3>
+ConfigurationPageBase, Ui_SecurityPage
+<h3>Class Attributes</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+<table>
+<tr>
+<td><a href="#SecurityPage.__init__">SecurityPage</a></td>
+<td>Constructor</td>
+</tr><tr>
+<td><a href="#SecurityPage.on_masterPasswordButton_clicked">on_masterPasswordButton_clicked</a></td>
+<td>Private slot to change the master password.</td>
+</tr><tr>
+<td><a href="#SecurityPage.on_masterPasswordCheckBox_clicked">on_masterPasswordCheckBox_clicked</a></td>
+<td>Private slot to handle the use of a master password.</td>
+</tr><tr>
+<td><a href="#SecurityPage.save">save</a></td>
+<td>Public slot to save the Help Viewers configuration.</td>
+</tr>
+</table>
+<a NAME="SecurityPage.__init__" ID="SecurityPage.__init__"></a>
+<h4>SecurityPage (Constructor)</h4>
+<b>SecurityPage</b>(<i>configDialog</i>)
+<p>
+        Constructor
+</p><dl>
+<dt><i>configDialog</i></dt>
+<dd>
+reference to the configuration dialog (ConfigurationDialog)
+</dd>
+</dl><a NAME="SecurityPage.on_masterPasswordButton_clicked" ID="SecurityPage.on_masterPasswordButton_clicked"></a>
+<h4>SecurityPage.on_masterPasswordButton_clicked</h4>
+<b>on_masterPasswordButton_clicked</b>(<i></i>)
+<p>
+        Private slot to change the master password.
+</p><a NAME="SecurityPage.on_masterPasswordCheckBox_clicked" ID="SecurityPage.on_masterPasswordCheckBox_clicked"></a>
+<h4>SecurityPage.on_masterPasswordCheckBox_clicked</h4>
+<b>on_masterPasswordCheckBox_clicked</b>(<i>checked</i>)
+<p>
+        Private slot to handle the use of a master password.
+</p><dl>
+<dt><i>checked</i></dt>
+<dd>
+flag indicating the state of the check box (boolean)
+</dd>
+</dl><a NAME="SecurityPage.save" ID="SecurityPage.save"></a>
+<h4>SecurityPage.save</h4>
+<b>save</b>(<i></i>)
+<p>
+        Public slot to save the Help Viewers configuration.
+</p>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="create" ID="create"></a>
+<h2>create</h2>
+<b>create</b>(<i>dlg</i>)
+<p>
+    Module function to create the configuration page.
+</p><dl>
+<dt><i>dlg</i></dt>
+<dd>
+reference to the configuration dialog
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- a/Documentation/Source/eric5.Preferences.__init__.html	Thu Jun 16 16:29:27 2011 +0200
+++ b/Documentation/Source/eric5.Preferences.__init__.html	Sun Jun 19 15:19:46 2011 +0200
@@ -47,6 +47,9 @@
 <h3>Functions</h3>
 <table>
 <tr>
+<td><a href="#convertPasswords">convertPasswords</a></td>
+<td>Module function to convert all passwords.</td>
+</tr><tr>
 <td><a href="#exportPreferences">exportPreferences</a></td>
 <td>Module function to export the current preferences.</td>
 </tr><tr>
@@ -355,6 +358,25 @@
 
 <div align="right"><a href="#top">Up</a></div>
 <hr /><hr />
+<a NAME="convertPasswords" ID="convertPasswords"></a>
+<h2>convertPasswords</h2>
+<b>convertPasswords</b>(<i>oldPassword, newPassword, prefClass=Prefs</i>)
+<p>
+    Module function to convert all passwords.
+</p><dl>
+<dt><i>oldPassword</i></dt>
+<dd>
+current master password (string)
+</dd><dt><i>newPassword</i></dt>
+<dd>
+new master password (string)
+</dd><dt><i>prefClass</i></dt>
+<dd>
+preferences class used as the storage area
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
 <a NAME="exportPreferences" ID="exportPreferences"></a>
 <h2>exportPreferences</h2>
 <b>exportPreferences</b>(<i>prefClass=Prefs</i>)
--- a/Documentation/Source/eric5.UI.UserInterface.html	Thu Jun 16 16:29:27 2011 +0200
+++ b/Documentation/Source/eric5.UI.UserInterface.html	Sun Jun 19 15:19:46 2011 +0200
@@ -142,6 +142,10 @@
 </dd><dt>appendStdout(str)</dt>
 <dd>
 emitted to write data to stdout logger
+</dd><dt>masterPasswordChanged(str, str)</dt>
+<dd>
+emitted after the master
+            password has been changed with the old and the new password
 </dd><dt>preferencesChanged()</dt>
 <dd>
 emitted after the preferences were changed
@@ -349,6 +353,9 @@
 <td><a href="#UserInterface.__linguist4">__linguist4</a></td>
 <td>Private slot to start the Qt-Linguist 4 executable.</td>
 </tr><tr>
+<td><a href="#UserInterface.__masterPasswordChanged">__masterPasswordChanged</a></td>
+<td>Private slot to handle the change of the master password.</td>
+</tr><tr>
 <td><a href="#UserInterface.__newProject">__newProject</a></td>
 <td>Private slot to handle the NewProject signal.</td>
 </tr><tr>
@@ -1175,6 +1182,19 @@
 <dd>
 filename of the translation file to be opened
 </dd>
+</dl><a NAME="UserInterface.__masterPasswordChanged" ID="UserInterface.__masterPasswordChanged"></a>
+<h4>UserInterface.__masterPasswordChanged</h4>
+<b>__masterPasswordChanged</b>(<i>oldPassword, newPassword</i>)
+<p>
+        Private slot to handle the change of the master password.
+</p><dl>
+<dt><i>oldPassword</i></dt>
+<dd>
+current master password (string)
+</dd><dt><i>newPassword</i></dt>
+<dd>
+new master password (string)
+</dd>
 </dl><a NAME="UserInterface.__newProject" ID="UserInterface.__newProject"></a>
 <h4>UserInterface.__newProject</h4>
 <b>__newProject</b>(<i></i>)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Documentation/Source/eric5.Utilities.PasswordChecker.html	Sun Jun 19 15:19:46 2011 +0200
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'
+'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html><head>
+<title>eric5.Utilities.PasswordChecker</title>
+<style>
+body {
+    background: #EDECE6;
+    margin: 0em 1em 10em 1em;
+    color: black;
+}
+
+h1 { color: white; background: #85774A; }
+h2 { color: white; background: #85774A; }
+h3 { color: white; background: #9D936E; }
+h4 { color: white; background: #9D936E; }
+    
+a { color: #BA6D36; }
+
+</style>
+</head>
+<body><a NAME="top" ID="top"></a>
+<h1>eric5.Utilities.PasswordChecker</h1>
+<p>
+Module implementing a checker for password strength
+</p>
+<h3>Global Attributes</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+<table>
+<tr>
+<td><a href="#PasswordChecker">PasswordChecker</a></td>
+<td>Class implementing a checker for password strength.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr /><hr />
+<a NAME="PasswordChecker" ID="PasswordChecker"></a>
+<h2>PasswordChecker</h2>
+<p>
+    Class implementing a checker for password strength.
+</p>
+<h3>Derived from</h3>
+object
+<h3>Class Attributes</h3>
+<table>
+<tr><td>Complexity_Good</td></tr><tr><td>Complexity_Strong</td></tr><tr><td>Complexity_VeryStrong</td></tr><tr><td>Complexity_VeryWeak</td></tr><tr><td>Complexity_Weak</td></tr><tr><td>Status_Exceeded</td></tr><tr><td>Status_Failed</td></tr><tr><td>Status_Passed</td></tr>
+</table>
+<h3>Methods</h3>
+<table>
+<tr>
+<td><a href="#PasswordChecker.__init__">PasswordChecker</a></td>
+<td>Constructor</td>
+</tr><tr>
+<td><a href="#PasswordChecker.__determineBinaryStatus">__determineBinaryStatus</a></td>
+<td>Private method to determine a binary status.</td>
+</tr><tr>
+<td><a href="#PasswordChecker.__determineStatus">__determineStatus</a></td>
+<td>Private method to determine the status.</td>
+</tr><tr>
+<td><a href="#PasswordChecker.__strReverse">__strReverse</a></td>
+<td>Private method to reverse a string.</td>
+</tr><tr>
+<td><a href="#PasswordChecker.checkPassword">checkPassword</a></td>
+<td>Public method to check a given password.</td>
+</tr>
+</table>
+<a NAME="PasswordChecker.__init__" ID="PasswordChecker.__init__"></a>
+<h4>PasswordChecker (Constructor)</h4>
+<b>PasswordChecker</b>(<i></i>)
+<p>
+        Constructor
+</p><a NAME="PasswordChecker.__determineBinaryStatus" ID="PasswordChecker.__determineBinaryStatus"></a>
+<h4>PasswordChecker.__determineBinaryStatus</h4>
+<b>__determineBinaryStatus</b>(<i>value</i>)
+<p>
+        Private method to determine a binary status.
+</p><dl>
+<dt><i>value</i></dt>
+<dd>
+value to check (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+status (Status_Failed, Status_Passed)
+</dd>
+</dl><a NAME="PasswordChecker.__determineStatus" ID="PasswordChecker.__determineStatus"></a>
+<h4>PasswordChecker.__determineStatus</h4>
+<b>__determineStatus</b>(<i>value</i>)
+<p>
+        Private method to determine the status.
+</p><dl>
+<dt><i>value</i></dt>
+<dd>
+value to check (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+status (Status_Failed, Status_Passed, Status_Exceeded)
+</dd>
+</dl><a NAME="PasswordChecker.__strReverse" ID="PasswordChecker.__strReverse"></a>
+<h4>PasswordChecker.__strReverse</h4>
+<b>__strReverse</b>(<i>string</i>)
+<p>
+        Private method to reverse a string.
+</p><dl>
+<dt><i>string</i></dt>
+<dd>
+string to be reversed (string)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+reversed string (string)
+</dd>
+</dl><a NAME="PasswordChecker.checkPassword" ID="PasswordChecker.checkPassword"></a>
+<h4>PasswordChecker.checkPassword</h4>
+<b>checkPassword</b>(<i>password</i>)
+<p>
+        Public method to check a given password.
+</p><dl>
+<dt><i>password</i></dt>
+<dd>
+password to be checked (string)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+indication for the password strength (Complexity_VeryWeak,
+            Complexity_Weak, Complexity_Good, Complexity_Strong,
+            Complexity_VeryStrong)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- a/Documentation/Source/eric5.Utilities.__init__.html	Thu Jun 16 16:29:27 2011 +0200
+++ b/Documentation/Source/eric5.Utilities.__init__.html	Sun Jun 19 15:19:46 2011 +0200
@@ -185,12 +185,6 @@
 <td><a href="#prepareQtMacBundle">prepareQtMacBundle</a></td>
 <td>Module function for starting Qt tools that are Mac OS X bundles.</td>
 </tr><tr>
-<td><a href="#pwDecode">pwDecode</a></td>
-<td>Module function to decode a password.</td>
-</tr><tr>
-<td><a href="#pwEncode">pwEncode</a></td>
-<td>Module function to encode a password.</td>
-</tr><tr>
 <td><a href="#py2compile">py2compile</a></td>
 <td>Function to compile one Python 2 source file to Python 2 bytecode.</td>
 </tr><tr>
@@ -1215,42 +1209,6 @@
 </dl>
 <div align="right"><a href="#top">Up</a></div>
 <hr /><hr />
-<a NAME="pwDecode" ID="pwDecode"></a>
-<h2>pwDecode</h2>
-<b>pwDecode</b>(<i>epw</i>)
-<p>
-    Module function to decode a password.
-</p><dl>
-<dt><i>pw</i></dt>
-<dd>
-encoded password to decode (string)
-</dd>
-</dl><dl>
-<dt>Returns:</dt>
-<dd>
-decoded password (string)
-</dd>
-</dl>
-<div align="right"><a href="#top">Up</a></div>
-<hr /><hr />
-<a NAME="pwEncode" ID="pwEncode"></a>
-<h2>pwEncode</h2>
-<b>pwEncode</b>(<i>pw</i>)
-<p>
-    Module function to encode a password.
-</p><dl>
-<dt><i>pw</i></dt>
-<dd>
-password to encode (string)
-</dd>
-</dl><dl>
-<dt>Returns:</dt>
-<dd>
-encoded password (string)
-</dd>
-</dl>
-<div align="right"><a href="#top">Up</a></div>
-<hr /><hr />
 <a NAME="py2compile" ID="py2compile"></a>
 <h2>py2compile</h2>
 <b>py2compile</b>(<i>file, checkFlakes=False</i>)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Documentation/Source/eric5.Utilities.crypto.__init__.html	Sun Jun 19 15:19:46 2011 +0200
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'
+'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html><head>
+<title>eric5.Utilities.crypto.__init__</title>
+<style>
+body {
+    background: #EDECE6;
+    margin: 0em 1em 10em 1em;
+    color: black;
+}
+
+h1 { color: white; background: #85774A; }
+h2 { color: white; background: #85774A; }
+h3 { color: white; background: #9D936E; }
+h4 { color: white; background: #9D936E; }
+    
+a { color: #BA6D36; }
+
+</style>
+</head>
+<body><a NAME="top" ID="top"></a>
+<h1>eric5.Utilities.crypto.__init__</h1>
+<p>
+Package implementing cryptography related functionality.
+</p>
+<h3>Global Attributes</h3>
+<table>
+<tr><td>CryptoMarker</td></tr><tr><td>Delimiter</td></tr><tr><td>EncodeMarker</td></tr><tr><td>MasterPassword</td></tr>
+</table>
+<h3>Classes</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Functions</h3>
+<table>
+<tr>
+<td><a href="#__getMasterPassword">__getMasterPassword</a></td>
+<td>Private module function to get the password from the user.</td>
+</tr><tr>
+<td><a href="#changeRememberedMaster">changeRememberedMaster</a></td>
+<td>Module function to change the remembered master password.</td>
+</tr><tr>
+<td><a href="#pwConvert">pwConvert</a></td>
+<td>Module function to convert a plaintext password to the encoded form or vice versa.</td>
+</tr><tr>
+<td><a href="#pwDecode">pwDecode</a></td>
+<td>Module function to decode a password.</td>
+</tr><tr>
+<td><a href="#pwDecrypt">pwDecrypt</a></td>
+<td>Module function to decrypt a password.</td>
+</tr><tr>
+<td><a href="#pwEncode">pwEncode</a></td>
+<td>Module function to encode a password.</td>
+</tr><tr>
+<td><a href="#pwEncrypt">pwEncrypt</a></td>
+<td>Module function to encrypt a password.</td>
+</tr><tr>
+<td><a href="#pwRecode">pwRecode</a></td>
+<td>Module function to re-encode a password.</td>
+</tr><tr>
+<td><a href="#pwReencrypt">pwReencrypt</a></td>
+<td>Module function to re-encrypt a password.</td>
+</tr>
+</table>
+<hr /><hr />
+<a NAME="__getMasterPassword" ID="__getMasterPassword"></a>
+<h2>__getMasterPassword</h2>
+<b>__getMasterPassword</b>(<i></i>)
+<p>
+    Private module function to get the password from the user.
+</p>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="changeRememberedMaster" ID="changeRememberedMaster"></a>
+<h2>changeRememberedMaster</h2>
+<b>changeRememberedMaster</b>(<i>newPassword</i>)
+<p>
+    Module function to change the remembered master password.
+</p><dl>
+<dt><i>newPassword</i></dt>
+<dd>
+new password to be used (string)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="pwConvert" ID="pwConvert"></a>
+<h2>pwConvert</h2>
+<b>pwConvert</b>(<i>pw, encode=True</i>)
+<p>
+    Module function to convert a plaintext password to the encoded form or
+    vice versa.
+</p><p>
+    If there is an error, an empty code is returned for the encode function
+    or the given encoded password for the decode function.
+</p><dl>
+<dt><i>pw</i></dt>
+<dd>
+password to encode (string)
+</dd><dt><i>encode</i></dt>
+<dd>
+flag indicating an encode or decode function (boolean)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+encode or decoded password (string)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="pwDecode" ID="pwDecode"></a>
+<h2>pwDecode</h2>
+<b>pwDecode</b>(<i>epw</i>)
+<p>
+    Module function to decode a password.
+</p><dl>
+<dt><i>epw</i></dt>
+<dd>
+encoded password to decode (string)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+decoded password (string)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="pwDecrypt" ID="pwDecrypt"></a>
+<h2>pwDecrypt</h2>
+<b>pwDecrypt</b>(<i>epw, masterPW=None</i>)
+<p>
+    Module function to decrypt a password.
+</p><dl>
+<dt><i>epw</i></dt>
+<dd>
+hashed password to decrypt (string)
+</dd><dt><i>masterPW</i></dt>
+<dd>
+password to be used for encryption (string)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+decrypted password (string) and flag indicating
+        success (boolean)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="pwEncode" ID="pwEncode"></a>
+<h2>pwEncode</h2>
+<b>pwEncode</b>(<i>pw</i>)
+<p>
+    Module function to encode a password.
+</p><dl>
+<dt><i>pw</i></dt>
+<dd>
+password to encode (string)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+encoded password (string)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="pwEncrypt" ID="pwEncrypt"></a>
+<h2>pwEncrypt</h2>
+<b>pwEncrypt</b>(<i>pw, masterPW=None</i>)
+<p>
+    Module function to encrypt a password.
+</p><dl>
+<dt><i>pw</i></dt>
+<dd>
+password to encrypt (string)
+</dd><dt><i>masterPW</i></dt>
+<dd>
+password to be used for encryption (string)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+encrypted password (string) and flag indicating
+        success (boolean)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="pwRecode" ID="pwRecode"></a>
+<h2>pwRecode</h2>
+<b>pwRecode</b>(<i>epw, oldPassword, newPassword</i>)
+<p>
+    Module function to re-encode a password.
+</p><p>
+    In case of an error the encoded password is returned unchanged.
+</p><dl>
+<dt><i>epw</i></dt>
+<dd>
+encoded password to re-encode (string)
+</dd><dt><i>oldPassword</i></dt>
+<dd>
+password used to encode (string)
+</dd><dt><i>newPassword</i></dt>
+<dd>
+new password to be used (string)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+encoded password (string)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="pwReencrypt" ID="pwReencrypt"></a>
+<h2>pwReencrypt</h2>
+<b>pwReencrypt</b>(<i>epw, oldPassword, newPassword</i>)
+<p>
+    Module function to re-encrypt a password.
+</p><dl>
+<dt><i>epw</i></dt>
+<dd>
+hashed password to re-encrypt (string)
+</dd><dt><i>oldPassword</i></dt>
+<dd>
+password used to encrypt (string)
+</dd><dt><i>newPassword</i></dt>
+<dd>
+new password to be used (string)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+encrypted password (string) and flag indicating
+        success (boolean)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Documentation/Source/eric5.Utilities.crypto.py3AES.html	Sun Jun 19 15:19:46 2011 +0200
@@ -0,0 +1,710 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'
+'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html><head>
+<title>eric5.Utilities.crypto.py3AES</title>
+<style>
+body {
+    background: #EDECE6;
+    margin: 0em 1em 10em 1em;
+    color: black;
+}
+
+h1 { color: white; background: #85774A; }
+h2 { color: white; background: #85774A; }
+h3 { color: white; background: #9D936E; }
+h4 { color: white; background: #9D936E; }
+    
+a { color: #BA6D36; }
+
+</style>
+</head>
+<body><a NAME="top" ID="top"></a>
+<h1>eric5.Utilities.crypto.py3AES</h1>
+<p>
+Module implementing classes for encryption according
+Advanced Encryption Standard.
+</p>
+<h3>Global Attributes</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+<table>
+<tr>
+<td><a href="#AES">AES</a></td>
+<td>Class implementing the Advanced Encryption Standard algorithm.</td>
+</tr><tr>
+<td><a href="#AESModeOfOperation">AESModeOfOperation</a></td>
+<td>Class implementing the different AES mode of operations.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+<table>
+<tr>
+<td><a href="#append_PKCS7_padding">append_PKCS7_padding</a></td>
+<td>Function to pad the given data to a multiple of 16-bytes by PKCS7 padding.</td>
+</tr><tr>
+<td><a href="#decryptData">decryptData</a></td>
+<td>Module function to decrypt the given data with the given key.</td>
+</tr><tr>
+<td><a href="#encryptData">encryptData</a></td>
+<td>Module function to encrypt the given data with the given key.</td>
+</tr><tr>
+<td><a href="#strip_PKCS7_padding">strip_PKCS7_padding</a></td>
+<td>Function to strip off PKCS7 padding.</td>
+</tr>
+</table>
+<hr /><hr />
+<a NAME="AES" ID="AES"></a>
+<h2>AES</h2>
+<p>
+    Class implementing the Advanced Encryption Standard algorithm.
+</p>
+<h3>Derived from</h3>
+object
+<h3>Class Attributes</h3>
+<table>
+<tr><td>KeySize</td></tr><tr><td>Rcon</td></tr><tr><td>rsbox</td></tr><tr><td>sbox</td></tr>
+</table>
+<h3>Methods</h3>
+<table>
+<tr>
+<td><a href="#AES.__addRoundKey">__addRoundKey</a></td>
+<td>Private method to add (XORs) the round key to the state.</td>
+</tr><tr>
+<td><a href="#AES.__aes_invMain">__aes_invMain</a></td>
+<td>Private method to perform the initial operations, the standard round, and the final operations of the inverse AES, creating a round key for each round.</td>
+</tr><tr>
+<td><a href="#AES.__aes_invRound">__aes_invRound</a></td>
+<td>Private method to apply the 4 operations of the inverse round in sequence.</td>
+</tr><tr>
+<td><a href="#AES.__aes_main">__aes_main</a></td>
+<td>Private method to perform the initial operations, the standard round, and the final operations of the forward AES, creating a round key for each round.</td>
+</tr><tr>
+<td><a href="#AES.__aes_round">__aes_round</a></td>
+<td>Private method to apply the 4 operations of the forward round in sequence.</td>
+</tr><tr>
+<td><a href="#AES.__core">__core</a></td>
+<td>Private method performing the key schedule core operation.</td>
+</tr><tr>
+<td><a href="#AES.__createRoundKey">__createRoundKey</a></td>
+<td>Private method to create a round key.</td>
+</tr><tr>
+<td><a href="#AES.__expandKey">__expandKey</a></td>
+<td>Private method performing Rijndael's key expansion.</td>
+</tr><tr>
+<td><a href="#AES.__galois_multiplication">__galois_multiplication</a></td>
+<td>Private method to perform a Galois multiplication of 8 bit characters a and b.</td>
+</tr><tr>
+<td><a href="#AES.__getRconValue">__getRconValue</a></td>
+<td>Private method to retrieve a given Rcon value.</td>
+</tr><tr>
+<td><a href="#AES.__getSBoxInvert">__getSBoxInvert</a></td>
+<td>Private method to retrieve a given Inverted S-Box value.</td>
+</tr><tr>
+<td><a href="#AES.__getSBoxValue">__getSBoxValue</a></td>
+<td>Private method to retrieve a given S-Box value.</td>
+</tr><tr>
+<td><a href="#AES.__mixColumn">__mixColumn</a></td>
+<td>Private method to perform a galois multiplication of 1 column the 4x4 matrix.</td>
+</tr><tr>
+<td><a href="#AES.__mixColumns">__mixColumns</a></td>
+<td>Private method to perform a galois multiplication of the 4x4 matrix.</td>
+</tr><tr>
+<td><a href="#AES.__rotate">__rotate</a></td>
+<td>Private method performing Rijndael's key schedule rotate operation.</td>
+</tr><tr>
+<td><a href="#AES.__shiftRow">__shiftRow</a></td>
+<td>Private method to shift the bytes of a row to the left.</td>
+</tr><tr>
+<td><a href="#AES.__shiftRows">__shiftRows</a></td>
+<td>Private method to iterate over the 4 rows and call __shiftRow() with that row.</td>
+</tr><tr>
+<td><a href="#AES.__subBytes">__subBytes</a></td>
+<td>Private method to substitute all the values from the state with the value in the SBox using the state value as index for the SBox.</td>
+</tr><tr>
+<td><a href="#AES.decrypt">decrypt</a></td>
+<td>Public method to decrypt a 128 bit input block against the given key of size specified.</td>
+</tr><tr>
+<td><a href="#AES.encrypt">encrypt</a></td>
+<td>Public method to encrypt a 128 bit input block against the given key of size specified.</td>
+</tr>
+</table>
+<a NAME="AES.__addRoundKey" ID="AES.__addRoundKey"></a>
+<h4>AES.__addRoundKey</h4>
+<b>__addRoundKey</b>(<i>state, roundKey</i>)
+<p>
+        Private method to add (XORs) the round key to the state.
+</p><dl>
+<dt><i>state</i></dt>
+<dd>
+state to be changed (bytearray)
+</dd><dt><i>roundKey</i></dt>
+<dd>
+key to be used for the modification (bytearray)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+modified state (bytearray)
+</dd>
+</dl><a NAME="AES.__aes_invMain" ID="AES.__aes_invMain"></a>
+<h4>AES.__aes_invMain</h4>
+<b>__aes_invMain</b>(<i>state, expandedKey, nbrRounds</i>)
+<p>
+        Private method to perform the initial operations, the standard round, and the
+        final operations of the inverse AES, creating a round key for each round.
+</p><dl>
+<dt><i>state</i></dt>
+<dd>
+state to be worked on (bytearray)
+</dd><dt><i>expandedKey</i></dt>
+<dd>
+expanded key to be used (bytearray)
+</dd><dt><i>nbrRounds</i></dt>
+<dd>
+number of rounds to be done (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+modified state (bytearray)
+</dd>
+</dl><a NAME="AES.__aes_invRound" ID="AES.__aes_invRound"></a>
+<h4>AES.__aes_invRound</h4>
+<b>__aes_invRound</b>(<i>state, roundKey</i>)
+<p>
+        Private method to apply the 4 operations of the inverse round in sequence.
+</p><dl>
+<dt><i>state</i></dt>
+<dd>
+state to be worked on (bytearray)
+</dd><dt><i>roundKey</i></dt>
+<dd>
+round key to be used (bytearray)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+modified state (bytearray)
+</dd>
+</dl><a NAME="AES.__aes_main" ID="AES.__aes_main"></a>
+<h4>AES.__aes_main</h4>
+<b>__aes_main</b>(<i>state, expandedKey, nbrRounds</i>)
+<p>
+        Private method to perform the initial operations, the standard round, and the
+        final operations of the forward AES, creating a round key for each round.
+</p><dl>
+<dt><i>state</i></dt>
+<dd>
+state to be worked on (bytearray)
+</dd><dt><i>expandedKey</i></dt>
+<dd>
+expanded key to be used (bytearray)
+</dd><dt><i>nbrRounds</i></dt>
+<dd>
+number of rounds to be done (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+modified state (bytearray)
+</dd>
+</dl><a NAME="AES.__aes_round" ID="AES.__aes_round"></a>
+<h4>AES.__aes_round</h4>
+<b>__aes_round</b>(<i>state, roundKey</i>)
+<p>
+        Private method to apply the 4 operations of the forward round in sequence.
+</p><dl>
+<dt><i>state</i></dt>
+<dd>
+state to be worked on (bytearray)
+</dd><dt><i>roundKey</i></dt>
+<dd>
+round key to be used (bytearray)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+modified state (bytearray)
+</dd>
+</dl><a NAME="AES.__core" ID="AES.__core"></a>
+<h4>AES.__core</h4>
+<b>__core</b>(<i>data, iteration</i>)
+<p>
+        Private method performing the key schedule core operation.
+</p><dl>
+<dt><i>data</i></dt>
+<dd>
+data to operate on (bytearray)
+</dd><dt><i>iteration</i></dt>
+<dd>
+iteration counter (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+modified data (bytearray)
+</dd>
+</dl><a NAME="AES.__createRoundKey" ID="AES.__createRoundKey"></a>
+<h4>AES.__createRoundKey</h4>
+<b>__createRoundKey</b>(<i>expandedKey, roundKeyPointer</i>)
+<p>
+        Private method to create a round key.
+</p><dl>
+<dt><i>expandedKey</i></dt>
+<dd>
+expanded key to be used (bytearray)
+</dd><dt><i>roundKeyPointer</i></dt>
+<dd>
+position within the expanded key (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+round key (bytearray)
+</dd>
+</dl><a NAME="AES.__expandKey" ID="AES.__expandKey"></a>
+<h4>AES.__expandKey</h4>
+<b>__expandKey</b>(<i>key, size, expandedKeySize</i>)
+<p>
+        Private method performing Rijndael's key expansion.
+</p><p>
+        Expands a 128, 192 or 256 bit key into a 176, 208 or 240 bit key.
+</p><dl>
+<dt><i>key</i></dt>
+<dd>
+key to be expanded (bytes or bytearray)
+</dd><dt><i>size</i></dt>
+<dd>
+size of the key in bytes (16, 24 or 32)
+</dd><dt><i>expandedKeySize</i></dt>
+<dd>
+size of the expanded key (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+expanded key (bytearray)
+</dd>
+</dl><a NAME="AES.__galois_multiplication" ID="AES.__galois_multiplication"></a>
+<h4>AES.__galois_multiplication</h4>
+<b>__galois_multiplication</b>(<i>a, b</i>)
+<p>
+        Private method to perform a Galois multiplication of 8 bit characters a and b.
+</p><dl>
+<dt><i>a</i></dt>
+<dd>
+first factor (byte)
+</dd><dt><i>b</i></dt>
+<dd>
+second factor (byte)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+result (byte)
+</dd>
+</dl><a NAME="AES.__getRconValue" ID="AES.__getRconValue"></a>
+<h4>AES.__getRconValue</h4>
+<b>__getRconValue</b>(<i>num</i>)
+<p>
+        Private method to retrieve a given Rcon value.
+</p><dl>
+<dt><i>num</i></dt>
+<dd>
+position of the value (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+Rcon value (integer)
+</dd>
+</dl><a NAME="AES.__getSBoxInvert" ID="AES.__getSBoxInvert"></a>
+<h4>AES.__getSBoxInvert</h4>
+<b>__getSBoxInvert</b>(<i>num</i>)
+<p>
+        Private method to retrieve a given Inverted S-Box value.
+</p><dl>
+<dt><i>num</i></dt>
+<dd>
+position of the value (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+value of the Inverted S-Box (integer)
+</dd>
+</dl><a NAME="AES.__getSBoxValue" ID="AES.__getSBoxValue"></a>
+<h4>AES.__getSBoxValue</h4>
+<b>__getSBoxValue</b>(<i>num</i>)
+<p>
+        Private method to retrieve a given S-Box value.
+</p><dl>
+<dt><i>num</i></dt>
+<dd>
+position of the value (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+value of the S-Box (integer)
+</dd>
+</dl><a NAME="AES.__mixColumn" ID="AES.__mixColumn"></a>
+<h4>AES.__mixColumn</h4>
+<b>__mixColumn</b>(<i>column, isInv</i>)
+<p>
+        Private method to perform a galois multiplication of 1 column the 4x4 matrix.
+</p><dl>
+<dt><i>column</i></dt>
+<dd>
+column to be worked on (bytearray)
+</dd><dt><i>isInv</i></dt>
+<dd>
+flag indicating an inverse operation (boolean)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+modified column (bytearray)
+</dd>
+</dl><a NAME="AES.__mixColumns" ID="AES.__mixColumns"></a>
+<h4>AES.__mixColumns</h4>
+<b>__mixColumns</b>(<i>state, isInv</i>)
+<p>
+        Private method to perform a galois multiplication of the 4x4 matrix.
+</p><dl>
+<dt><i>state</i></dt>
+<dd>
+state to be worked on (bytearray)
+</dd><dt><i>isInv</i></dt>
+<dd>
+flag indicating an inverse operation (boolean)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+modified state (bytearray)
+</dd>
+</dl><a NAME="AES.__rotate" ID="AES.__rotate"></a>
+<h4>AES.__rotate</h4>
+<b>__rotate</b>(<i>data</i>)
+<p>
+        Private method performing Rijndael's key schedule rotate operation.
+</p><p>
+        Rotate the data word eight bits to the left: eg, rotate(1d2c3a4f) == 2c3a4f1d.
+</p><dl>
+<dt><i>data</i></dt>
+<dd>
+data of size 4 (bytearray)
+</dd>
+</dl><a NAME="AES.__shiftRow" ID="AES.__shiftRow"></a>
+<h4>AES.__shiftRow</h4>
+<b>__shiftRow</b>(<i>state, statePointer, nbr, isInv</i>)
+<p>
+        Private method to shift the bytes of a row to the left.
+</p><dl>
+<dt><i>state</i></dt>
+<dd>
+state to be worked on (bytearray)
+</dd><dt><i>statePointer</i></dt>
+<dd>
+index into the state (integer)
+</dd><dt><i>nbr</i></dt>
+<dd>
+number of positions to shift (integer)
+</dd><dt><i>isInv</i></dt>
+<dd>
+flag indicating an inverse operation (boolean)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+modified state (bytearray)
+</dd>
+</dl><a NAME="AES.__shiftRows" ID="AES.__shiftRows"></a>
+<h4>AES.__shiftRows</h4>
+<b>__shiftRows</b>(<i>state, isInv</i>)
+<p>
+        Private method to iterate over the 4 rows and call __shiftRow() with
+        that row.
+</p><dl>
+<dt><i>state</i></dt>
+<dd>
+state to be worked on (bytearray)
+</dd><dt><i>isInv</i></dt>
+<dd>
+flag indicating an inverse operation (boolean)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+modified state (bytearray)
+</dd>
+</dl><a NAME="AES.__subBytes" ID="AES.__subBytes"></a>
+<h4>AES.__subBytes</h4>
+<b>__subBytes</b>(<i>state, isInv</i>)
+<p>
+        Private method to substitute all the values from the state with the value in
+        the SBox using the state value as index for the SBox.
+</p><dl>
+<dt><i>state</i></dt>
+<dd>
+state to be worked on (bytearray)
+</dd><dt><i>isInv</i></dt>
+<dd>
+flag indicating an inverse operation (boolean)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+modified state (bytearray)
+</dd>
+</dl><a NAME="AES.decrypt" ID="AES.decrypt"></a>
+<h4>AES.decrypt</h4>
+<b>decrypt</b>(<i>iput, key, size</i>)
+<p>
+        Public method to decrypt a 128 bit input block against the given key of size
+        specified.
+</p><dl>
+<dt><i>iput</i></dt>
+<dd>
+input data (bytearray)
+</dd><dt><i>key</i></dt>
+<dd>
+key to be used (bytes or bytearray)
+</dd><dt><i>size</i></dt>
+<dd>
+key size (16, 24 or 32)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+decrypted data (bytes)
+</dd>
+</dl><a NAME="AES.encrypt" ID="AES.encrypt"></a>
+<h4>AES.encrypt</h4>
+<b>encrypt</b>(<i>iput, key, size</i>)
+<p>
+        Public method to encrypt a 128 bit input block against the given key of size
+        specified.
+</p><dl>
+<dt><i>iput</i></dt>
+<dd>
+input data (bytearray)
+</dd><dt><i>key</i></dt>
+<dd>
+key to be used (bytes or bytearray)
+</dd><dt><i>size</i></dt>
+<dd>
+key size (16, 24 or 32)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+encrypted data (bytes)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="AESModeOfOperation" ID="AESModeOfOperation"></a>
+<h2>AESModeOfOperation</h2>
+<p>
+    Class implementing the different AES mode of operations.
+</p>
+<h3>Derived from</h3>
+object
+<h3>Class Attributes</h3>
+<table>
+<tr><td>ModeOfOperation</td></tr><tr><td>aes</td></tr>
+</table>
+<h3>Methods</h3>
+<table>
+<tr>
+<td><a href="#AESModeOfOperation.__extractBytes">__extractBytes</a></td>
+<td>Private method to extract a range of bytes from the input.</td>
+</tr><tr>
+<td><a href="#AESModeOfOperation.decrypt">decrypt</a></td>
+<td>Public method to perform the decryption operation.</td>
+</tr><tr>
+<td><a href="#AESModeOfOperation.encrypt">encrypt</a></td>
+<td>Public method to perform the encryption operation.</td>
+</tr>
+</table>
+<a NAME="AESModeOfOperation.__extractBytes" ID="AESModeOfOperation.__extractBytes"></a>
+<h4>AESModeOfOperation.__extractBytes</h4>
+<b>__extractBytes</b>(<i>input, start, end, mode</i>)
+<p>
+        Private method to extract a range of bytes from the input.
+</p><dl>
+<dt><i>input</i></dt>
+<dd>
+input data (bytes)
+</dd><dt><i>start</i></dt>
+<dd>
+start index (integer)
+</dd><dt><i>end</i></dt>
+<dd>
+end index (integer)
+</dd><dt><i>mode</i></dt>
+<dd>
+mode of operation (0, 1, 2)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+extracted bytes (bytearray)
+</dd>
+</dl><a NAME="AESModeOfOperation.decrypt" ID="AESModeOfOperation.decrypt"></a>
+<h4>AESModeOfOperation.decrypt</h4>
+<b>decrypt</b>(<i>cipherIn, originalsize, mode, key, size, IV</i>)
+<p>
+        Public method to perform the decryption operation.
+</p><dl>
+<dt><i>input</i></dt>
+<dd>
+data to be encrypted (bytes)
+</dd><dt><i>originalsize</i></dt>
+<dd>
+unencrypted string length (required for CBC)
+            (integer)
+</dd><dt><i>mode</i></dt>
+<dd>
+mode of operation (0, 1 or 2)
+</dd><dt><i>key</i></dt>
+<dd>
+key to be used (bytes)
+</dd><dt><i>size</i></dt>
+<dd>
+length of the key (integer)
+</dd><dt><i>IV</i></dt>
+<dd>
+initialisation vector (bytearray)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+decrypted data (bytes)
+</dd>
+</dl><a NAME="AESModeOfOperation.encrypt" ID="AESModeOfOperation.encrypt"></a>
+<h4>AESModeOfOperation.encrypt</h4>
+<b>encrypt</b>(<i>input, mode, key, size, IV</i>)
+<p>
+        Public method to perform the encryption operation.
+</p><dl>
+<dt><i>input</i></dt>
+<dd>
+data to be encrypted (bytes)
+</dd><dt><i>mode</i></dt>
+<dd>
+mode of operation (0, 1 or 2)
+</dd><dt><i>key</i></dt>
+<dd>
+key to be used (bytes)
+</dd><dt><i>size</i></dt>
+<dd>
+length of the key (integer)
+</dd><dt><i>IV</i></dt>
+<dd>
+initialisation vector (bytearray)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+tuple with mode of operation, length of the input and
+            the encrypted data (integer, integer, bytes)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="append_PKCS7_padding" ID="append_PKCS7_padding"></a>
+<h2>append_PKCS7_padding</h2>
+<b>append_PKCS7_padding</b>(<i>b</i>)
+<p>
+    Function to pad the given data to a multiple of 16-bytes by PKCS7 padding.
+</p><dl>
+<dt><i>b</i></dt>
+<dd>
+data to be padded (bytes)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+padded data (bytes)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="decryptData" ID="decryptData"></a>
+<h2>decryptData</h2>
+<b>decryptData</b>(<i>key, data, mode=AESModeOfOperation.ModeOfOperation["CBC"]</i>)
+<p>
+    Module function to decrypt the given data with the given key.
+</p><dl>
+<dt><i>key</i></dt>
+<dd>
+key to be used for decryption (bytes)
+</dd><dt><i>data</i></dt>
+<dd>
+data to be decrypted (with initialization vector prepended) (bytes)
+</dd><dt><i>mode</i></dt>
+<dd>
+mode of operations (0, 1 or 2)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+decrypted data (bytes)
+</dd>
+</dl><dl>
+<dt>Raises <b>ValueError</b>:</dt>
+<dd>
+key size is invalid or decrypted data is invalid
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="encryptData" ID="encryptData"></a>
+<h2>encryptData</h2>
+<b>encryptData</b>(<i>key, data, mode=AESModeOfOperation.ModeOfOperation["CBC"]</i>)
+<p>
+    Module function to encrypt the given data with the given key.
+</p><dl>
+<dt><i>key</i></dt>
+<dd>
+key to be used for encryption (bytes)
+</dd><dt><i>data</i></dt>
+<dd>
+data to be encrypted (bytes)
+</dd><dt><i>mode</i></dt>
+<dd>
+mode of operations (0, 1 or 2)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+encrypted data prepended with the initialization vector (bytes)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="strip_PKCS7_padding" ID="strip_PKCS7_padding"></a>
+<h2>strip_PKCS7_padding</h2>
+<b>strip_PKCS7_padding</b>(<i>b</i>)
+<p>
+    Function to strip off PKCS7 padding.
+</p><dl>
+<dt><i>b</i></dt>
+<dd>
+data to be stripped (bytes)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+stripped data (bytes)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Documentation/Source/eric5.Utilities.crypto.py3PBKDF2.html	Sun Jun 19 15:19:46 2011 +0200
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'
+'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html><head>
+<title>eric5.Utilities.crypto.py3PBKDF2</title>
+<style>
+body {
+    background: #EDECE6;
+    margin: 0em 1em 10em 1em;
+    color: black;
+}
+
+h1 { color: white; background: #85774A; }
+h2 { color: white; background: #85774A; }
+h3 { color: white; background: #9D936E; }
+h4 { color: white; background: #9D936E; }
+    
+a { color: #BA6D36; }
+
+</style>
+</head>
+<body><a NAME="top" ID="top"></a>
+<h1>eric5.Utilities.crypto.py3PBKDF2</h1>
+<p>
+Module implementing PBKDF2 functions.
+</p>
+<h3>Global Attributes</h3>
+<table>
+<tr><td>Delimiter</td></tr><tr><td>Hashes</td></tr>
+</table>
+<h3>Classes</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Functions</h3>
+<table>
+<tr>
+<td><a href="#hashPassword">hashPassword</a></td>
+<td>Module function to hash a password according to the PBKDF2 specification.</td>
+</tr><tr>
+<td><a href="#hashPasswordTuple">hashPasswordTuple</a></td>
+<td>Module function to hash a password according to the PBKDF2 specification.</td>
+</tr><tr>
+<td><a href="#pbkdf2">pbkdf2</a></td>
+<td>Module function to hash a password according to the PBKDF2 specification.</td>
+</tr><tr>
+<td><a href="#rehashPassword">rehashPassword</a></td>
+<td>Module function to recreate a password hash given the hash parameters.</td>
+</tr><tr>
+<td><a href="#verifyPassword">verifyPassword</a></td>
+<td>Module function to verify a password against a hash encoded password.</td>
+</tr>
+</table>
+<hr /><hr />
+<a NAME="hashPassword" ID="hashPassword"></a>
+<h2>hashPassword</h2>
+<b>hashPassword</b>(<i>password, digestMod=hashlib.sha512, iterations=10000, saltSize=32</i>)
+<p>
+    Module function to hash a password according to the PBKDF2 specification.
+</p><dl>
+<dt><i>password</i></dt>
+<dd>
+clear text password (string)
+</dd><dt><i>digestMod</i></dt>
+<dd>
+hash function
+</dd><dt><i>iterations</i></dt>
+<dd>
+number of times hash function should be applied (integer)
+</dd><dt><i>saltSize</i></dt>
+<dd>
+size of the salt (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+hashed password entry according to PBKDF2 specification (string)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="hashPasswordTuple" ID="hashPasswordTuple"></a>
+<h2>hashPasswordTuple</h2>
+<b>hashPasswordTuple</b>(<i>password, digestMod=hashlib.sha512, iterations=10000, saltSize=32</i>)
+<p>
+    Module function to hash a password according to the PBKDF2 specification.
+</p><dl>
+<dt><i>password</i></dt>
+<dd>
+clear text password (string)
+</dd><dt><i>digestMod</i></dt>
+<dd>
+hash function
+</dd><dt><i>iterations</i></dt>
+<dd>
+number of times hash function should be applied (integer)
+</dd><dt><i>saltSize</i></dt>
+<dd>
+size of the salt (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+tuple of digestname (string), number of iterations (integer),
+        salt (bytes) and hashed password (bytes)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="pbkdf2" ID="pbkdf2"></a>
+<h2>pbkdf2</h2>
+<b>pbkdf2</b>(<i>password, salt, iterations, digestMod</i>)
+<p>
+    Module function to hash a password according to the PBKDF2 specification.
+</p><dl>
+<dt><i>password</i></dt>
+<dd>
+clear text password (bytes)
+</dd><dt><i>salt</i></dt>
+<dd>
+salt value (bytes)
+</dd><dt><i>iterations</i></dt>
+<dd>
+number of times hash function should be applied (integer)
+</dd><dt><i>digestMod</i></dt>
+<dd>
+hash function
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+hashed password (bytes)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="rehashPassword" ID="rehashPassword"></a>
+<h2>rehashPassword</h2>
+<b>rehashPassword</b>(<i>password, hashParameters</i>)
+<p>
+    Module function to recreate a password hash given the hash parameters.
+</p><dl>
+<dt><i>password</i></dt>
+<dd>
+clear text password (string)
+</dd><dt><i>hashParameters</i></dt>
+<dd>
+hash parameters in the form
+        'digestmod$iterations$salt' (string)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+hashed password (bytes)
+</dd>
+</dl><dl>
+<dt>Raises <b>ValueError</b>:</dt>
+<dd>
+the hash parameters string is not of the expected format
+        or the digest is not one of the known ones
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="verifyPassword" ID="verifyPassword"></a>
+<h2>verifyPassword</h2>
+<b>verifyPassword</b>(<i>password, hash</i>)
+<p>
+    Module function to verify a password against a hash encoded password.
+</p><dl>
+<dt><i>password</i></dt>
+<dd>
+clear text password (string)
+</dd><dt><i>hash</i></dt>
+<dd>
+hash encoded password in the form
+        'digestmod$iterations$salt$hashed_password' as produced by the
+        hashPassword function (string)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+flag indicating a successfull verification (boolean)
+</dd>
+</dl><dl>
+<dt>Raises <b>ValueError</b>:</dt>
+<dd>
+the hash is not of the expected format or the
+        digest is not one of the known ones
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- a/Documentation/Source/eric5.install.html	Thu Jun 16 16:29:27 2011 +0200
+++ b/Documentation/Source/eric5.install.html	Sun Jun 19 15:19:46 2011 +0200
@@ -173,7 +173,7 @@
 <hr /><hr />
 <a NAME="copyTree" ID="copyTree"></a>
 <h2>copyTree</h2>
-<b>copyTree</b>(<i>src, dst, filters, excludeDirs=[]</i>)
+<b>copyTree</b>(<i>src, dst, filters, excludeDirs=[], excludePatterns=[]</i>)
 <p>
     Copy Python, translation, documentation, wizards configuration,
     designer template files and DTDs of a directory tree.
@@ -190,6 +190,9 @@
 </dd><dt><i>excludeDirs</i></dt>
 <dd>
 list of (sub)directories to exclude from copying
+</dd><dt><i>excludePatterns=</i></dt>
+<dd>
+list of filter pattern determining the files to be skipped
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
--- a/Documentation/Source/index-eric5.E5Gui.html	Thu Jun 16 16:29:27 2011 +0200
+++ b/Documentation/Source/index-eric5.E5Gui.html	Sun Jun 19 15:19:46 2011 +0200
@@ -67,6 +67,9 @@
 <td><a href="eric5.E5Gui.E5PassivePopup.html">E5PassivePopup</a></td>
 <td>Module implementing dialog-like popup that displays messages without interrupting the user.</td>
 </tr><tr>
+<td><a href="eric5.E5Gui.E5PasswordMeter.html">E5PasswordMeter</a></td>
+<td>Module implementing a custom widget indicating the strength of a password.</td>
+</tr><tr>
 <td><a href="eric5.E5Gui.E5SideBar.html">E5SideBar</a></td>
 <td>Module implementing a sidebar class.</td>
 </tr><tr>
--- a/Documentation/Source/index-eric5.Preferences.ConfigurationPages.html	Thu Jun 16 16:29:27 2011 +0200
+++ b/Documentation/Source/index-eric5.Preferences.ConfigurationPages.html	Sun Jun 19 15:19:46 2011 +0200
@@ -131,6 +131,9 @@
 <td><a href="eric5.Preferences.ConfigurationPages.InterfacePage.html">InterfacePage</a></td>
 <td>Module implementing the Interface configuration page.</td>
 </tr><tr>
+<td><a href="eric5.Preferences.ConfigurationPages.MasterPasswordEntryDialog.html">MasterPasswordEntryDialog</a></td>
+<td>Module implementing a dialog to enter or change the master password.</td>
+</tr><tr>
 <td><a href="eric5.Preferences.ConfigurationPages.MultiProjectPage.html">MultiProjectPage</a></td>
 <td>Module implementing the Multi Project configuration page.</td>
 </tr><tr>
@@ -158,6 +161,9 @@
 <td><a href="eric5.Preferences.ConfigurationPages.QtPage.html">QtPage</a></td>
 <td>Module implementing the Qt configuration page.</td>
 </tr><tr>
+<td><a href="eric5.Preferences.ConfigurationPages.SecurityPage.html">SecurityPage</a></td>
+<td>Module implementing the Security configuration page.</td>
+</tr><tr>
 <td><a href="eric5.Preferences.ConfigurationPages.ShellPage.html">ShellPage</a></td>
 <td>Module implementing the Shell configuration page.</td>
 </tr><tr>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Documentation/Source/index-eric5.Utilities.crypto.html	Sun Jun 19 15:19:46 2011 +0200
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'
+'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html><head>
+<title>eric5.Utilities.crypto</title>
+<style>
+body {
+    background: #EDECE6;
+    margin: 0em 1em 10em 1em;
+    color: black;
+}
+
+h1 { color: white; background: #85774A; }
+h2 { color: white; background: #85774A; }
+h3 { color: white; background: #9D936E; }
+h4 { color: white; background: #9D936E; }
+    
+a { color: #BA6D36; }
+
+</style>
+</head>
+<body>
+<h1>eric5.Utilities.crypto</h1>
+<p>
+Package implementing cryptography related functionality.
+</p>
+
+
+<h3>Modules</h3>
+<table>
+<tr>
+<td><a href="eric5.Utilities.crypto.__init__.html">crypto</a></td>
+<td>Package implementing cryptography related functionality.</td>
+</tr><tr>
+<td><a href="eric5.Utilities.crypto.py3AES.html">py3AES</a></td>
+<td>Module implementing classes for encryption according Advanced Encryption Standard.</td>
+</tr><tr>
+<td><a href="eric5.Utilities.crypto.py3PBKDF2.html">py3PBKDF2</a></td>
+<td>Module implementing PBKDF2 functions.</td>
+</tr>
+</table>
+</body></html>
\ No newline at end of file
--- a/Documentation/Source/index-eric5.Utilities.html	Thu Jun 16 16:29:27 2011 +0200
+++ b/Documentation/Source/index-eric5.Utilities.html	Sun Jun 19 15:19:46 2011 +0200
@@ -31,6 +31,9 @@
 <td><a href="index-eric5.Utilities.ClassBrowsers.html">ClassBrowsers</a></td>
 <td>Package implementing class browsers for various languages.</td>
 </tr><tr>
+<td><a href="index-eric5.Utilities.crypto.html">crypto</a></td>
+<td>Package implementing cryptography related functionality.</td>
+</tr><tr>
 <td><a href="index-eric5.Utilities.py3flakes.html">py3flakes</a></td>
 <td>Package containg the pyflakes Python3 port adapted for Qt.</td>
 </tr>
@@ -45,6 +48,9 @@
 <td><a href="eric5.Utilities.ModuleParser.html">ModuleParser</a></td>
 <td>Parse a Python module file.</td>
 </tr><tr>
+<td><a href="eric5.Utilities.PasswordChecker.html">PasswordChecker</a></td>
+<td>Module implementing a checker for password strength</td>
+</tr><tr>
 <td><a href="eric5.Utilities.SingleApplication.html">SingleApplication</a></td>
 <td>Module implementing the single application server and client.</td>
 </tr><tr>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/E5Gui/E5PasswordMeter.py	Sun Jun 19 15:19:46 2011 +0200
@@ -0,0 +1,93 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a custom widget indicating the strength of a password.
+"""
+
+from PyQt4.QtGui import QProgressBar
+
+from Utilities.PasswordChecker import PasswordChecker
+
+
+class E5PasswordMeter(QProgressBar):
+    """
+    Class implementing a custom widget indicating the strength of a password.
+    """
+    def __init__(self, parent=None):
+        """
+        Constructor
+        
+        @param parent reference to the parent widget (QWidget)
+        """
+        super().__init__(parent)
+        
+        super().setTextVisible(False)
+        super().setMaximum(100)
+        self.__increment = 100 // (PasswordChecker.Complexity_VeryStrong + 1)
+        
+        self.__indicatorColors = [
+            "#ff0000",      # red
+            "#ff8800",      # orange
+            "#ffff00",      # yellow
+            "#ccff00",      # yellow green
+            "#00ff00",      # green
+        ]
+        self.__noIndicator = "#ffffff"
+        
+        self.__styleSheetTemplate = \
+            "QProgressBar {{"\
+            " border: 2px solid black;" \
+            " border-radius: 5px;" \
+            " text-align: center; }}" \
+            "QProgressBar::chunk:horizontal {{" \
+            " background-color: {0}; }}"
+        self.setStyleSheet(self.__styleSheetTemplate.format(self.__noIndicator))
+    
+    def checkPasswordStrength(self, password):
+        """
+        Public slot to check the password strength and update the
+        progress bar accordingly.
+        
+        @param password password to be checked (string)
+        """
+        strength = PasswordChecker().checkPassword(password)
+        self.setStyleSheet(self.__styleSheetTemplate.format(
+            self.__indicatorColors[strength]))
+        super().setValue((strength + 1) * self.__increment)
+    
+    def setValue(self, value):
+        """
+        Public method to set the value.
+        
+        Overwritten to do nothing.
+        """
+        pass
+    
+    def setMaximum(self, value):
+        """
+        Public method to set the maximum value.
+        
+        Overwritten to do nothing.
+        """
+        pass
+    
+    def setMinimum(self, value):
+        """
+        Public method to set the minimal value.
+        
+        Overwritten to do nothing.
+        """
+        pass
+
+if __name__ == "__main__":
+    import sys
+    from PyQt4.QtGui import QApplication
+    
+    app = QApplication(sys.argv)
+    meter = E5PasswordMeter()
+    meter.show()
+    meter.checkPasswordStrength("Blah2+")
+    app.exec_()
--- a/Helpviewer/HelpWindow.py	Thu Jun 16 16:29:27 2011 +0200
+++ b/Helpviewer/HelpWindow.py	Sun Jun 19 15:19:46 2011 +0200
@@ -1920,6 +1920,7 @@
                                   fromEric=self.fromEric,
                                   displayMode=ConfigurationDialog.HelpBrowserMode)
         dlg.preferencesChanged.connect(self.preferencesChanged)
+        dlg.masterPasswordChanged.connect(self.masterPasswordChanged)
         dlg.show()
         if self.__lastConfigurationPageName:
             dlg.showConfigurationPageByName(self.__lastConfigurationPageName)
@@ -1957,6 +1958,19 @@
             self.virustotalScanCurrentAct.setEnabled(True)
         self.__virusTotalSearchChanged(self.virustotalSearchEdit.text())
     
+    def masterPasswordChanged(self, oldPassword, newPassword):
+        """
+        Public slot to handle the change of the master password.
+        
+        @param oldPassword current master password (string)
+        @param newPassword new master password (string)
+        """
+        self.passwordManager().masterPasswordChanged(oldPassword, newPassword)
+        if self.fromEric and isinstance(self.sender(), ConfigurationDialog):
+            # we were called from our local configuration dialog
+            Preferences.convertPasswords(oldPassword, newPassword)
+            Utilities.crypto.changeRememberedMaster(newPassword)
+    
     def __showAcceptedLanguages(self):
         """
         Private slot to configure the accepted languages for web pages.
--- a/Helpviewer/Network/NetworkAccessManager.py	Thu Jun 16 16:29:27 2011 +0200
+++ b/Helpviewer/Network/NetworkAccessManager.py	Sun Jun 19 15:19:46 2011 +0200
@@ -173,9 +173,9 @@
                                "realm '{1}'</b>").format(urlRoot, auth.realm())
         
         dlg = AuthenticationDialog(info, auth.user(),
-                                   Preferences.getHelp("SavePasswords"),
-                                   Preferences.getHelp("SavePasswords"))
-        if Preferences.getHelp("SavePasswords"):
+                                   Preferences.getUser("SavePasswords"),
+                                   Preferences.getUser("SavePasswords"))
+        if Preferences.getUser("SavePasswords"):
             username, password = \
                 Helpviewer.HelpWindow.HelpWindow.passwordManager().getLogin(
                     reply.url(), auth.realm())
@@ -185,7 +185,7 @@
             username, password = dlg.getData()
             auth.setUser(username)
             auth.setPassword(password)
-            if Preferences.getHelp("SavePasswords"):
+            if Preferences.getUser("SavePasswords"):
                 Helpviewer.HelpWindow.HelpWindow.passwordManager().setLogin(
                     reply.url(), auth.realm(), username, password)
     
--- a/Helpviewer/Passwords/PasswordManager.py	Thu Jun 16 16:29:27 2011 +0200
+++ b/Helpviewer/Passwords/PasswordManager.py	Sun Jun 19 15:19:46 2011 +0200
@@ -9,7 +9,8 @@
 
 import os
 
-from PyQt4.QtCore import pyqtSignal, QObject, QByteArray, QUrl
+from PyQt4.QtCore import pyqtSignal, QObject, QByteArray, QUrl, QCoreApplication
+from PyQt4.QtGui import QProgressDialog, QApplication
 from PyQt4.QtNetwork import QNetworkRequest
 from PyQt4.QtWebKit import QWebSettings, QWebPage
 
@@ -19,6 +20,7 @@
 
 from Utilities.AutoSaver import AutoSaver
 import Utilities
+import Utilities.crypto
 import Preferences
 
 
@@ -129,7 +131,8 @@
         
         key = self.__createKey(url, realm)
         try:
-            return self.__logins[key][0], Utilities.pwDecode(self.__logins[key][1])
+            return self.__logins[key][0], Utilities.crypto.pwConvert(
+                self.__logins[key][1], encode=False)
         except KeyError:
             return "", ""
     
@@ -146,7 +149,7 @@
             self.__load()
         
         key = self.__createKey(url, realm)
-        self.__logins[key] = (username, Utilities.pwEncode(password))
+        self.__logins[key] = (username, Utilities.crypto.pwConvert(password, encode=True))
         self.changed.emit()
     
     def __createKey(self, url, realm):
@@ -308,7 +311,8 @@
         if site not in self.__logins:
             return None
         
-        return self.__logins[site][0], Utilities.pwDecode(self.__logins[site][1])
+        return self.__logins[site][0], Utilities.crypto.pwConvert(
+            self.__logins[site][1], encode=False)
     
     def post(self, request, data):
         """
@@ -318,7 +322,7 @@
         @param data data to be sent (QByteArray)
         """
         # shall passwords be saved?
-        if not Preferences.getHelp("SavePasswords"):
+        if not Preferences.getUser("SavePasswords"):
             return
         
         # observe privacy
@@ -407,7 +411,7 @@
                 password = element[1]
                 form.elements[index] = (element[0], "--PASSWORD--")
         if user and password:
-            self.__logins[key] = (user, Utilities.pwEncode(password))
+            self.__logins[key] = (user, Utilities.crypto.pwConvert(password, encode=True))
             self.__loginForms[key] = form
             self.changed.emit()
     
@@ -438,12 +442,13 @@
         if boundary is not None:
             args = self.__extractMultipartQueryItems(data, boundary)
         else:
-            argsUrl = QUrl.fromEncoded(QByteArray("foo://bar.com/?" + data))
+            argsUrl = QUrl.fromEncoded(
+                QByteArray("foo://bar.com/?" + data.replace(b"+", b"%20")))
             encodedArgs = argsUrl.queryItems()
             args = set()
             for arg in encodedArgs:
                 key = arg[0]
-                value = arg[1].replace("+", " ")
+                value = arg[1]
                 args.add((key, value))
         
         # extract the forms
@@ -560,10 +565,37 @@
                type_ in ["hidden", "reset", "submit"]:
                 continue
             if type_ == "password":
-                value = Utilities.pwDecode(self.__logins[key][1])
+                value = Utilities.crypto.pwConvert(self.__logins[key][1], encode=False)
             setType = type_ == "checkbox" and "checked" or "value"
             value = value.replace("\\", "\\\\")
             value = value.replace('"', '\\"')
             javascript = 'document.forms[{0}].elements["{1}"].{2}="{3}";'.format(
                          formName, name, setType, value)
             page.mainFrame().evaluateJavaScript(javascript)
+    
+    def masterPasswordChanged(self, oldPassword, newPassword):
+        """
+        Public slot to handle the change of the master password.
+        
+        @param oldPassword current master password (string)
+        @param newPassword new master password (string)
+        """
+        if not self.__loaded:
+            self.__load()
+        
+        progress = QProgressDialog(self.trUtf8("Re-encoding saved passwords..."),
+            None, 0, len(self.__logins), QApplication.activeModalWidget())
+        progress.setMinimumDuration(0)
+        count = 0
+        
+        for key in self.__logins:
+            progress.setValue(count)
+            QCoreApplication.processEvents()
+            username, hash = self.__logins[key]
+            hash = Utilities.crypto.pwRecode(hash, oldPassword, newPassword)
+            self.__logins[key] = (username, hash)
+            count += 1
+        
+        progress.setValue(len(self.__logins))
+        QCoreApplication.processEvents()
+        self.changed.emit()
--- a/Preferences/ConfigurationDialog.py	Thu Jun 16 16:29:27 2011 +0200
+++ b/Preferences/ConfigurationDialog.py	Sun Jun 19 15:19:46 2011 +0200
@@ -60,8 +60,11 @@
     Class implementing a dialog for the configuration of eric5.
     
     @signal preferencesChanged() emitted after settings have been changed
+    @signal masterPasswordChanged(str, str) emitted after the master
+        password has been changed with the old and the new password
     """
     preferencesChanged = pyqtSignal()
+    masterPasswordChanged = pyqtSignal(str, str)
     
     DefaultMode = 0
     HelpBrowserMode = 1
@@ -143,6 +146,9 @@
                 "qtPage": \
                     [self.trUtf8("Qt"), "preferences-qtlogo.png",
                     "QtPage", None, None],
+                "securityPage": \
+                    [self.trUtf8("Security"), "preferences-security.png",
+                    "SecurityPage", None, None],
                 "shellPage": \
                     [self.trUtf8("Shell"), "preferences-shell.png",
                     "ShellPage", None, None],
@@ -297,6 +303,9 @@
                 "printerPage": \
                     [self.trUtf8("Printer"), "preferences-printer.png",
                     "PrinterPage", None, None],
+                "securityPage": \
+                    [self.trUtf8("Security"), "preferences-security.png",
+                    "SecurityPage", None, None],
                 
                 "0helpPage": \
                     [self.trUtf8("Help"), "preferences-help.png",
@@ -643,8 +652,11 @@
     Class for the dialog variant.
     
     @signal preferencesChanged() emitted after settings have been changed
+    @signal masterPasswordChanged(str, str) emitted after the master
+        password has been changed with the old and the new password
     """
     preferencesChanged = pyqtSignal()
+    masterPasswordChanged = pyqtSignal(str, str)
     
     DefaultMode = ConfigurationWidget.DefaultMode
     HelpBrowserMode = ConfigurationWidget.HelpBrowserMode
@@ -680,6 +692,7 @@
         self.cw.buttonBox.accepted[()].connect(self.accept)
         self.cw.buttonBox.rejected[()].connect(self.reject)
         self.cw.preferencesChanged.connect(self.__preferencesChanged)
+        self.cw.masterPasswordChanged.connect(self.__masterPasswordChanged)
         
     def __preferencesChanged(self):
         """
@@ -687,6 +700,15 @@
         """
         self.preferencesChanged.emit()
         
+    def __masterPasswordChanged(self, oldPassword, newPassword):
+        """
+        Private slot to handle the change of the master password.
+        
+        @param oldPassword current master password (string)
+        @param newPassword new master password (string)
+        """
+        self.masterPasswordChanged.emit(oldPassword, newPassword)
+        
     def showConfigurationPageByName(self, pageName):
         """
         Public slot to show a named configuration page.
--- a/Preferences/ConfigurationPages/DebuggerPython3Page.ui	Thu Jun 16 16:29:27 2011 +0200
+++ b/Preferences/ConfigurationPages/DebuggerPython3Page.ui	Sun Jun 19 15:19:46 2011 +0200
@@ -50,7 +50,7 @@
       <item row="1" column="0">
        <widget class="QLineEdit" name="interpreterEdit">
         <property name="toolTip">
-         <string>Enter the path of the Python3 interpreter to be used by the debug client.</string>
+         <string>Enter the path of the Python3 interpreter to be used by the debug client. Leave empty to use the default.</string>
         </property>
        </widget>
       </item>
--- a/Preferences/ConfigurationPages/DebuggerPythonPage.ui	Thu Jun 16 16:29:27 2011 +0200
+++ b/Preferences/ConfigurationPages/DebuggerPythonPage.ui	Sun Jun 19 15:19:46 2011 +0200
@@ -40,7 +40,7 @@
       <item row="0" column="0">
        <widget class="QLineEdit" name="interpreterEdit">
         <property name="toolTip">
-         <string>Enter the path of the Python interpreter to be used by the debug client.  Leave empty to use the default.</string>
+         <string>Enter the path of the Python interpreter to be used by the debug client.</string>
         </property>
        </widget>
       </item>
--- a/Preferences/ConfigurationPages/HelpWebBrowserPage.py	Thu Jun 16 16:29:27 2011 +0200
+++ b/Preferences/ConfigurationPages/HelpWebBrowserPage.py	Sun Jun 19 15:19:46 2011 +0200
@@ -8,7 +8,6 @@
 """
 
 from PyQt4.QtCore import pyqtSlot, QLocale
-from PyQt4.QtWebKit import QWebSettings
 from PyQt4.QtNetwork import QNetworkRequest
 
 from .ConfigurationPageBase import ConfigurationPageBase
@@ -31,6 +30,7 @@
         self.setupUi(self)
         self.setObjectName("HelpWebBrowserPage")
         
+        self.__configDlg = configDialog
         mw = configDialog.parent().parent()
         if hasattr(mw, "helpWindow") and mw.helpWindow is not None:
             self.__helpWindow = mw.helpWindow
@@ -66,14 +66,6 @@
         self.pluginsCheckBox.setChecked(
             Preferences.getHelp("PluginsEnabled"))
         
-        self.savePasswordsCheckBox.setChecked(
-            Preferences.getHelp("SavePasswords"))
-        if hasattr(QWebSettings, "DnsPrefetchEnabled"):
-            self.dnsPrefetchCheckBox.setChecked(
-            Preferences.getHelp("DnsPrefetchEnabled"))
-        else:
-            self.dnsPrefetchCheckBox.setEnabled(False)
-        
         self.diskCacheCheckBox.setChecked(
             Preferences.getHelp("DiskCacheEnabled"))
         self.cacheSizeSpinBox.setValue(
@@ -127,7 +119,7 @@
         index = self.languageCombo.findData(Preferences.getHelp("SearchLanguage"))
         if index > -1:
             self.languageCombo.setCurrentIndex(index)
-        
+    
     def save(self):
         """
         Public slot to save the Help Viewers configuration.
@@ -154,12 +146,6 @@
         Preferences.setHelp("PluginsEnabled",
             self.pluginsCheckBox.isChecked())
         
-        Preferences.setHelp("SavePasswords",
-            self.savePasswordsCheckBox.isChecked())
-        if self.dnsPrefetchCheckBox.isEnabled():
-            Preferences.setHelp("DnsPrefetchEnabled",
-                self.dnsPrefetchCheckBox.isChecked())
-        
         Preferences.setHelp("DiskCacheEnabled",
             self.diskCacheCheckBox.isChecked())
         Preferences.setHelp("DiskCacheSize",
@@ -224,7 +210,7 @@
         Private slot to set the default home page.
         """
         self.homePageEdit.setText(Preferences.Prefs.helpDefaults["HomePage"])
-    
+
 
 def create(dlg):
     """
--- a/Preferences/ConfigurationPages/HelpWebBrowserPage.ui	Thu Jun 16 16:29:27 2011 +0200
+++ b/Preferences/ConfigurationPages/HelpWebBrowserPage.ui	Sun Jun 19 15:19:46 2011 +0200
@@ -260,35 +260,6 @@
     </widget>
    </item>
    <item>
-    <widget class="QGroupBox" name="groupBox_3">
-     <property name="title">
-      <string>Security</string>
-     </property>
-     <layout class="QVBoxLayout" name="verticalLayout_2">
-      <item>
-       <widget class="QCheckBox" name="savePasswordsCheckBox">
-        <property name="toolTip">
-         <string>Select to save passwords</string>
-        </property>
-        <property name="text">
-         <string>Save passwords</string>
-        </property>
-       </widget>
-      </item>
-      <item>
-       <widget class="QCheckBox" name="dnsPrefetchCheckBox">
-        <property name="toolTip">
-         <string>Select to enable DNS prefetch</string>
-        </property>
-        <property name="text">
-         <string>Use DNS prefetching to improve page loading</string>
-        </property>
-       </widget>
-      </item>
-     </layout>
-    </widget>
-   </item>
-   <item>
     <widget class="QGroupBox" name="groupBox">
      <property name="title">
       <string>History</string>
@@ -535,8 +506,6 @@
   <tabstop>jsOpenWindowsCheckBox</tabstop>
   <tabstop>jsClipboardCheckBox</tabstop>
   <tabstop>pluginsCheckBox</tabstop>
-  <tabstop>savePasswordsCheckBox</tabstop>
-  <tabstop>dnsPrefetchCheckBox</tabstop>
   <tabstop>expireHistory</tabstop>
   <tabstop>diskCacheCheckBox</tabstop>
   <tabstop>cacheKeepButton</tabstop>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Preferences/ConfigurationPages/MasterPasswordEntryDialog.py	Sun Jun 19 15:19:46 2011 +0200
@@ -0,0 +1,108 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to enter or change the master password.
+"""
+
+from PyQt4.QtCore import pyqtSlot
+from PyQt4.QtGui import QDialog, QDialogButtonBox
+
+from .Ui_MasterPasswordEntryDialog import Ui_MasterPasswordEntryDialog
+
+from Utilities.crypto.py3PBKDF2 import verifyPassword
+
+
+class MasterPasswordEntryDialog(QDialog, Ui_MasterPasswordEntryDialog):
+    """
+    Class implementing a dialog to enter or change the master password.
+    """
+    def __init__(self, oldPasswordHash, parent=None):
+        """
+        Constructor
+        
+        @param oldPasswordHash hash of the current password (string)
+        @param parent reference to the parent widget (QWidget)
+        """
+        QDialog.__init__(self, parent)
+        self.setupUi(self)
+        
+        self.__oldPasswordHash = oldPasswordHash
+        if self.__oldPasswordHash == "":
+            self.currentPasswordEdit.setEnabled(False)
+            if hasattr(self.currentPasswordEdit, "setPlaceholderText"):
+                self.currentPasswordEdit.setPlaceholderText(
+                    self.trUtf8("(not defined yet)"))
+        
+        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
+    
+    def __updateUI(self):
+        """
+        Private slot to update the variable parts of the UI.
+        """
+        enable = True
+        error = ""
+        if self.currentPasswordEdit.isEnabled():
+            enable = \
+                verifyPassword(self.currentPasswordEdit.text(), self.__oldPasswordHash)
+            if not enable:
+                error = error or self.trUtf8("Wrong password entered.")
+        
+        if self.newPasswordEdit.text() == "":
+            enable = False
+            error = error or self.trUtf8("New password must not be empty.")
+        
+        if self.newPasswordEdit.text() != "" and \
+           self.newPasswordEdit.text() != self.newPasswordAgainEdit.text():
+            enable = False
+            error = error or self.trUtf8("Repeated password is wrong.")
+        
+        if self.currentPasswordEdit.isEnabled():
+            if self.newPasswordEdit.text() == self.currentPasswordEdit.text():
+                enable = False
+                error = error or self.trUtf8("Old and new password must not be the same.")
+        
+        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(enable)
+        self.errorLabel.setText(error)
+    
+    @pyqtSlot(str)
+    def on_currentPasswordEdit_textChanged(self, txt):
+        """
+        Private slot to handle changes of the current password.
+        
+        @param txt content of the edit widget (string)
+        """
+        self.__updateUI()
+    
+    @pyqtSlot(str)
+    def on_newPasswordEdit_textChanged(self, txt):
+        """
+        Private slot to handle changes of the new password.
+        
+        @param txt content of the edit widget (string)
+        """
+        self.passwordMeter.checkPasswordStrength(txt)
+        self.__updateUI()
+    
+    @pyqtSlot(str)
+    def on_newPasswordAgainEdit_textChanged(self, txt):
+        """
+        Private slot to handle changes of the new again password.
+        
+        @param txt content of the edit widget (string)
+        """
+        self.__updateUI()
+    
+    def getMasterPassword(self):
+        """
+        Public method to get the new master password.
+        """
+        return self.newPasswordEdit.text()
+    
+    def getCurrentPassword(self):
+        """
+        Public method to get the current master password.
+        """
+        return self.currentPasswordEdit.text()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Preferences/ConfigurationPages/MasterPasswordEntryDialog.ui	Sun Jun 19 15:19:46 2011 +0200
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MasterPasswordEntryDialog</class>
+ <widget class="QDialog" name="MasterPasswordEntryDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>450</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Master Password</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>&lt;p&gt;Enter your master password below. This password will be used to encrypt sensitive data. You will be asked once per session for this password when the data needs to be accessed for the first time.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Note: If you forget the master password, the encrypted data cannot be recovered!&lt;/b&gt;&lt;/p&gt;</string>
+     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>28</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <layout class="QGridLayout" name="gridLayout">
+     <item row="0" column="0">
+      <widget class="QLabel" name="label_2">
+       <property name="text">
+        <string>Current Password:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <widget class="QLineEdit" name="currentPasswordEdit">
+       <property name="toolTip">
+        <string>Enter the current password</string>
+       </property>
+       <property name="echoMode">
+        <enum>QLineEdit::Password</enum>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="0">
+      <widget class="QLabel" name="label_3">
+       <property name="text">
+        <string>New Password:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="1">
+      <widget class="QLineEdit" name="newPasswordEdit">
+       <property name="toolTip">
+        <string>Enter the new password</string>
+       </property>
+       <property name="echoMode">
+        <enum>QLineEdit::Password</enum>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="0">
+      <widget class="QLabel" name="label_4">
+       <property name="text">
+        <string>New Password (again):</string>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="1">
+      <widget class="QLineEdit" name="newPasswordAgainEdit">
+       <property name="toolTip">
+        <string>Repeat the new password</string>
+       </property>
+       <property name="echoMode">
+        <enum>QLineEdit::Password</enum>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="E5PasswordMeter" name="passwordMeter">
+     <property name="toolTip">
+      <string>Shows an indication for the password strength</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="errorLabel">
+     <property name="styleSheet">
+      <string notr="true">color : red;</string>
+     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>E5PasswordMeter</class>
+   <extends>QProgressBar</extends>
+   <header>E5Gui/E5PasswordMeter</header>
+  </customwidget>
+ </customwidgets>
+ <tabstops>
+  <tabstop>currentPasswordEdit</tabstop>
+  <tabstop>newPasswordEdit</tabstop>
+  <tabstop>newPasswordAgainEdit</tabstop>
+  <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>MasterPasswordEntryDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>MasterPasswordEntryDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- a/Preferences/ConfigurationPages/NetworkPage.py	Thu Jun 16 16:29:27 2011 +0200
+++ b/Preferences/ConfigurationPages/NetworkPage.py	Sun Jun 19 15:19:46 2011 +0200
@@ -122,6 +122,15 @@
                 dn = dn[:-1]
             self.downloadDirEdit.setText(dn)
     
+    @pyqtSlot()
+    def on_clearProxyPasswordsButton_clicked(self):
+        """
+        Private slot to clear the saved proxy passwords.
+        """
+        Preferences.setUI("ProxyPassword/Http", "")
+        Preferences.setUI("ProxyPassword/Https", "")
+        Preferences.setUI("ProxyPassword/Ftp", "")
+    
 
 def create(dlg):
     """
--- a/Preferences/ConfigurationPages/NetworkPage.ui	Thu Jun 16 16:29:27 2011 +0200
+++ b/Preferences/ConfigurationPages/NetworkPage.ui	Sun Jun 19 15:19:46 2011 +0200
@@ -303,6 +303,16 @@
         </layout>
        </widget>
       </item>
+      <item>
+       <widget class="QPushButton" name="clearProxyPasswordsButton">
+        <property name="toolTip">
+         <string>Press to clear the saved proxy passwords</string>
+        </property>
+        <property name="text">
+         <string>Clear Proxy Passwords</string>
+        </property>
+       </widget>
+      </item>
      </layout>
     </widget>
    </item>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Preferences/ConfigurationPages/SecurityPage.py	Sun Jun 19 15:19:46 2011 +0200
@@ -0,0 +1,114 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the Security configuration page.
+"""
+
+from PyQt4.QtCore import pyqtSlot
+from PyQt4.QtGui import QDialog
+from PyQt4.QtWebKit import QWebSettings
+
+from .ConfigurationPageBase import ConfigurationPageBase
+from .Ui_SecurityPage import Ui_SecurityPage
+
+from .MasterPasswordEntryDialog import MasterPasswordEntryDialog
+
+import Preferences
+
+
+class SecurityPage(ConfigurationPageBase, Ui_SecurityPage):
+    """
+    Class implementing the Security configuration page.
+    """
+    def __init__(self, configDialog):
+        """
+        Constructor
+        
+        @param configDialog reference to the configuration dialog (ConfigurationDialog)
+        """
+        super().__init__()
+        self.setupUi(self)
+        self.setObjectName("SecurityPage")
+        
+        self.__configDlg = configDialog
+        
+        # set initial values
+        self.savePasswordsCheckBox.setChecked(
+            Preferences.getUser("SavePasswords"))
+        self.masterPasswordCheckBox.setChecked(
+            Preferences.getUser("UseMasterPassword"))
+        self.masterPasswordButton.setEnabled(
+            Preferences.getUser("UseMasterPassword"))
+        if hasattr(QWebSettings, "DnsPrefetchEnabled"):
+            self.dnsPrefetchCheckBox.setChecked(
+            Preferences.getHelp("DnsPrefetchEnabled"))
+        else:
+            self.dnsPrefetchCheckBox.setEnabled(False)
+        
+        self.__newPassword = ""
+        self.__oldUseMasterPassword = Preferences.getUser("UseMasterPassword")
+    
+    def save(self):
+        """
+        Public slot to save the Help Viewers configuration.
+        """
+        Preferences.setUser("SavePasswords",
+            self.savePasswordsCheckBox.isChecked())
+        Preferences.setUser("UseMasterPassword",
+            self.masterPasswordCheckBox.isChecked())
+        if self.dnsPrefetchCheckBox.isEnabled():
+            Preferences.setHelp("DnsPrefetchEnabled",
+                self.dnsPrefetchCheckBox.isChecked())
+        
+        if self.__oldUseMasterPassword != self.masterPasswordCheckBox.isChecked():
+            self.__configDlg.masterPasswordChanged.emit("", self.__newPassword)
+    
+    @pyqtSlot(bool)
+    def on_masterPasswordCheckBox_clicked(self, checked):
+        """
+        Private slot to handle the use of a master password.
+        
+        @param checked flag indicating the state of the check box (boolean)
+        """
+        if checked:
+            dlg = MasterPasswordEntryDialog("", self)
+            if dlg.exec_() == QDialog.Accepted:
+                Preferences.setUser("MasterPassword", 
+                    dlg.getMasterPassword())
+                self.masterPasswordButton.setEnabled(True)
+                self.__newPassword = dlg.getMasterPassword()
+            else:
+                self.masterPasswordCheckBox.setChecked(False)
+        else:
+            self.masterPasswordButton.setEnabled(False)
+            self.__newPassword = ""
+    
+    @pyqtSlot()
+    def on_masterPasswordButton_clicked(self):
+        """
+        Private slot to change the master password.
+        """
+        dlg = MasterPasswordEntryDialog(Preferences.getUser("MasterPassword"), self)
+        if dlg.exec_() == QDialog.Accepted:
+            Preferences.setUser("MasterPassword", 
+                dlg.getMasterPassword())
+            
+            if self.__oldUseMasterPassword != self.masterPasswordCheckBox.isChecked():
+                # the user is about to change the use of a master password
+                # just save the changed password
+                self.__newPassword = dlg.getMasterPassword()
+            else:
+                self.__configDlg.masterPasswordChanged.emit(
+                    dlg.getCurrentPassword(), dlg.getMasterPassword())
+
+def create(dlg):
+    """
+    Module function to create the configuration page.
+    
+    @param dlg reference to the configuration dialog
+    """
+    page = SecurityPage(dlg)
+    return page
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Preferences/ConfigurationPages/SecurityPage.ui	Sun Jun 19 15:19:46 2011 +0200
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SecurityPage</class>
+ <widget class="QWidget" name="SecurityPage">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_3">
+   <item>
+    <widget class="QLabel" name="headerLabel">
+     <property name="text">
+      <string>&lt;b&gt;Configure security settings&lt;/b&gt;</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="Line" name="line1">
+     <property name="frameShape">
+      <enum>QFrame::HLine</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Sunken</enum>
+     </property>
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>Passwords</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <widget class="QCheckBox" name="savePasswordsCheckBox">
+        <property name="toolTip">
+         <string>Select to save passwords</string>
+        </property>
+        <property name="text">
+         <string>Save passwords</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout">
+        <item>
+         <widget class="QCheckBox" name="masterPasswordCheckBox">
+          <property name="toolTip">
+           <string>Select to use a master password</string>
+          </property>
+          <property name="text">
+           <string>Use Master Password</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer_4">
+          <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>
+         <widget class="QPushButton" name="masterPasswordButton">
+          <property name="enabled">
+           <bool>false</bool>
+          </property>
+          <property name="toolTip">
+           <string>Press to change the master password</string>
+          </property>
+          <property name="text">
+           <string>Change Master Password...</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox_3">
+     <property name="title">
+      <string>DNS</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <item>
+       <widget class="QCheckBox" name="dnsPrefetchCheckBox">
+        <property name="toolTip">
+         <string>Select to enable DNS prefetch</string>
+        </property>
+        <property name="text">
+         <string>Use DNS prefetching to improve page loading</string>
+        </property>
+       </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>113</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>savePasswordsCheckBox</tabstop>
+  <tabstop>masterPasswordCheckBox</tabstop>
+  <tabstop>masterPasswordButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
--- a/Preferences/__init__.py	Thu Jun 16 16:29:27 2011 +0200
+++ b/Preferences/__init__.py	Sun Jun 19 15:19:46 2011 +0200
@@ -622,7 +622,6 @@
         "HomePage": "pyrc:home",
         "HistoryLimit": 30,
         "DefaultScheme": "file://",
-        "SavePasswords": False,
         "AdBlockEnabled": False,
         "AdBlockSubscriptions": [],
         "OfflineStorageDatabaseQuota": 50,     # 50 MB
@@ -740,6 +739,9 @@
         "MailServerUseTLS": False,
         "MailServerPort": 25,
         "UseSystemEmailClient": False,
+        "MasterPassword": "",           # stores the password hash
+        "UseMasterPassword": False,
+        "SavePasswords": False,
     }
     
     # defaults for vcs related stuff
@@ -1204,8 +1206,10 @@
             prefClass.uiDefaults[key]))
     elif key in ["ProxyPassword/Http", "ProxyPassword/Https",
                  "ProxyPassword/Ftp", ]:
-        from Utilities import pwDecode
-        return pwDecode(prefClass.settings.value("UI/" + key, prefClass.uiDefaults[key]))
+        from Utilities.crypto import pwConvert
+        return pwConvert(
+            prefClass.settings.value("UI/" + key, prefClass.uiDefaults[key]),
+            encode=False)
     elif key in ["LogStdErrColour"]:
         col = prefClass.settings.value("UI/" + key)
         if col is not None:
@@ -1280,8 +1284,8 @@
         prefClass.settings.setValue("UI/" + key, value.name())
     elif key in ["ProxyPassword/Http", "ProxyPassword/Https",
                  "ProxyPassword/Ftp", ]:
-        from Utilities import pwEncode
-        prefClass.settings.setValue("UI/" + key, pwEncode(value))
+        from Utilities.crypto import pwConvert
+        prefClass.settings.setValue("UI/" + key, pwConvert(value, encode=True))
     else:
         prefClass.settings.setValue("UI/" + key, value)
     
@@ -1941,7 +1945,7 @@
             prefClass.helpDefaults[key]))
     elif key in ["SingleHelpWindow", "SaveGeometry", "WebSearchSuggestions",
                  "DiskCacheEnabled", "FilterTrackingCookies", "PrintBackgrounds",
-                 "SavePasswords", "AdBlockEnabled", "AutoLoadImages",
+                 "AdBlockEnabled", "AutoLoadImages",
                  "JavaEnabled", "JavaScriptEnabled", "JavaScriptCanOpenWindows",
                  "JavaScriptCanAccessClipboard", "PluginsEnabled", "DnsPrefetchEnabled",
                  "OfflineStorageDatabaseEnabled", "OfflineWebApplicationCacheEnabled",
@@ -2099,14 +2103,15 @@
     @return the requested user setting
     """
     if key == "MailServerPassword":
-        from Utilities import pwDecode
-        return pwDecode(prefClass.settings.value("User/" + key,
-            prefClass.userDefaults[key]))
+        from Utilities.crypto import pwConvert
+        return pwConvert(prefClass.settings.value("User/" + key,
+            prefClass.userDefaults[key]), encode=False)
     elif key in ["MailServerPort"]:
         return int(prefClass.settings.value("User/" + key,
             prefClass.userDefaults[key]))
     elif key in ["MailServerAuthentication", "MailServerUseTLS",
-                 "UseSystemEmailClient"]:
+                 "UseSystemEmailClient", "UseMasterPassword",
+                 "SavePasswords"]:
         return toBool(prefClass.settings.value("User/" + key,
             prefClass.userDefaults[key]))
     else:
@@ -2122,9 +2127,13 @@
     @param prefClass preferences class used as the storage area
     """
     if key == "MailServerPassword":
-        from Utilities import pwEncode
+        from Utilities.crypto import pwConvert
         prefClass.settings.setValue(
-            "User/" + key, pwEncode(value))
+            "User/" + key, pwConvert(value, encode=True))
+    elif key == "MasterPassword":
+        from Utilities.crypto.py3PBKDF2 import hashPassword
+        prefClass.settings.setValue(
+            "User/" + key, hashPassword(value))
     else:
         prefClass.settings.setValue("User/" + key, value)
     
@@ -2473,6 +2482,29 @@
         return {}
     else:
         return value
+
+
+def convertPasswords(oldPassword, newPassword, prefClass=Prefs):
+    """
+    Module function to convert all passwords.
     
+    @param oldPassword current master password (string)
+    @param newPassword new master password (string)
+    @param prefClass preferences class used as the storage area
+    """
+    from Utilities.crypto import pwRecode
+    for key in ["ProxyPassword/Http", "ProxyPassword/Https",
+                "ProxyPassword/Ftp", ]:
+        prefClass.settings.setValue("UI/" + key, pwRecode(
+            prefClass.settings.value("UI/" + key, prefClass.uiDefaults[key]),
+            oldPassword,
+            newPassword))
+    for key in ["MailServerPassword"]:
+        prefClass.settings.setValue("User/" + key, pwRecode(
+            prefClass.settings.value("User/" + key, prefClass.userDefaults[key]),
+            oldPassword,
+            newPassword))
+
+
 initPreferences()
 initRecentSettings()
--- a/UI/UserInterface.py	Thu Jun 16 16:29:27 2011 +0200
+++ b/UI/UserInterface.py	Sun Jun 19 15:19:46 2011 +0200
@@ -38,6 +38,7 @@
 from PyUnit.UnittestDialog import UnittestDialog
 
 from Helpviewer.HelpWindow import HelpWindow
+from Helpviewer.Passwords.PasswordManager import PasswordManager
 
 from Preferences.ConfigurationDialog import ConfigurationDialog
 from Preferences.ViewProfileDialog import ViewProfileDialog
@@ -179,12 +180,15 @@
     @signal reloadAPIs() emitted to reload the api information
     @signal showMenu(str, QMenu) emitted when a menu is about to be shown. The name
             of the menu and a reference to the menu are given.
+    @signal masterPasswordChanged(str, str) emitted after the master
+            password has been changed with the old and the new password
     """
     appendStderr = pyqtSignal(str)
     appendStdout = pyqtSignal(str)
     preferencesChanged = pyqtSignal()
     reloadAPIs = pyqtSignal()
     showMenu = pyqtSignal(str, QMenu)
+    masterPasswordChanged = pyqtSignal(str, str)
     
     maxFilePathLen = 100
     maxSbFilePathLen = 150
@@ -4850,6 +4854,7 @@
                 self.helpWindow = help
                 self.helpWindow.helpClosed.connect(self.__helpClosed)
                 self.preferencesChanged.connect(self.helpWindow.preferencesChanged)
+                self.masterPasswordChanged.connect(self.helpWindow.masterPasswordChanged)
         elif searchWord is not None:
             self.helpWindow.search(searchWord)
             self.helpWindow.raise_()
@@ -4863,6 +4868,7 @@
         """
         if Preferences.getHelp("SingleHelpWindow"):
             self.preferencesChanged.disconnect(self.helpWindow.preferencesChanged)
+            self.masterPasswordChanged.disconnect(self.helpWindow.masterPasswordChanged)
             self.helpWindow = None
     
     def __helpViewer(self):
@@ -4889,6 +4895,7 @@
         """
         dlg = ConfigurationDialog(self, 'Configuration', True)
         dlg.preferencesChanged.connect(self.__preferencesChanged)
+        dlg.masterPasswordChanged.connect(self.__masterPasswordChanged)
         dlg.show()
         if pageName is not None:
             dlg.showConfigurationPageByName(pageName)
@@ -4953,6 +4960,21 @@
         
         self.preferencesChanged.emit()
         
+    
+    def __masterPasswordChanged(self, oldPassword, newPassword):
+        """
+        Private slot to handle the change of the master password.
+        
+        @param oldPassword current master password (string)
+        @param newPassword new master password (string)
+        """
+        self.masterPasswordChanged.emit(oldPassword, newPassword)
+        Preferences.convertPasswords(oldPassword, newPassword)
+        if self.helpWindow is None:
+            pwManager = PasswordManager()
+            pwManager.masterPasswordChanged(oldPassword, newPassword)
+        Utilities.crypto.changeRememberedMaster(newPassword)
+        
     def __reloadAPIs(self):
         """
         Private slot to reload the api information.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/PasswordChecker.py	Sun Jun 19 15:19:46 2011 +0200
@@ -0,0 +1,613 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a checker for password strength
+"""
+
+import re
+
+
+class PasswordChecker(object):
+    """
+    Class implementing a checker for password strength.
+    """
+    Complexity_VeryWeak = 0
+    Complexity_Weak = 1
+    Complexity_Good = 2
+    Complexity_Strong = 3
+    Complexity_VeryStrong = 4
+    
+    Status_Failed = 0
+    Status_Passed = 1
+    Status_Exceeded = 2
+    
+    def __init__(self):
+        """
+        Constructor
+        """
+        self.score = {
+            "count": 0,
+            "adjusted": 0,
+            "beforeRedundancy": 0
+        }
+        
+        # complexity index
+        self.complexity = {
+            "limits": [20, 50, 60, 80, 100],
+            "value": self.Complexity_VeryWeak
+        }
+        
+        # check categories follow
+        
+        # length of the password
+        self.passwordLength = {
+            "count": 0,
+            "minimum": 6,
+            "status": self.Status_Failed,
+            "rating": 0,
+            "factor": 0.5,      # per character bonus
+            "bonus": 10,        # minimum reached? Get a bonus.
+            "penalty": -20,     # if we stay under minimum, we get punished
+        }
+        
+        # recommended password length
+        self.recommendedPasswordLength = {
+            "count": 0,
+            "minimum": 8,
+            "status": self.Status_Failed,
+            "rating": 0,
+            "factor": 1.2,
+            "bonus": 10,
+            "penalty": -10,
+        }
+        
+        # Basic requirements are:
+        # 1) Password Length
+        # 2) Uppercase letter use
+        # 3) Lowercase letter use
+        # 4) Numeric character use
+        # 5) Symbol use
+        self.basicRequirements = {
+            "count": 0,
+            "minimum": 3,       # have to be matched to get the bonus
+            "status": self.Status_Failed,
+            "rating": 0,
+            "factor": 1.0,
+            "bonus": 10,
+            "penalty": -10,
+        }
+        
+        # how much redundancy is permitted, if the password is
+        # long enough. we will skip the redudancy penalty if this
+        # number is not exceeded (meaning redundancy < this number)
+        self.redundancy = {
+            "value": 1,         # 1 means, not double characters, default to start
+            "permitted": 2.0,   # 2 means, in average every character can occur twice
+            "status": self.Status_Failed,
+            "rating": 0,
+        }
+        
+        # number of uppercase letters, such as A-Z
+        self.uppercaseLetters = {
+            "count": 0,
+            "minimum": 1,
+            "status": self.Status_Failed,
+            "rating": 0,
+            "factor": 0.0,
+            "bonus": 10,
+            "penalty": -10,
+        }
+        
+        # number of lowercase letters, such as a-z 
+        self.lowercaseLetters = {
+            "count": 0,
+            "minimum": 1,
+            "status": self.Status_Failed,
+            "rating": 0,
+            "factor": 0.0,
+            "bonus": 10,
+            "penalty": -10,
+        }
+        
+        # number of numeric characters
+        self.numerics = {
+            "count": 0,
+            "minimum": 1,
+            "status": self.Status_Failed,
+            "rating": 0,
+            "factor": 0.0,
+            "bonus": 10,
+            "penalty": -10,
+        }
+        
+        # number of symbol characters
+        self.symbols = {
+            "count": 0,
+            "minimum": 1,
+            "status": self.Status_Failed,
+            "rating": 0,
+            "factor": 0.0,
+            "bonus": 10,
+            "penalty": -10,
+        }
+        
+        # number of dedicated symbols in the middle
+        self.middleSymbols = {
+            "count": 0,
+            "minimum": 1,
+            "status": self.Status_Failed,
+            "rating": 0,
+            "factor": 0.0,
+            "bonus": 10,
+            "penalty": -10,
+        }
+        
+        # number of dedicated numbers in the middle
+        self.middleNumerics = {
+            "count": 0,
+            "minimum": 1,
+            "status": self.Status_Failed,
+            "rating": 0,
+            "factor": 0.0,
+            "bonus": 10,
+            "penalty": -10,
+        }
+        
+        # how many sequential characters should be checked
+        # such as "abc" or "MNO" to be not part of the password
+        self.sequentialLetters = {
+            "data": "abcdefghijklmnopqrstuvwxyz",
+            "length": 3,
+            
+            "count": 0,
+            "status": self.Status_Failed,
+            "rating": 0,
+            "factor": -1.0,
+            "bonus": 0,
+            "penalty": -10,
+        }
+        
+        # how many sequential characters should be checked
+        # such as "123" to be not part of the password
+        self.sequentialNumerics = {
+            "data": "0123456789",
+            "length": 3,
+            
+            "count": 0,
+            "status": self.Status_Failed,
+            "rating": 0,
+            "factor": -1.0,
+            "bonus": 0,
+            "penalty": -10,
+        }
+        
+        # keyboard patterns to check, typical sequences from your
+        # keyboard
+        self.keyboardPatterns = {
+            # German and English keyboard text
+            "data": [
+                "qwertzuiop", "asdfghjkl", "yxcvbnm", "!\"§$%&/()=",    # de
+                "1234567890",   # de numbers
+                "qaywsxedcrfvtgbzhnujmik,ol.pö-üä+#",   # de up-down
+                
+                "qwertyuiop", "asdfghjkl", "zyxcvbnm", "!@#$%^&*()_",   # en
+                "1234567890",   # en numbers
+                "qazwsxedcrfvtgbyhnujmik,ol.p;/[']\\",  # en up-down
+            ],
+            "length": 4,    # how long is the pattern to check and blame for?
+            
+            "count": 0,     # how many of these pattern can be found
+            "status": self.Status_Failed,
+            "rating": 0,
+            "factor": -1.0,     # each occurrence is punished with that factor
+            "bonus": 0,
+            "penalty": -10,
+        }
+        
+        # check for repeated sequences, like in catcat
+        self.repeatedSequences = {
+            "length": 3,
+            
+            "count": 0,
+            "status": self.Status_Failed,
+            "rating": 0,
+            "factor": 0.0,
+            "bonus": 0,
+            "penalty": -10,
+        }
+        
+        # check for repeated mirrored sequences, like in tactac
+        self.mirroredSequences = {
+            "length": 3,
+            
+            "count": 0,
+            "status": self.Status_Failed,
+            "rating": 0,
+            "factor": 0.0,
+            "bonus": 0,
+            "penalty": -10,
+        }
+        
+        self.uppercaseRe = re.compile("[A-Z]")
+        self.lowercaseRe = re.compile("[a-z]")
+        self.numberRe = re.compile("[0-9]")
+        self.symbolRe = re.compile("[^a-zA-Z0-9]")
+    
+    def __strReverse(self, string):
+        """
+        Private method to reverse a string.
+        
+        @param string string to be reversed (string)
+        @return reversed string (string)
+        """
+        return "".join(reversed(string))
+    
+    def __determineStatus(self, value):
+        """
+        Private method to determine the status.
+        
+        @param value value to check (integer)
+        @return status (Status_Failed, Status_Passed, Status_Exceeded)
+        """
+        if value == 0:
+            return self.Status_Passed
+        elif value > 0:
+            return self.Status_Exceeded
+        else:
+            return self.Status_Failed
+    
+    def __determineBinaryStatus(self, value):
+        """
+        Private method to determine a binary status.
+        
+        @param value value to check (integer)
+        @return status (Status_Failed, Status_Passed)
+        """
+        if value == 0:
+            return self.Status_Passed
+        else:
+            return self.Status_Failed
+    
+    def checkPassword(self, password):
+        """
+        Public method to check a given password.
+        
+        @param password password to be checked (string)
+        @return indication for the password strength (Complexity_VeryWeak,
+            Complexity_Weak, Complexity_Good, Complexity_Strong,
+            Complexity_VeryStrong)
+        """
+        # how long is the password?
+        self.passwordLength["count"] = len(password)
+        self.recommendedPasswordLength["count"] = len(password)
+        
+        # Loop through password to check for Symbol, Numeric, Lowercase 
+        # and Uppercase pattern matches
+        for index in range(len(password)):
+            if self.uppercaseRe.match(password[index]):
+                self.uppercaseLetters["count"] += 1
+            elif self.lowercaseRe.match(password[index]):
+                self.lowercaseLetters["count"] += 1
+            elif self.numberRe.match(password[index]):
+                if index > 0 and index < len(password) - 1:
+                    self.middleNumerics["count"] += 1
+                self.numerics["count"] += 1
+            elif self.symbolRe.match(password[index]):
+                if index > 0 and index < len(password) - 1:
+                    self.middleSymbols["count"] += 1
+                self.symbols["count"] += 1
+        
+        # check the variance of symbols or better the redundancy
+        # makes only sense for at least two characters
+        if len(password) > 1:
+            uniqueCharacters = []
+            for index1 in range(len(password)):
+                found = False
+                for index2 in range(index1 + 1, len(password)):
+                    if password[index1] == password[index2]:
+                        found = True
+                        break
+                if not found:
+                    uniqueCharacters.append(password[index1] )
+            
+            # calculate a redundancy number
+            self.redundancy["value"] = len(password) / len(uniqueCharacters)
+        
+        # Check for sequential alpha string patterns (forward and reverse) but only,
+        # if the string has already a length to check for, does not make sense to check
+        # the password "ab" for the sequential data "abc"
+        lowercasedPassword = password.lower();
+        
+        if self.passwordLength["count"] >= self.sequentialLetters["length"]:
+            for index in range(len(self.sequentialLetters["data"]) - \
+                               self.sequentialLetters["length"] + 1):
+                fwd = self.sequentialLetters["data"][
+                    index:index + self.sequentialLetters["length"]]
+                rev = self.__strReverse(fwd)
+                if lowercasedPassword.find(fwd) != -1:
+                    self.sequentialLetters["count"] += 1
+                if lowercasedPassword.find(rev) != -1:
+                    self.sequentialLetters["count"] += 1
+        
+        # Check for sequential numeric string patterns (forward and reverse)
+        if self.passwordLength["count"] >= self.sequentialNumerics["length"]:
+            for index in range(len(self.sequentialNumerics["data"]) - \
+                               self.sequentialNumerics["length"] + 1):
+                fwd = self.sequentialNumerics["data"][
+                    index:index + self.sequentialNumerics["length"]]
+                rev = self.__strReverse(fwd)
+                if lowercasedPassword.find(fwd) != -1:
+                    self.sequentialNumerics["count"] += 1
+                if lowercasedPassword.find(rev) != -1:
+                    self.sequentialNumerics["count"] += 1
+        
+        # Check common keyboard patterns
+        patternsMatched = []
+        if self.passwordLength["count"] >= self.keyboardPatterns["length"]:
+            for pattern in self.keyboardPatterns["data"]:
+                for index in range(len(pattern)- self.keyboardPatterns["length"] + 1):
+                    fwd = pattern[index:index + self.keyboardPatterns["length"]]
+                    rev = self.__strReverse(fwd)
+                    if lowercasedPassword.find(fwd) != -1:
+                        if fwd not in patternsMatched:
+                            self.keyboardPatterns["count"] += 1
+                            patternsMatched.append(fwd)
+                    if lowercasedPassword.find(rev) != -1:
+                        if fwd not in patternsMatched:
+                            self.keyboardPatterns["count"] += 1
+                            patternsMatched.append(rev)
+        
+        # Try to find repeated sequences of characters.
+        if self.passwordLength["count"] >= self.repeatedSequences["length"]:
+            for index in range(len(lowercasedPassword) - \
+                               self.repeatedSequences["length"] + 1):
+                fwd = lowercasedPassword[index:index + self.repeatedSequences["length"]]
+                if lowercasedPassword.find(
+                   fwd, index + self.repeatedSequences["length"]) != -1:
+                    self.repeatedSequences["count"] += 1
+        
+        # Try to find mirrored sequences of characters.
+        if self.passwordLength["count"] >= self.mirroredSequences["length"]:
+            for index in range(len(lowercasedPassword) - \
+                               self.mirroredSequences["length"] + 1):
+                fwd = lowercasedPassword[index:index + self.mirroredSequences["length"]]
+                rev = self.__strReverse(fwd)
+                if lowercasedPassword.find(
+                   fwd, index + self.mirroredSequences["length"]) != -1:
+                    self.mirroredSequences["count"] += 1
+        
+        # Initial score based on length
+        self.score["count"] = self.passwordLength["count"] * self.passwordLength["factor"]
+        
+        # passwordLength
+        # credit additional length or punish "under" length
+        if self.passwordLength["count"] >= self.passwordLength["minimum"]:
+            # credit additional characters over minimum
+            self.passwordLength["rating"] = self.passwordLength["bonus"] + \
+                (self.passwordLength["count"] - self.passwordLength["minimum"]) * \
+                self.passwordLength["factor"]
+        else:
+            self.passwordLength["rating"] = self.passwordLength["penalty"]
+        self.score["count"] += self.passwordLength["rating"]
+        
+        # recommendedPasswordLength
+        # Credit reaching the recommended password length or put a 
+        # penalty on it
+        if self.passwordLength["count"] >= self.recommendedPasswordLength["minimum"]:
+            self.recommendedPasswordLength["rating"] = \
+                self.recommendedPasswordLength["bonus"] + \
+                (self.passwordLength["count"] - \
+                 self.recommendedPasswordLength["minimum"]) * \
+                self.recommendedPasswordLength["factor"]
+        else:
+            self.recommendedPasswordLength["rating"] = \
+                self.recommendedPasswordLength["penalty"]
+        self.score["count"] += self.recommendedPasswordLength["rating"]
+        
+        # lowercaseLetters
+        # Honor or punish the lowercase letter use
+        if self.lowercaseLetters["count"] > 0:
+            self.lowercaseLetters["rating"] = self.lowercaseLetters["bonus"] + \
+                self.lowercaseLetters["count"] * self.lowercaseLetters["factor"]
+        else:
+            self.lowercaseLetters["rating"] = self.lowercaseLetters["penalty"]
+        self.score["count"] += self.lowercaseLetters["rating"]
+        
+        # uppercaseLetters
+        # Honor or punish the lowercase letter use
+        if self.uppercaseLetters["count"] > 0:
+            self.uppercaseLetters["rating"] = self.uppercaseLetters["bonus"] + \
+                self.uppercaseLetters["count"] * self.uppercaseLetters["factor"]
+        else:
+            self.uppercaseLetters["rating"] = self.uppercaseLetters["penalty"]
+        self.score["count"] += self.uppercaseLetters["rating"]
+        
+        # numerics
+        # Honor or punish the numerics use
+        if self.numerics["count"] > 0:
+            self.numerics["rating"] = self.numerics["bonus"] + \
+                self.numerics["count"] * self.numerics["factor"]
+        else:
+            self.numerics["rating"] = self.numerics["penalty"]
+        self.score["count"] += self.numerics["rating"]
+        
+        # symbols
+        # Honor or punish the symbols use
+        if self.symbols["count"] > 0:
+            self.symbols["rating"] = self.symbols["bonus"] + \
+                self.symbols["count"] * self.symbols["factor"]
+        else:
+            self.symbols["rating"] = self.symbols["penalty"]
+        self.score["count"] += self.symbols["rating"]
+        
+        # middleSymbols
+        # Honor or punish the middle symbols use
+        if self.middleSymbols["count"] > 0:
+            self.middleSymbols["rating"] = self.middleSymbols["bonus"] + \
+                self.middleSymbols["count"] * self.middleSymbols["factor"]
+        else:
+            self.middleSymbols["rating"] = self.middleSymbols["penalty"]
+        self.score["count"] += self.middleSymbols["rating"]
+        
+        # middleNumerics
+        # Honor or punish the middle numerics use
+        if self.middleNumerics["count"] > 0:
+            self.middleNumerics["rating"] = self.middleNumerics["bonus"] + \
+                self.middleNumerics["count"] * self.middleNumerics["factor"]
+        else:
+            self.middleNumerics["rating"] = self.middleNumerics["penalty"]
+        self.score["count"] += self.middleNumerics["rating"]
+        
+        # sequentialLetters
+        # Honor or punish the sequential letter use
+        if self.sequentialLetters["count"] == 0:
+            self.sequentialLetters["rating"] = self.sequentialLetters["bonus"] + \
+                self.sequentialLetters["count"] * self.sequentialLetters["factor"]
+        else:
+            self.sequentialLetters["rating"] = self.sequentialLetters["penalty"]
+        self.score["count"] += self.sequentialLetters["rating"]
+        
+        # sequentialNumerics
+        # Honor or punish the sequential numerics use
+        if self.sequentialNumerics["count"] == 0:
+            self.sequentialNumerics["rating"] = self.sequentialNumerics["bonus"] + \
+                self.sequentialNumerics["count"] * self.sequentialNumerics["factor"]
+        else:
+            self.sequentialNumerics["rating"] = self.sequentialNumerics["penalty"]
+        self.score["count"] += self.sequentialNumerics["rating"]
+        
+        # keyboardPatterns
+        # Honor or punish the keyboard patterns use
+        if self.keyboardPatterns["count"] == 0:
+            self.keyboardPatterns["rating"] = self.keyboardPatterns["bonus"] + \
+                self.keyboardPatterns["count"] * self.keyboardPatterns["factor"]
+        else:
+            self.keyboardPatterns["rating"] = self.keyboardPatterns["penalty"]
+        self.score["count"] += self.keyboardPatterns["rating"]
+        
+        # Count our basicRequirements and set the status
+        self.basicRequirements["count"] = 0
+        
+        # password length
+        self.passwordLength["status"] = self.__determineStatus(
+            self.passwordLength["count"] - self.passwordLength["minimum"])
+        if self.passwordLength["status"] != self.Status_Failed:
+            # requirement met
+            self.basicRequirements["count"] += 1
+        
+        # uppercase letters
+        self.uppercaseLetters["status"] = self.__determineStatus(
+            self.uppercaseLetters["count"] - self.uppercaseLetters["minimum"])
+        if self.uppercaseLetters["status"] != self.Status_Failed:
+            # requirement met
+            self.basicRequirements["count"] += 1
+        
+        # lowercase letters
+        self.lowercaseLetters["status"] = self.__determineStatus(
+            self.lowercaseLetters["count"] - self.lowercaseLetters["minimum"])
+        if self.lowercaseLetters["status"] != self.Status_Failed:
+            # requirement met
+            self.basicRequirements["count"] += 1
+        
+        # numerics
+        self.numerics["status"] = self.__determineStatus(
+            self.numerics["count"] - self.numerics["minimum"])
+        if self.numerics["status"] != self.Status_Failed:
+            # requirement met
+            self.basicRequirements["count"] += 1
+        
+        # symbols
+        self.symbols["status"] = self.__determineStatus(
+            self.symbols["count"] - self.symbols["minimum"])
+        if self.symbols["status"] != self.Status_Failed:
+            # requirement met
+            self.basicRequirements["count"] += 1
+        
+        # judge the requirement status
+        self.basicRequirements["status"] = self.__determineStatus(
+            self.basicRequirements["count"] - self.basicRequirements["minimum"])
+        if self.basicRequirements["status"] != self.Status_Failed:
+            self.basicRequirements["rating"] = \
+                self.basicRequirements["bonus"] + \
+                self.basicRequirements["factor"] * self.basicRequirements["count"]
+        else:
+            self.basicRequirements["rating"] = self.basicRequirements["penalty"]
+        self.score["count"] += self.basicRequirements["rating"]
+        
+        # beyond basic requirements
+        self.recommendedPasswordLength["status"] = self.__determineStatus(
+            self.recommendedPasswordLength["count"] - \
+                self.recommendedPasswordLength["minimum"])
+        self.middleNumerics["status"] = self.__determineStatus(
+            self.middleNumerics["count"] - \
+                self.middleNumerics["minimum"])
+        self.middleSymbols["status"] = self.__determineStatus(
+            self.middleSymbols["count"] - \
+                self.middleSymbols["minimum"])
+        self.sequentialLetters["status"] = self.__determineBinaryStatus(
+            self.sequentialLetters["count"])
+        self.sequentialNumerics["status"] = self.__determineBinaryStatus(
+            self.sequentialNumerics["count"])
+        self.keyboardPatterns["status"] = self.__determineBinaryStatus(
+            self.keyboardPatterns["count"])
+        self.repeatedSequences["status"] = self.__determineBinaryStatus(
+            self.repeatedSequences["count"])
+        self.mirroredSequences["status"] = self.__determineBinaryStatus(
+            self.mirroredSequences["count"])
+        
+        # we apply them only, if the length is not awesome
+        if self.recommendedPasswordLength["status"] != self.Status_Exceeded:
+            # repeatedSequences
+            # Honor or punish the use of repeated sequences
+            if self.repeatedSequences["count"] == 0:
+                self.repeatedSequences["rating"] = self.repeatedSequences["bonus"]
+            else:
+                self.repeatedSequences["rating"] = self.repeatedSequences["penalty"] + \
+                    self.repeatedSequences["count"] * \
+                    self.repeatedSequences["factor"]
+            
+            # mirroredSequences
+            # Honor or punish the use of mirrored sequences
+            if self.mirroredSequences["count"] == 0:
+                self.mirroredSequences["rating"] = self.mirroredSequences["bonus"]
+            else:
+                self.mirroredSequences["rating"] = self.mirroredSequences["penalty"] + \
+                    self.mirroredSequences["count"] * \
+                    self.mirroredSequences["factor"]
+        
+        # save value before redundancy
+        self.score["beforeRedundancy"] = self.score["count"]
+        
+        # apply the redundancy
+        # is the password length requirement fulfilled?
+        if self.recommendedPasswordLength["status"] != self.Status_Exceeded:
+            # full penalty, because password is not long enough, only for a positive score
+            if self.score["count"] > 0:
+                self.score["count"] *= 1.0 / self.redundancy["value"]
+        
+        # level it out
+        if self.score["count"] > 100:
+            self.score["adjusted"] = 100
+        elif self.score["count"] < 0:
+            self.score["adjusted"] = 0
+        else:
+            self.score["adjusted"] = self.score["count"]
+        
+        # judge it
+        for index in range(len(self.complexity["limits"])):
+            if self.score["adjusted"] <= self.complexity["limits"][index]:
+                self.complexity["value"] = index
+                break
+        
+        return self.complexity["value"]
+
+if __name__ == "__main__":
+    while True:
+        try:
+            pwd = input("Enter password: ")
+            print(pwd, PasswordChecker().checkPassword(pwd))
+        except KeyboardInterrupt:
+            break
--- a/Utilities/__init__.py	Thu Jun 16 16:29:27 2011 +0200
+++ b/Utilities/__init__.py	Sun Jun 19 15:19:46 2011 +0200
@@ -12,8 +12,6 @@
 import re
 import fnmatch
 import glob
-import random
-import base64
 import getpass
 
 
@@ -1206,8 +1204,8 @@
         be empty, if a syntax error was detected by the syntax checker.
     """
     interpreter = Preferences.getDebugger("PythonInterpreter")
-    if interpreter == "" or not isExecutable(interpreter):
-        return (True, file, "1", "",
+    if interpreter == "" or not isinpath(interpreter):
+        return (True, file, "1", "0", "",
             QCoreApplication.translate("Utilities",
                                        "Python2 interpreter not configured."),
             [])
@@ -1517,36 +1515,6 @@
     return True
 
 ################################################################################
-# password handling functions below
-################################################################################
-
-
-def pwEncode(pw):
-    """
-    Module function to encode a password.
-    
-    @param pw password to encode (string)
-    @return encoded password (string)
-    """
-    pop = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,;:-_!$?*+#"
-    marker = "CE4"
-    rpw = "".join(random.sample(pop, 32)) + pw + "".join(random.sample(pop, 32))
-    return marker + base64.b64encode(rpw.encode()).decode()
-
-
-def pwDecode(epw):
-    """
-    Module function to decode a password.
-    
-    @param pw encoded password to decode (string)
-    @return decoded password (string)
-    """
-    if not epw.startswith("CE4"):
-        return epw  # it was not encoded using pwEncode
-    
-    return base64.b64decode(epw[3:].encode())[32:-32].decode()
-
-################################################################################
 # posix compatibility functions below
 ################################################################################
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/crypto/__init__.py	Sun Jun 19 15:19:46 2011 +0200
@@ -0,0 +1,315 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Package implementing cryptography related functionality.
+"""
+
+##import os
+##import sys
+##sys.path.insert(1, os.path.join(os.path.dirname(__file__), "../.."))
+##
+import random
+import base64
+
+from PyQt4.QtCore import QCoreApplication
+from PyQt4.QtGui import QLineEdit, QInputDialog
+
+from E5Gui import E5MessageBox
+
+from .py3AES import encryptData, decryptData
+from .py3PBKDF2 import verifyPassword, hashPasswordTuple, rehashPassword
+##from py3AES import encryptData, decryptData
+##from py3PBKDF2 import verifyPassword, hashPasswordTuple, rehashPassword
+
+import Preferences
+
+################################################################################
+## password handling functions below
+################################################################################
+
+
+EncodeMarker = "CE4"
+CryptoMarker = "CR5"
+
+Delimiter = "$"
+
+MasterPassword = None
+
+
+def pwEncode(pw):
+    """
+    Module function to encode a password.
+    
+    @param pw password to encode (string)
+    @return encoded password (string)
+    """
+    pop = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,;:-_!$?*+#"
+    rpw = "".join(random.sample(pop, 32)) + pw + "".join(random.sample(pop, 32))
+    return EncodeMarker + base64.b64encode(rpw.encode("utf-8")).decode("ascii")
+
+
+def pwDecode(epw):
+    """
+    Module function to decode a password.
+    
+    @param epw encoded password to decode (string)
+    @return decoded password (string)
+    """
+    if not epw.startswith(EncodeMarker):
+        return epw  # it was not encoded using pwEncode
+    
+    return base64.b64decode(epw[3:].encode("ascii"))[32:-32].decode("utf-8")
+
+
+##def passwordHash(pw):
+##    """
+##    Module function to calculate the hash for the given password.
+##    
+##    This is done by hashing it 65.000 times with SHA1 in order to make brute force
+##    attacks a bit harder.
+##    
+##    @param pw password to be hashed (string)
+##    @return password hash (string)
+##    """
+##    hash = QCryptographicHash.hash(QByteArray(pw.encode("utf-8")),
+##                                   QCryptographicHash.Sha1)
+##    for i in range(65000):
+##        hash = QCryptographicHash.hash(hash, QCryptographicHash.Sha1)
+##    return base64.b64encode(bytes(hash)).decode("ascii")
+##
+##
+##def generateCryptoKey(pw, keyLength=32):
+##    """
+##    Module function to calculate a crypto key given a password.
+##    
+##    This is done by hashing the password 32.000 times MD5 and 32.000 times with MD4.
+##    These hashes are concatenated and and the first bytes are taken depending on the
+##    desired key length.
+##    
+##    @param pw password to be used (string)
+##    @param keyLength length of the desired key (16, 24 or 32) (default is
+##        32 bytes suitable for AES256 encryption)
+##    @return crypto key (bytes)
+##    """
+##    if keyLength not in [16, 24, 32]:
+##        raise ValueError(QCoreApplication.translate(
+##            "Crypto", "Illegal key length ({0}) given.").format(keyLength))
+##    
+##    hash1 = QCryptographicHash.hash(QByteArray(pw.encode("utf-8")),
+##                                    QCryptographicHash.Md5)
+##    hash2 = QCryptographicHash.hash(QByteArray(pw.encode("utf-8")),
+##                                    QCryptographicHash.Md4)
+##    for i in range(32000):
+##        hash1 = QCryptographicHash.hash(hash1, QCryptographicHash.Md5)
+##        hash2 = QCryptographicHash.hash(hash2, QCryptographicHash.Md4)
+##    hash = (hash1 + hash2)[:keyLength]
+##    return bytes(hash)
+
+
+def __getMasterPassword():
+    """
+    Private module function to get the password from the user.
+    """
+    global MasterPassword
+    
+    pw, ok = QInputDialog.getText(
+        None,
+        QCoreApplication.translate("Crypto", "Master Password"),
+        QCoreApplication.translate("Crypto", "Enter the master password:"),
+        QLineEdit.Password)
+    if ok:
+        masterPassword = Preferences.getUser("MasterPassword")
+        try:
+            if masterPassword:
+                if verifyPassword(pw, masterPassword):
+                    MasterPassword = pwEncode(pw)
+                else:
+                    E5MessageBox.warning(None,
+                        QCoreApplication.translate("Crypto", "Master Password"),
+                        QCoreApplication.translate("Crypto", 
+                            """The given password is incorrect."""))
+            else:
+                E5MessageBox.critical(None,
+                    QCoreApplication.translate("Crypto", "Master Password"),
+                    QCoreApplication.translate("Crypto", 
+                        """There is no master password registered."""))
+        except ValueError as why:
+            E5MessageBox.warning(None,
+                QCoreApplication.translate("Crypto", "Master Password"),
+                QCoreApplication.translate("Crypto",
+                    """<p>The given password cannot be verified.</p>"""
+                    """<p>Reason: {0}""".format(str(why))))
+
+
+def pwEncrypt(pw, masterPW=None):
+    """
+    Module function to encrypt a password.
+    
+    @param pw password to encrypt (string)
+    @param masterPW password to be used for encryption (string)
+    @return encrypted password (string) and flag indicating
+        success (boolean)
+    """
+    if masterPW is None:
+        if MasterPassword is None:
+            __getMasterPassword()
+            if MasterPassword is None:
+                return "", False
+        
+        masterPW = pwDecode(MasterPassword)
+    
+    digestname, iterations, salt, hash = hashPasswordTuple(masterPW)
+    key = hash[:32]
+    try:
+        cipher = encryptData(key, pw.encode("utf-8"))
+    except ValueError:
+        return "", False
+    return CryptoMarker + Delimiter.join([
+        digestname,
+        str(iterations),
+        base64.b64encode(salt).decode("ascii"),
+        base64.b64encode(cipher).decode("ascii")
+    ]), True
+
+
+def pwDecrypt(epw, masterPW=None):
+    """
+    Module function to decrypt a password.
+    
+    @param epw hashed password to decrypt (string)
+    @param masterPW password to be used for encryption (string)
+    @return decrypted password (string) and flag indicating
+        success (boolean)
+    """
+    if not epw.startswith(CryptoMarker):
+        return epw, False  # it was not encoded using pwEncrypt
+    
+    if masterPW is None:
+        if MasterPassword is None:
+            __getMasterPassword()
+            if MasterPassword is None:
+                return "", False
+        
+        masterPW = pwDecode(MasterPassword)
+    
+    hashParameters, epw = epw[3:].rsplit(Delimiter, 1)
+    try:
+        # recreate the key used to encrypt
+        key = rehashPassword(masterPW, hashParameters)[:32]
+        plaintext = decryptData(key, base64.b64decode(epw.encode("ascii")))
+    except ValueError:
+        return "", False
+    return plaintext.decode("utf-8"), True
+
+
+def pwReencrypt(epw, oldPassword, newPassword):
+    """
+    Module function to re-encrypt a password.
+    
+    @param epw hashed password to re-encrypt (string)
+    @param oldPassword password used to encrypt (string)
+    @param newPassword new password to be used (string)
+    @return encrypted password (string) and flag indicating
+        success (boolean)
+    """
+    plaintext, ok = pwDecrypt(epw, oldPassword)
+    if ok:
+        return pwEncrypt(plaintext, newPassword)
+    else:
+        return "", False
+
+
+def pwRecode(epw, oldPassword, newPassword):
+    """
+    Module function to re-encode a password.
+    
+    In case of an error the encoded password is returned unchanged.
+    
+    @param epw encoded password to re-encode (string)
+    @param oldPassword password used to encode (string)
+    @param newPassword new password to be used (string)
+    @return encoded password (string)
+    """
+    if epw == "":
+        return epw
+    
+    if newPassword == "":
+        plaintext, ok = pwDecrypt(epw)
+        return (pwEncode(plaintext) if ok else epw)
+    else:
+        if oldPassword == "":
+            plaintext = pwDecode(epw)
+            cipher, ok = pwEncrypt(plaintext, newPassword)
+            return (cipher if ok else epw)
+        else:
+            npw, ok = pwReencrypt(epw, oldPassword, newPassword)
+            return (npw if ok else epw)
+
+
+def pwConvert(pw, encode=True):
+    """
+    Module function to convert a plaintext password to the encoded form or
+    vice versa.
+    
+    If there is an error, an empty code is returned for the encode function
+    or the given encoded password for the decode function.
+    
+    @param pw password to encode (string)
+    @param encode flag indicating an encode or decode function (boolean)
+    @return encode or decoded password (string)
+    """
+    if pw == "":
+        return pw
+    
+    if encode:
+        # plain text -> encoded
+        if Preferences.getUser("UseMasterPassword"):
+            epw = pwEncrypt(pw)[0]
+        else:
+            epw = pwEncode(pw)
+        return epw
+    else:
+        # encoded -> plain text
+        if Preferences.getUser("UseMasterPassword"):
+            plain, ok = pwDecrypt(pw)
+        else:
+            plain, ok = pwDecode(pw), True
+        return (plain if ok else pw)
+
+
+def changeRememberedMaster(newPassword):
+    """
+    Module function to change the remembered master password.
+    
+    @param newPassword new password to be used (string)
+    """
+    global MasterPassword
+    
+    if newPassword == "":
+        MasterPassword = None
+    else:
+        MasterPassword = pwEncode(newPassword)
+    
+if __name__ == "__main__":
+    import sys
+    from PyQt4.QtGui import QApplication
+    
+    app = QApplication([])
+    
+    mpw = "blahblah"
+    cpw = "SomeSecret"
+    
+    cipher, ok = pwEncrypt(cpw)
+    print(ok, cipher)
+    plain, ok = pwDecrypt(cipher)
+    print(ok, plain)
+    
+    cipher, ok = pwEncrypt(cpw, mpw)
+    print(ok, cipher)
+    plain, ok = pwDecrypt(cipher, mpw)
+    print(ok, plain)
+    
+    sys.exit(0)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/crypto/py3AES.py	Sun Jun 19 15:19:46 2011 +0200
@@ -0,0 +1,835 @@
+#!/usr/bin/python3
+#
+# aes.py: implements AES - Advanced Encryption Standard
+# from the SlowAES project, http://code.google.com/p/slowaes/
+#
+# Copyright (c) 2008    Josh Davis ( http://www.josh-davis.org ),
+#           Alex Martelli ( http://www.aleax.it )
+#
+# Ported from C code written by Laurent Haan ( http://www.progressive-coding.com )
+#
+# Licensed under the Apache License, Version 2.0
+# http://www.apache.org/licenses/
+#
+
+#
+# Ported to Python3
+#
+# Copyright (c) 2011 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing classes for encryption according
+Advanced Encryption Standard.
+"""
+
+import os
+import math
+
+
+def append_PKCS7_padding(b):
+    """
+    Function to pad the given data to a multiple of 16-bytes by PKCS7 padding.
+    
+    @param b data to be padded (bytes)
+    @return padded data (bytes)
+    """
+    numpads = 16 - (len(b) % 16)
+    return b + numpads * bytes(chr(numpads), encoding="ascii")
+
+
+def strip_PKCS7_padding(b):
+    """
+    Function to strip off PKCS7 padding.
+    
+    @param b data to be stripped (bytes)
+    @return stripped data (bytes)
+    """
+    if len(b) % 16 or not b:
+        raise ValueError("Data of len {0} can't be PCKS7-padded".format(len(b)))
+    numpads = b[-1]
+    if numpads > 16:
+        raise ValueError("Data ending with {0} can't be PCKS7-padded".format(b[-1]))
+    return b[:-numpads]
+
+
+class AES(object):
+    """
+    Class implementing the Advanced Encryption Standard algorithm.
+    """
+    # valid key sizes
+    KeySize = {
+        "SIZE_128": 16,
+        "SIZE_192": 24,
+        "SIZE_256": 32,
+    }
+
+    # Rijndael S-box
+    sbox = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67,
+            0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59,
+            0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7,
+            0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1,
+            0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05,
+            0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83,
+            0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29,
+            0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+            0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa,
+            0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c,
+            0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc,
+            0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
+            0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19,
+            0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee,
+            0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49,
+            0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+            0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4,
+            0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6,
+            0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70,
+            0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9,
+            0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e,
+            0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1,
+            0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0,
+            0x54, 0xbb, 0x16]
+
+    # Rijndael Inverted S-box
+    rsbox = [0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3,
+             0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f,
+             0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54,
+             0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b,
+             0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24,
+             0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8,
+             0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d,
+             0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
+             0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab,
+             0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3,
+             0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1,
+             0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41,
+             0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6,
+             0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9,
+             0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d,
+             0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
+             0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0,
+             0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07,
+             0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60,
+             0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f,
+             0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5,
+             0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b,
+             0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55,
+             0x21, 0x0c, 0x7d]
+
+    # Rijndael Rcon
+    Rcon = [0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
+            0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97,
+            0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72,
+            0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66,
+            0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
+            0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d,
+            0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
+            0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61,
+            0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
+            0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
+            0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc,
+            0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5,
+            0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a,
+            0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d,
+            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
+            0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
+            0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4,
+            0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
+            0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08,
+            0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
+            0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d,
+            0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2,
+            0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74,
+            0xe8, 0xcb]
+
+    def __getSBoxValue(self, num):
+        """
+        Private method to retrieve a given S-Box value.
+        
+        @param num position of the value (integer)
+        @return value of the S-Box (integer)
+        """
+        return self.sbox[num]
+
+    def __getSBoxInvert(self, num):
+        """
+        Private method to retrieve a given Inverted S-Box value.
+        
+        @param num position of the value (integer)
+        @return value of the Inverted S-Box (integer)
+        """
+        return self.rsbox[num]
+
+    def __rotate(self, data):
+        """
+        Private method performing Rijndael's key schedule rotate operation.
+
+        Rotate the data word eight bits to the left: eg, rotate(1d2c3a4f) == 2c3a4f1d.
+        
+        @param data data of size 4 (bytearray)
+        """
+        return data[1:] + data[:1]
+
+    def __getRconValue(self, num):
+        """
+        Private method to retrieve a given Rcon value.
+        
+        @param num position of the value (integer)
+        @return Rcon value (integer)
+        """
+        return self.Rcon[num]
+
+    def __core(self, data, iteration):
+        """
+        Private method performing the key schedule core operation.
+        
+        @param data data to operate on (bytearray)
+        @param iteration iteration counter (integer)
+        @return modified data (bytearray)
+        """
+        # rotate the 32-bit word 8 bits to the left
+        data = self.__rotate(data)
+        # apply S-Box substitution on all 4 parts of the 32-bit word
+        for i in range(4):
+            data[i] = self.__getSBoxValue(data[i])
+        # XOR the output of the rcon operation with i to the first part
+        # (leftmost) only
+        data[0] = data[0] ^ self.__getRconValue(iteration)
+        return data
+
+    def __expandKey(self, key, size, expandedKeySize):
+        """
+        Private method performing Rijndael's key expansion.
+
+        Expands a 128, 192 or 256 bit key into a 176, 208 or 240 bit key.
+        
+        @param key key to be expanded (bytes or bytearray)
+        @param size size of the key in bytes (16, 24 or 32)
+        @param expandedKeySize size of the expanded key (integer)
+        @return expanded key (bytearray)
+        """
+        # current expanded keySize, in bytes
+        currentSize = 0
+        rconIteration = 1
+        expandedKey = bytearray(expandedKeySize)
+
+        # set the 16, 24, 32 bytes of the expanded key to the input key
+        for j in range(size):
+            expandedKey[j] = key[j]
+        currentSize += size
+
+        while currentSize < expandedKeySize:
+            # assign the previous 4 bytes to the temporary value t
+            t = expandedKey[currentSize - 4:currentSize]
+
+            # every 16, 24, 32 bytes we apply the core schedule to t
+            # and increment rconIteration afterwards
+            if currentSize % size == 0:
+                t = self.__core(t, rconIteration)
+                rconIteration += 1
+            # For 256-bit keys, we add an extra sbox to the calculation
+            if size == self.KeySize["SIZE_256"] and ((currentSize % size) == 16):
+                for l in range(4):
+                    t[l] = self.__getSBoxValue(t[l])
+
+            # We XOR t with the four-byte block 16, 24, 32 bytes before the new
+            # expanded key. This becomes the next four bytes in the expanded key.
+            for m in range(4):
+                expandedKey[currentSize] = \
+                    expandedKey[currentSize - size] ^ t[m]
+                currentSize += 1
+
+        return expandedKey
+
+    def __addRoundKey(self, state, roundKey):
+        """
+        Private method to add (XORs) the round key to the state.
+        
+        @param state state to be changed (bytearray)
+        @param roundKey key to be used for the modification (bytearray)
+        @return modified state (bytearray)
+        """
+        buf = state[:]
+        for i in range(16):
+            buf[i] ^= roundKey[i]
+        return buf
+
+    def __createRoundKey(self, expandedKey, roundKeyPointer):
+        """
+        Private method to create a round key.
+        
+        @param expandedKey expanded key to be used (bytearray)
+        @param roundKeyPointer position within the expanded key (integer)
+        @return round key (bytearray)
+        """
+        roundKey = bytearray(16)
+        for i in range(4):
+            for j in range(4):
+                roundKey[j * 4 + i] = expandedKey[roundKeyPointer + i * 4 + j]
+        return roundKey
+
+    def __galois_multiplication(self, a, b):
+        """
+        Private method to perform a Galois multiplication of 8 bit characters a and b.
+        
+        @param a first factor (byte)
+        @param b second factor (byte)
+        @return result (byte)
+        """
+        p = 0
+        for counter in range(8):
+            if b & 1:
+                p ^= a
+            hi_bit_set = a & 0x80
+            a <<= 1
+            # keep a 8 bit
+            a &= 0xFF
+            if hi_bit_set:
+                a ^= 0x1b
+            b >>= 1
+        return p
+
+    def __subBytes(self, state, isInv):
+        """
+        Private method to substitute all the values from the state with the value in
+        the SBox using the state value as index for the SBox.
+        
+        @param state state to be worked on (bytearray)
+        @param isInv flag indicating an inverse operation (boolean)
+        @return modified state (bytearray)
+        """
+        state = state[:]
+        if isInv:
+            getter = self.__getSBoxInvert
+        else:
+            getter = self.__getSBoxValue
+        for i in range(16):
+            state[i] = getter(state[i])
+        return state
+
+    def __shiftRows(self, state, isInv):
+        """
+        Private method to iterate over the 4 rows and call __shiftRow() with
+        that row.
+        
+        @param state state to be worked on (bytearray)
+        @param isInv flag indicating an inverse operation (boolean)
+        @return modified state (bytearray)
+        """
+        state = state[:]
+        for i in range(4):
+            state = self.__shiftRow(state, i * 4, i, isInv)
+        return state
+
+    def __shiftRow(self, state, statePointer, nbr, isInv):
+        """
+        Private method to shift the bytes of a row to the left.
+        
+        @param state state to be worked on (bytearray)
+        @param statePointer index into the state (integer)
+        @param nbr number of positions to shift (integer)
+        @param isInv flag indicating an inverse operation (boolean)
+        @return modified state (bytearray)
+        """
+        state = state[:]
+        for i in range(nbr):
+            if isInv:
+                state[statePointer:statePointer + 4] = \
+                        state[statePointer + 3:statePointer + 4] + \
+                        state[statePointer:statePointer + 3]
+            else:
+                state[statePointer:statePointer + 4] = \
+                        state[statePointer + 1:statePointer + 4] + \
+                        state[statePointer:statePointer + 1]
+        return state
+
+    def __mixColumns(self, state, isInv):
+        """
+        Private method to perform a galois multiplication of the 4x4 matrix.
+        
+        @param state state to be worked on (bytearray)
+        @param isInv flag indicating an inverse operation (boolean)
+        @return modified state (bytearray)
+        """
+        state = state[:]
+        # iterate over the 4 columns
+        for i in range(4):
+            # construct one column by slicing over the 4 rows
+            column = state[i:i + 16:4]
+            # apply the __mixColumn on one column
+            column = self.__mixColumn(column, isInv)
+            # put the values back into the state
+            state[i:i + 16:4] = column
+
+        return state
+
+    # galois multiplication of 1 column of the 4x4 matrix
+    def __mixColumn(self, column, isInv):
+        """
+        Private method to perform a galois multiplication of 1 column the 4x4 matrix.
+        
+        @param column column to be worked on (bytearray)
+        @param isInv flag indicating an inverse operation (boolean)
+        @return modified column (bytearray)
+        """
+        column = column[:]
+        if isInv:
+            mult = [14, 9, 13, 11]
+        else:
+            mult = [2, 1, 1, 3]
+        cpy = column[:]
+        g = self.__galois_multiplication
+
+        column[0] = g(cpy[0], mult[0]) ^ g(cpy[3], mult[1]) ^ \
+                    g(cpy[2], mult[2]) ^ g(cpy[1], mult[3])
+        column[1] = g(cpy[1], mult[0]) ^ g(cpy[0], mult[1]) ^ \
+                    g(cpy[3], mult[2]) ^ g(cpy[2], mult[3])
+        column[2] = g(cpy[2], mult[0]) ^ g(cpy[1], mult[1]) ^ \
+                    g(cpy[0], mult[2]) ^ g(cpy[3], mult[3])
+        column[3] = g(cpy[3], mult[0]) ^ g(cpy[2], mult[1]) ^ \
+                    g(cpy[1], mult[2]) ^ g(cpy[0], mult[3])
+        return column
+
+    def __aes_round(self, state, roundKey):
+        """
+        Private method to apply the 4 operations of the forward round in sequence.
+        
+        @param state state to be worked on (bytearray)
+        @param roundKey round key to be used (bytearray)
+        @return modified state (bytearray)
+        """
+        state = self.__subBytes(state, False)
+        state = self.__shiftRows(state, False)
+        state = self.__mixColumns(state, False)
+        state = self.__addRoundKey(state, roundKey)
+        return state
+
+    def __aes_invRound(self, state, roundKey):
+        """
+        Private method to apply the 4 operations of the inverse round in sequence.
+        
+        @param state state to be worked on (bytearray)
+        @param roundKey round key to be used (bytearray)
+        @return modified state (bytearray)
+        """
+        state = self.__shiftRows(state, True)
+        state = self.__subBytes(state, True)
+        state = self.__addRoundKey(state, roundKey)
+        state = self.__mixColumns(state, True)
+        return state
+
+    def __aes_main(self, state, expandedKey, nbrRounds):
+        """
+        Private method to perform the initial operations, the standard round, and the
+        final operations of the forward AES, creating a round key for each round.
+        
+        @param state state to be worked on (bytearray)
+        @param expandedKey expanded key to be used (bytearray)
+        @param nbrRounds number of rounds to be done (integer)
+        @return modified state (bytearray)
+        """
+        state = self.__addRoundKey(state, self.__createRoundKey(expandedKey, 0))
+        i = 1
+        while i < nbrRounds:
+            state = self.__aes_round(
+                state, self.__createRoundKey(expandedKey, 16 * i))
+            i += 1
+        state = self.__subBytes(state, False)
+        state = self.__shiftRows(state, False)
+        state = self.__addRoundKey(
+            state, self.__createRoundKey(expandedKey, 16 * nbrRounds))
+        return state
+
+    def __aes_invMain(self, state, expandedKey, nbrRounds):
+        """
+        Private method to perform the initial operations, the standard round, and the
+        final operations of the inverse AES, creating a round key for each round.
+        
+        @param state state to be worked on (bytearray)
+        @param expandedKey expanded key to be used (bytearray)
+        @param nbrRounds number of rounds to be done (integer)
+        @return modified state (bytearray)
+        """
+        state = self.__addRoundKey(
+            state, self.__createRoundKey(expandedKey, 16 * nbrRounds))
+        i = nbrRounds - 1
+        while i > 0:
+            state = self.__aes_invRound(
+                state, self.__createRoundKey(expandedKey, 16 * i))
+            i -= 1
+        state = self.__shiftRows(state, True)
+        state = self.__subBytes(state, True)
+        state = self.__addRoundKey(state, self.__createRoundKey(expandedKey, 0))
+        return state
+
+    def encrypt(self, iput, key, size):
+        """
+        Public method to encrypt a 128 bit input block against the given key of size
+        specified.
+        
+        @param iput input data (bytearray)
+        @param key key to be used (bytes or bytearray)
+        @param size key size (16, 24 or 32)
+        @return encrypted data (bytes)
+        """
+        output = bytearray(16)
+        # the number of rounds
+        nbrRounds = 0
+        # the 128 bit block to encode
+        block = bytearray(16)
+        # set the number of rounds
+        if size == self.KeySize["SIZE_128"]:
+            nbrRounds = 10
+        elif size == self.KeySize["SIZE_192"]:
+            nbrRounds = 12
+        elif size == self.KeySize["SIZE_256"]:
+            nbrRounds = 14
+        else:
+            raise ValueError("Wrong key size given ({0}).".format(size))
+
+        # the expanded keySize
+        expandedKeySize = 16 * (nbrRounds + 1)
+
+        # Set the block values, for the block:
+        # a0,0 a0,1 a0,2 a0,3
+        # a1,0 a1,1 a1,2 a1,3
+        # a2,0 a2,1 a2,2 a2,3
+        # a3,0 a3,1 a3,2 a3,3
+        # the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3
+        #
+        # iterate over the columns
+        for i in range(4):
+            # iterate over the rows
+            for j in range(4):
+                block[i + j * 4] = iput[i * 4 + j]
+
+        # expand the key into an 176, 208, 240 bytes key
+        # the expanded key
+        expandedKey = self.__expandKey(key, size, expandedKeySize)
+
+        # encrypt the block using the expandedKey
+        block = self.__aes_main(block, expandedKey, nbrRounds)
+
+        # unmap the block again into the output
+        for k in range(4):
+            # iterate over the rows
+            for l in range(4):
+                output[k * 4 + l] = block[k + l * 4]
+        return bytes(output)
+
+    # decrypts a 128 bit input block against the given key of size specified
+    def decrypt(self, iput, key, size):
+        """
+        Public method to decrypt a 128 bit input block against the given key of size
+        specified.
+        
+        @param iput input data (bytearray)
+        @param key key to be used (bytes or bytearray)
+        @param size key size (16, 24 or 32)
+        @return decrypted data (bytes)
+        """
+        output = bytearray(16)
+        # the number of rounds
+        nbrRounds = 0
+        # the 128 bit block to decode
+        block = bytearray(16)
+        # set the number of rounds
+        if size == self.KeySize["SIZE_128"]:
+            nbrRounds = 10
+        elif size == self.KeySize["SIZE_192"]:
+            nbrRounds = 12
+        elif size == self.KeySize["SIZE_256"]:
+            nbrRounds = 14
+        else:
+            raise ValueError("Wrong key size given ({0}).".format(size))
+
+        # the expanded keySize
+        expandedKeySize = 16 * (nbrRounds + 1)
+
+        # Set the block values, for the block:
+        # a0,0 a0,1 a0,2 a0,3
+        # a1,0 a1,1 a1,2 a1,3
+        # a2,0 a2,1 a2,2 a2,3
+        # a3,0 a3,1 a3,2 a3,3
+        # the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3
+
+        # iterate over the columns
+        for i in range(4):
+            # iterate over the rows
+            for j in range(4):
+                block[i + j * 4] = iput[i * 4 + j]
+        # expand the key into an 176, 208, 240 bytes key
+        expandedKey = self.__expandKey(key, size, expandedKeySize)
+        # decrypt the block using the expandedKey
+        block = self.__aes_invMain(block, expandedKey, nbrRounds)
+        # unmap the block again into the output
+        for k in range(4):
+            # iterate over the rows
+            for l in range(4):
+                output[k * 4 + l] = block[k + l * 4]
+        return output
+
+
+class AESModeOfOperation(object):
+    """
+    Class implementing the different AES mode of operations.
+    """
+    aes = AES()
+
+    # structure of supported modes of operation
+    ModeOfOperation = {
+        "OFB": 0,
+        "CFB": 1,
+        "CBC": 2,
+    }
+
+    def __extractBytes(self, input, start, end, mode):
+        """
+        Private method to extract a range of bytes from the input.
+        
+        @param input input data (bytes)
+        @param start start index (integer)
+        @param end end index (integer)
+        @param mode mode of operation (0, 1, 2)
+        @return extracted bytes (bytearray)
+        """
+        if end - start > 16:
+            end = start + 16
+        if mode == self.ModeOfOperation["CBC"]:
+            ar = bytearray(16)
+        else:
+            ar = bytearray()
+
+        i = start
+        j = 0
+        while len(ar) < end - start:
+            ar.append(0)
+        while i < end:
+            ar[j] = input[i]
+            j += 1
+            i += 1
+        return ar
+
+    def encrypt(self, input, mode, key, size, IV):
+        """
+        Public method to perform the encryption operation.
+        
+        @param input data to be encrypted (bytes)
+        @param mode mode of operation (0, 1 or 2)
+        @param key key to be used (bytes)
+        @param size length of the key (integer)
+        @param IV initialisation vector (bytearray)
+        @return tuple with mode of operation, length of the input and
+            the encrypted data (integer, integer, bytes)
+        """
+        if len(key) % size:
+            raise ValueError("Illegal size ({0}) for key '{1}'.".format(
+                size, key))
+        if len(IV) % 16:
+            raise ValueError("IV is not a multiple of 16.")
+        # the AES input/output
+        iput = bytearray(16)
+        output = bytearray()
+        ciphertext = bytearray(16)
+        # the output cipher string
+        cipherOut = bytearray()
+        # char firstRound
+        firstRound = True
+        if input:
+            for j in range(int(math.ceil(float(len(input)) / 16))):
+                start = j * 16
+                end = j * 16 + 16
+                if  end > len(input):
+                    end = len(input)
+                plaintext = self.__extractBytes(input, start, end, mode)
+                # print 'PT@%s:%s' % (j, plaintext)
+                if mode == self.ModeOfOperation["CFB"]:
+                    if firstRound:
+                        output = self.aes.encrypt(IV, key, size)
+                        firstRound = False
+                    else:
+                        output = self.aes.encrypt(iput, key, size)
+                    for i in range(16):
+                        if len(plaintext) - 1 < i:
+                            ciphertext[i] = 0 ^ output[i]
+                        elif len(output) - 1 < i:
+                            ciphertext[i] = plaintext[i] ^ 0
+                        elif len(plaintext) - 1 < i and len(output) < i:
+                            ciphertext[i] = 0 ^ 0
+                        else:
+                            ciphertext[i] = plaintext[i] ^ output[i]
+                    for k in range(end - start):
+                        cipherOut.append(ciphertext[k])
+                    iput = ciphertext
+                elif mode == self.ModeOfOperation["OFB"]:
+                    if firstRound:
+                        output = self.aes.encrypt(IV, key, size)
+                        firstRound = False
+                    else:
+                        output = self.aes.encrypt(iput, key, size)
+                    for i in range(16):
+                        if len(plaintext) - 1 < i:
+                            ciphertext[i] = 0 ^ output[i]
+                        elif len(output) - 1 < i:
+                            ciphertext[i] = plaintext[i] ^ 0
+                        elif len(plaintext) - 1 < i and len(output) < i:
+                            ciphertext[i] = 0 ^ 0
+                        else:
+                            ciphertext[i] = plaintext[i] ^ output[i]
+                    for k in range(end - start):
+                        cipherOut.append(ciphertext[k])
+                    iput = output
+                elif mode == self.ModeOfOperation["CBC"]:
+                    for i in range(16):
+                        if firstRound:
+                            iput[i] = plaintext[i] ^ IV[i]
+                        else:
+                            iput[i] = plaintext[i] ^ ciphertext[i]
+                    # print 'IP@%s:%s' % (j, iput)
+                    firstRound = False
+                    ciphertext = self.aes.encrypt(iput, key, size)
+                    # always 16 bytes because of the padding for CBC
+                    for k in range(16):
+                        cipherOut.append(ciphertext[k])
+        return mode, len(input), bytes(cipherOut)
+
+    # Mode of Operation Decryption
+    # cipherIn - Encrypted String
+    # originalsize - The unencrypted string length - required for CBC
+    # mode - mode of type modeOfOperation
+    # key - a number array of the bit length size
+    # size - the bit length of the key
+    # IV - the 128 bit number array Initilization Vector
+    def decrypt(self, cipherIn, originalsize, mode, key, size, IV):
+        """
+        Public method to perform the decryption operation.
+        
+        @param input data to be encrypted (bytes)
+        @param originalsize unencrypted string length (required for CBC)
+            (integer)
+        @param mode mode of operation (0, 1 or 2)
+        @param key key to be used (bytes)
+        @param size length of the key (integer)
+        @param IV initialisation vector (bytearray)
+        @return decrypted data (bytes)
+        """
+        if len(key) % size:
+            raise ValueError("Illegal size ({0}) for key '{1}'.".format(
+                size, key))
+        if len(IV) % 16:
+            raise ValueError("IV is not a multiple of 16.")
+        # the AES input/output
+        ciphertext = bytearray()
+        iput = bytearray()
+        output = bytearray()
+        plaintext = bytearray(16)
+        # the output bytes
+        bytesOut = bytearray()
+        # char firstRound
+        firstRound = True
+        if cipherIn != None:
+            for j in range(int(math.ceil(float(len(cipherIn)) / 16))):
+                start = j * 16
+                end = j * 16 + 16
+                if j * 16 + 16 > len(cipherIn):
+                    end = len(cipherIn)
+                ciphertext = cipherIn[start:end]
+                if mode == self.ModeOfOperation["CFB"]:
+                    if firstRound:
+                        output = self.aes.encrypt(IV, key, size)
+                        firstRound = False
+                    else:
+                        output = self.aes.encrypt(iput, key, size)
+                    for i in range(16):
+                        if len(output) - 1 < i:
+                            plaintext[i] = 0 ^ ciphertext[i]
+                        elif len(ciphertext) - 1 < i:
+                            plaintext[i] = output[i] ^ 0
+                        elif len(output) - 1 < i and len(ciphertext) < i:
+                            plaintext[i] = 0 ^ 0
+                        else:
+                            plaintext[i] = output[i] ^ ciphertext[i]
+                    for k in range(end - start):
+                        bytesOut.append(plaintext[k])
+                    iput = ciphertext
+                elif mode == self.ModeOfOperation["OFB"]:
+                    if firstRound:
+                        output = self.aes.encrypt(IV, key, size)
+                        firstRound = False
+                    else:
+                        output = self.aes.encrypt(iput, key, size)
+                    for i in range(16):
+                        if len(output) - 1 < i:
+                            plaintext[i] = 0 ^ ciphertext[i]
+                        elif len(ciphertext) - 1 < i:
+                            plaintext[i] = output[i] ^ 0
+                        elif len(output) - 1 < i and len(ciphertext) < i:
+                            plaintext[i] = 0 ^ 0
+                        else:
+                            plaintext[i] = output[i] ^ ciphertext[i]
+                    for k in range(end - start):
+                        bytesOut.append(plaintext[k])
+                    iput = output
+                elif mode == self.ModeOfOperation["CBC"]:
+                    output = self.aes.decrypt(ciphertext, key, size)
+                    for i in range(16):
+                        if firstRound:
+                            plaintext[i] = IV[i] ^ output[i]
+                        else:
+                            plaintext[i] = iput[i] ^ output[i]
+                    firstRound = False
+                    if originalsize is not None and originalsize < end:
+                        for k in range(originalsize - start):
+                            bytesOut.append(plaintext[k])
+                    else:
+                        for k in range(end - start):
+                            bytesOut.append(plaintext[k])
+                    iput = ciphertext
+        return bytes(bytesOut)
+
+
+def encryptData(key, data, mode=AESModeOfOperation.ModeOfOperation["CBC"]):
+    """
+    Module function to encrypt the given data with the given key.
+    
+    @param key key to be used for encryption (bytes)
+    @param data data to be encrypted (bytes)
+    @param mode mode of operations (0, 1 or 2)
+    @return encrypted data prepended with the initialization vector (bytes)
+    """
+    key = bytearray(key)
+    if mode == AESModeOfOperation.ModeOfOperation["CBC"]:
+        data = append_PKCS7_padding(data)
+    keysize = len(key)
+    assert keysize in AES.KeySize.values(), 'invalid key size: {0}'.format(keysize)
+    # create a new iv using random data
+    iv = bytearray([i for i in os.urandom(16)])
+    moo = AESModeOfOperation()
+    mode, length, ciph = moo.encrypt(data, mode, key, keysize, iv)
+    # With padding, the original length does not need to be known. It's a bad
+    # idea to store the original message length.
+    # prepend the iv.
+    return bytes(iv) + bytes(ciph)
+
+
+def decryptData(key, data, mode=AESModeOfOperation.ModeOfOperation["CBC"]):
+    """
+    Module function to decrypt the given data with the given key.
+    
+    @param key key to be used for decryption (bytes)
+    @param data data to be decrypted (with initialization vector prepended) (bytes)
+    @param mode mode of operations (0, 1 or 2)
+    @return decrypted data (bytes)
+    @exception ValueError key size is invalid or decrypted data is invalid
+    """
+    key = bytearray(key)
+    keysize = len(key)
+    assert keysize in AES.KeySize.values(), 'invalid key size: %s' % keysize
+    # iv is first 16 bytes
+    iv = bytearray(data[:16])
+    data = bytearray(data[16:])
+    moo = AESModeOfOperation()
+    decr = moo.decrypt(data, None, mode, key, keysize, iv)
+    if mode == AESModeOfOperation.ModeOfOperation["CBC"]:
+        decr = strip_PKCS7_padding(decr)
+    return bytes(decr)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/crypto/py3PBKDF2.py	Sun Jun 19 15:19:46 2011 +0200
@@ -0,0 +1,147 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2002 - 2011 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing PBKDF2 functions.
+"""
+
+import hashlib
+import hmac
+import os
+import base64
+
+Hashes = {
+    "sha1": hashlib.sha1,
+    "sha224": hashlib.sha224,
+    "sha256": hashlib.sha256,
+    "sha384": hashlib.sha384,
+    "sha512": hashlib.sha512,
+    "md5": hashlib.md5,
+}
+
+Delimiter = "$"
+
+def pbkdf2(password, salt, iterations, digestMod):
+    """
+    Module function to hash a password according to the PBKDF2 specification.
+    
+    @param password clear text password (bytes)
+    @param salt salt value (bytes)
+    @param iterations number of times hash function should be applied (integer)
+    @param digestMod hash function
+    @return hashed password (bytes)
+    """
+    hash = password
+    for i in range(iterations):
+        hash = hmac.new(salt, hash, digestMod).digest()
+    return hash
+
+
+def hashPasswordTuple(password, digestMod=hashlib.sha512, iterations=10000, saltSize=32):
+    """
+    Module function to hash a password according to the PBKDF2 specification.
+    
+    @param password clear text password (string)
+    @param digestMod hash function
+    @param iterations number of times hash function should be applied (integer)
+    @param saltSize size of the salt (integer)
+    @return tuple of digestname (string), number of iterations (integer),
+        salt (bytes) and hashed password (bytes)
+    """
+    salt = os.urandom(saltSize)
+    password = password.encode("utf-8")
+    hash = pbkdf2(password, salt, iterations, digestMod)
+    digestname = digestMod.__name__.replace("openssl_", "")
+    return digestname, iterations, salt, hash
+
+
+def hashPassword(password, digestMod=hashlib.sha512, iterations=10000, saltSize=32):
+    """
+    Module function to hash a password according to the PBKDF2 specification.
+    
+    @param password clear text password (string)
+    @param digestMod hash function
+    @param iterations number of times hash function should be applied (integer)
+    @param saltSize size of the salt (integer)
+    @return hashed password entry according to PBKDF2 specification (string)
+    """
+    digestname, iterations, salt, hash = \
+        hashPasswordTuple(password, digestMod, iterations, saltSize)
+    return Delimiter.join([
+        digestname,
+        str(iterations),
+        base64.b64encode(salt).decode("ascii"),
+        base64.b64encode(hash).decode("ascii")
+    ])
+
+
+def verifyPassword(password, hash):
+    """
+    Module function to verify a password against a hash encoded password.
+    
+    @param password clear text password (string)
+    @param hash hash encoded password in the form
+        'digestmod$iterations$salt$hashed_password' as produced by the
+        hashPassword function (string)
+    @return flag indicating a successfull verification (boolean)
+    @exception ValueError the hash is not of the expected format or the
+        digest is not one of the known ones
+    """
+    try:
+        digestname, iterations, salt, pwHash = hash.split(Delimiter)
+    except ValueError:
+        raise ValueError(
+            "Expected hash encoded password in format "\
+            "'digestmod{0}iterations{0}salt{0}hashed_password".format(Delimiter))
+    
+    if digestname not in Hashes.keys():
+        raise ValueError(
+            "Unsupported hash algorithm '{0}' for hash encoded password '{1}'.".format(
+            digestname, hash))
+    
+    iterations = int(iterations)
+    salt = base64.b64decode(salt.encode("ascii"))
+    pwHash = base64.b64decode(pwHash.encode("ascii"))
+    password = password.encode("utf-8")
+    return pwHash == pbkdf2(password, salt, iterations, Hashes[digestname])
+
+
+def rehashPassword(password, hashParameters):
+    """
+    Module function to recreate a password hash given the hash parameters.
+    
+    @param password clear text password (string)
+    @param hashParameters hash parameters in the form
+        'digestmod$iterations$salt' (string)
+    @return hashed password (bytes)
+    @exception ValueError the hash parameters string is not of the expected format
+        or the digest is not one of the known ones
+    """
+    try:
+        digestname, iterations, salt = hashParameters.split(Delimiter)
+    except ValueError:
+        raise ValueError(
+            "Expected hash parameters string in format "\
+            "'digestmod{0}iterations{0}salt".format(Delimiter))
+    
+    if digestname not in Hashes.keys():
+        raise ValueError(
+            "Unsupported hash algorithm '{0}' for hash parameters '{1}'.".format(
+            digestname, hash))
+    
+    iterations = int(iterations)
+    salt = base64.b64decode(salt.encode("ascii"))
+    password = password.encode("utf-8")
+    return pbkdf2(password, salt, iterations, Hashes[digestname])
+
+
+if __name__ == "__main__":
+    import sys
+    pw = "secret_password"
+    print(len(hashPasswordTuple(pw)[-1]))
+    pwHash = hashPassword(pw)
+    print(pwHash)
+    print(verifyPassword(pw, pwHash))
+    sys.exit(0)
--- a/changelog	Thu Jun 16 16:29:27 2011 +0200
+++ b/changelog	Sun Jun 19 15:19:46 2011 +0200
@@ -14,6 +14,8 @@
 - added a pause button to the web browser download
 - added some more user agent strings to the web browser
 - added some more search engines to the web browser
+- added capability to encrypt saved passwords with a master password
+  and rearranged some configuration parameters related to security
 
 Version 5.2-snapshot-20110501:
 - bug fixes
--- a/eric5.e4p	Thu Jun 16 16:29:27 2011 +0200
+++ b/eric5.e4p	Sun Jun 19 15:19:46 2011 +0200
@@ -919,6 +919,13 @@
     <Source>Plugins/VcsPlugins/vcsMercurial/RebaseExtension/rebase.py</Source>
     <Source>Plugins/VcsPlugins/vcsMercurial/RebaseExtension/ProjectHelper.py</Source>
     <Source>Plugins/VcsPlugins/vcsMercurial/RebaseExtension/HgRebaseDialog.py</Source>
+    <Source>Utilities/PasswordChecker.py</Source>
+    <Source>E5Gui/E5PasswordMeter.py</Source>
+    <Source>Preferences/ConfigurationPages/MasterPasswordEntryDialog.py</Source>
+    <Source>Utilities/crypto/__init__.py</Source>
+    <Source>Utilities/crypto/py3AES.py</Source>
+    <Source>Utilities/crypto/py3PBKDF2.py</Source>
+    <Source>Preferences/ConfigurationPages/SecurityPage.py</Source>
   </Sources>
   <Forms>
     <Form>PyUnit/UnittestDialog.ui</Form>
@@ -1178,6 +1185,8 @@
     <Form>Plugins/VcsPlugins/vcsMercurial/GpgExtension/HgGpgSignDialog.ui</Form>
     <Form>Plugins/VcsPlugins/vcsMercurial/TransplantExtension/TransplantDialog.ui</Form>
     <Form>Plugins/VcsPlugins/vcsMercurial/RebaseExtension/HgRebaseDialog.ui</Form>
+    <Form>Preferences/ConfigurationPages/MasterPasswordEntryDialog.ui</Form>
+    <Form>Preferences/ConfigurationPages/SecurityPage.ui</Form>
   </Forms>
   <Translations>
     <Translation>i18n/eric5_cs.qm</Translation>
@@ -1271,8 +1280,6 @@
     <Other>CSSs/default.css</Other>
     <Other>Plugins/VcsPlugins/vcsMercurial/styles/logBrowserBookmark.style</Other>
     <Other>Plugins/VcsPlugins/vcsMercurial/styles/logDialogBookmark.style</Other>
-    <Other>icons/default/bookmark16.png</Other>
-    <Other>icons/default/bookmark32.png</Other>
   </Others>
   <MainScript>eric5.py</MainScript>
   <Vcs>
--- a/i18n/eric5_cs.ts	Thu Jun 16 16:29:27 2011 +0200
+++ b/i18n/eric5_cs.ts	Sun Jun 19 15:19:46 2011 +0200
@@ -2470,7 +2470,7 @@
 <context>
     <name>CodingError</name>
     <message>
-        <location filename="Utilities/__init__.py" line="95"/>
+        <location filename="Utilities/__init__.py" line="93"/>
         <source>The coding &apos;{0}&apos; is wrong for the given text.</source>
         <translation>Nesprávné kódování &apos;{0}&apos; pro daný text.</translation>
     </message>
@@ -2863,243 +2863,243 @@
 <context>
     <name>ConfigurationWidget</name>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="111"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="114"/>
         <source>Application</source>
         <translation>Aplikace</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="117"/>
-        <source>CORBA</source>
-        <translation>CORBA</translation>
-    </message>
-    <message>
         <location filename="Preferences/ConfigurationDialog.py" line="120"/>
-        <source>Email</source>
-        <translation>Email</translation>
+        <source>CORBA</source>
+        <translation>CORBA</translation>
     </message>
     <message>
         <location filename="Preferences/ConfigurationDialog.py" line="123"/>
-        <source>Graphics</source>
-        <translation>Grafika</translation>
+        <source>Email</source>
+        <translation>Email</translation>
     </message>
     <message>
         <location filename="Preferences/ConfigurationDialog.py" line="126"/>
+        <source>Graphics</source>
+        <translation>Grafika</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="129"/>
         <source>Icons</source>
         <translation>Ikony</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="132"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="135"/>
         <source>Plugin Manager</source>
         <translation>Plugin Manažer</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="298"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="304"/>
         <source>Printer</source>
         <translation>Tiskárna</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="172"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="178"/>
         <source>Python</source>
         <translation>Python</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="144"/>
-        <source>Qt</source>
-        <translation>Qt</translation>
-    </message>
-    <message>
         <location filename="Preferences/ConfigurationDialog.py" line="147"/>
-        <source>Shell</source>
-        <translation>Shell</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="150"/>
-        <source>Tasks</source>
-        <translation>Úlohy</translation>
+        <source>Qt</source>
+        <translation>Qt</translation>
     </message>
     <message>
         <location filename="Preferences/ConfigurationDialog.py" line="153"/>
+        <source>Shell</source>
+        <translation>Shell</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="156"/>
+        <source>Tasks</source>
+        <translation>Úlohy</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="159"/>
         <source>Templates</source>
         <translation>Šablony</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="162"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="168"/>
         <source>Version Control Systems</source>
         <translation>Version Control Systems</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="166"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="172"/>
         <source>Debugger</source>
         <translation>Debugger</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="178"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="184"/>
         <source>Ruby</source>
         <translation>Ruby</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="182"/>
-        <source>Editor</source>
-        <translation>Editor</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="185"/>
-        <source>APIs</source>
-        <translation>APIs</translation>
-    </message>
-    <message>
         <location filename="Preferences/ConfigurationDialog.py" line="188"/>
+        <source>Editor</source>
+        <translation>Editor</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="191"/>
+        <source>APIs</source>
+        <translation>APIs</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="194"/>
         <source>Autocompletion</source>
         <translation>Autodoplňování</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="195"/>
-        <source>Calltips</source>
-        <translation>Rychlé tipy</translation>
-    </message>
-    <message>
         <location filename="Preferences/ConfigurationDialog.py" line="201"/>
+        <source>Calltips</source>
+        <translation>Rychlé tipy</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="207"/>
         <source>General</source>
         <translation>Hlavní</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="216"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="222"/>
         <source>Typing</source>
         <translation>Psaní</translation>
     </message>
     <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="225"/>
+        <source>Exporters</source>
+        <translation>Exportery</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="229"/>
+        <source>Highlighters</source>
+        <translation>Zvýrazňovače</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="232"/>
+        <source>Filetype Associations</source>
+        <translation>Asociace typů souborů</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="236"/>
+        <source>Styles</source>
+        <translation>Styly</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="311"/>
+        <source>Help</source>
+        <translation>Nápověda</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="317"/>
+        <source>Help Documentation</source>
+        <translation>Dokumenty nápovědy</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="321"/>
+        <source>Help Viewers</source>
+        <translation>Prohlížeče nápovědy</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="273"/>
+        <source>Project</source>
+        <translation>Projekt</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="270"/>
+        <source>Project Viewer</source>
+        <translation>Prohlížeč projektu</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="276"/>
+        <source>Multiproject</source>
+        <translation>Multiprojekt</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="283"/>
+        <source>Interface</source>
+        <translation>Interface</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="286"/>
+        <source>Viewmanager</source>
+        <translation>Viewmanager</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="473"/>
+        <source>Configuration Page Error</source>
+        <translation>Chyba na straně konfigurace</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="210"/>
+        <source>Filehandling</source>
+        <translation>Manažer souborů</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="213"/>
+        <source>Searching</source>
+        <translation>Vyhledávání</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="314"/>
+        <source>Appearance</source>
+        <translation>Vzhled</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="204"/>
+        <source>QScintilla</source>
+        <translation>QScintilla</translation>
+    </message>
+    <message>
         <location filename="Preferences/ConfigurationDialog.py" line="219"/>
-        <source>Exporters</source>
-        <translation>Exportery</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="223"/>
-        <source>Highlighters</source>
-        <translation>Zvýrazňovače</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="226"/>
-        <source>Filetype Associations</source>
-        <translation>Asociace typů souborů</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="230"/>
-        <source>Styles</source>
-        <translation>Styly</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="302"/>
-        <source>Help</source>
-        <translation>Nápověda</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="308"/>
-        <source>Help Documentation</source>
-        <translation>Dokumenty nápovědy</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="312"/>
-        <source>Help Viewers</source>
-        <translation>Prohlížeče nápovědy</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="267"/>
-        <source>Project</source>
-        <translation>Projekt</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="264"/>
-        <source>Project Viewer</source>
-        <translation>Prohlížeč projektu</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="270"/>
-        <source>Multiproject</source>
-        <translation>Multiprojekt</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="277"/>
-        <source>Interface</source>
-        <translation>Interface</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="280"/>
-        <source>Viewmanager</source>
-        <translation>Viewmanager</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="464"/>
-        <source>Configuration Page Error</source>
-        <translation>Chyba na straně konfigurace</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="204"/>
-        <source>Filehandling</source>
-        <translation>Manažer souborů</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="207"/>
-        <source>Searching</source>
-        <translation>Vyhledávání</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="305"/>
-        <source>Appearance</source>
-        <translation>Vzhled</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="198"/>
-        <source>QScintilla</source>
-        <translation>QScintilla</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="213"/>
         <source>Style</source>
         <translation>Styl</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="237"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="243"/>
         <source>Properties</source>
         <translation>Nastavení</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="424"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="433"/>
         <source>Preferences</source>
         <translation>Předvolby</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="429"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="438"/>
         <source>Please select an entry of the list 
 to display the configuration page.</source>
         <translation>Pro zobrazení strany s konfigurací vyberte položku ze seznamu.</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="156"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="162"/>
         <source>Terminal</source>
         <translation>Terminál</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="295"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="301"/>
         <source>Network</source>
         <translation>Síť</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="210"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="216"/>
         <source>Spell checking</source>
         <translation>Kontrola pravopisu</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="175"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="181"/>
         <source>Python3</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="318"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="327"/>
         <source>Eric Web Browser</source>
         <translation>Eric web prohlížeč</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="464"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="473"/>
         <source>&lt;p&gt;The configuration page &lt;b&gt;{0}&lt;/b&gt; could not be loaded.&lt;/p&gt;</source>
         <translation>&lt;p&gt;Konfigurační stranu &lt;b&gt;{0}&lt;/b&gt; nelze načíst.&lt;/p&gt;</translation>
     </message>
@@ -3109,30 +3109,35 @@
         <translation type="obsolete">Py3Flakes</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="234"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="240"/>
         <source>Keywords</source>
         <translation>Klíčová slova</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="114"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="117"/>
         <source>Cooperation</source>
         <translation>Spolupráce</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="330"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="339"/>
         <source>Tray Starter</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="138"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="141"/>
         <source>PyFlakes</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationDialog.py" line="315"/>
+        <location filename="Preferences/ConfigurationDialog.py" line="324"/>
         <source>VirusTotal Interface</source>
         <translation type="unfinished"></translation>
     </message>
+    <message>
+        <location filename="Preferences/ConfigurationDialog.py" line="307"/>
+        <source>Security</source>
+        <translation type="unfinished">Bezpečnost</translation>
+    </message>
 </context>
 <context>
     <name>Connection</name>
@@ -3740,6 +3745,29 @@
     </message>
 </context>
 <context>
+    <name>Crypto</name>
+    <message>
+        <location filename="Utilities/crypto/__init__.py" line="140"/>
+        <source>Master Password</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Utilities/crypto/__init__.py" line="118"/>
+        <source>Enter the master password:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Utilities/crypto/__init__.py" line="130"/>
+        <source>The given password is incorrect.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Utilities/crypto/__init__.py" line="135"/>
+        <source>There is no master password registered.</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
     <name>DebugServer</name>
     <message>
         <location filename="Debugger/DebugServer.py" line="134"/>
@@ -5161,7 +5189,7 @@
     <message>
         <location filename="Preferences/ConfigurationPages/DebuggerPython3Page.ui" line="53"/>
         <source>Enter the path of the Python3 interpreter to be used by the debug client.</source>
-        <translation>Zadání cesty na Python3 interpret, který bude použit debug klientem.</translation>
+        <translation type="obsolete">Zadání cesty na Python3 interpret, který bude použit debug klientem.</translation>
     </message>
     <message>
         <location filename="Preferences/ConfigurationPages/DebuggerPython3Page.ui" line="60"/>
@@ -5273,6 +5301,11 @@
         <source>Select, to redirect stdin, stdout and stderr of the program being debugged to the eric5 IDE</source>
         <translation>Vyberte pro přesměrování stdin, stdout, a stderr programu, který je debugován v eric5 IDE</translation>
     </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/DebuggerPython3Page.ui" line="53"/>
+        <source>Enter the path of the Python3 interpreter to be used by the debug client. Leave empty to use the default.</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>DebuggerPythonPage</name>
@@ -5289,7 +5322,7 @@
     <message>
         <location filename="Preferences/ConfigurationPages/DebuggerPythonPage.ui" line="43"/>
         <source>Enter the path of the Python interpreter to be used by the debug client.  Leave empty to use the default.</source>
-        <translation>Zadání Python interpretru, který se má použít debug klientem. Má-li se použít default, ponechte zadání nevyplněné.</translation>
+        <translation type="obsolete">Zadání Python interpretru, který se má použít debug klientem. Má-li se použít default, ponechte zadání nevyplněné.</translation>
     </message>
     <message>
         <location filename="Preferences/ConfigurationPages/DebuggerPythonPage.ui" line="50"/>
@@ -5396,6 +5429,11 @@
         <source>Python Files (*.py *.py2)</source>
         <translation type="unfinished">Python soubory (*.py *.py3) {2)?}</translation>
     </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/DebuggerPythonPage.ui" line="43"/>
+        <source>Enter the path of the Python interpreter to be used by the debug client.</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>DebuggerRubyPage</name>
@@ -7734,7 +7772,7 @@
         <translation>Stiskněte pro výběr API souboru ze seznamu instalovaných API</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/EditorAPIsPage.py" line="170"/>
+        <location filename="Preferences/ConfigurationPages/EditorAPIsPage.py" line="181"/>
         <source>Add from installed APIs</source>
         <translation>Přidat z instalovaných API</translation>
     </message>
@@ -7744,7 +7782,7 @@
         <translation>Stiskněte pro kompilování vybrané API definici</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/EditorAPIsPage.py" line="221"/>
+        <location filename="Preferences/ConfigurationPages/EditorAPIsPage.py" line="228"/>
         <source>Compile APIs</source>
         <translation>Kompilovat API</translation>
     </message>
@@ -7794,12 +7832,12 @@
         <translation>API soubor (*.api);;Všechny soubory (*)</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/EditorAPIsPage.py" line="170"/>
+        <location filename="Preferences/ConfigurationPages/EditorAPIsPage.py" line="171"/>
         <source>Select from the list of installed API files</source>
         <translation>Výběr ze seznamu instalovaných API souborů</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/EditorAPIsPage.py" line="236"/>
+        <location filename="Preferences/ConfigurationPages/EditorAPIsPage.py" line="243"/>
         <source>Cancel compilation</source>
         <translation>Zrušit kompilaci</translation>
     </message>
@@ -7814,15 +7852,20 @@
         <translation>Stiskněte pro výběr API souboru ze seznamu API souborů instalovaných z pluginů</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/EditorAPIsPage.py" line="190"/>
+        <location filename="Preferences/ConfigurationPages/EditorAPIsPage.py" line="197"/>
         <source>Add from Plugin APIs</source>
         <translation>Přidat z API pluginů</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/EditorAPIsPage.py" line="190"/>
+        <location filename="Preferences/ConfigurationPages/EditorAPIsPage.py" line="197"/>
         <source>Select from the list of API files installed by plugins</source>
         <translation>Vybrat ze seznamu API souborů instalovaných pluginy</translation>
     </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/EditorAPIsPage.py" line="181"/>
+        <source>There are no APIs installed yet. Selection is not available.</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>EditorAutocompletionPage</name>
@@ -13635,42 +13678,42 @@
         <translation>Povolit zásuvné moduly</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="358"/>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="329"/>
         <source>Browser Cache</source>
         <translation>Procházet cache</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="364"/>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="335"/>
         <source>Enable disk cache</source>
         <translation>Zapnout disk cache</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="410"/>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="381"/>
         <source>Cache size:</source>
         <translation>Velikost cache:</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="417"/>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="388"/>
         <source>Enter the maximum size of the disk cache</source>
         <translation>Zadejte maximální velikost diskové cache</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="423"/>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="394"/>
         <source> MB</source>
         <translation> MB</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="491"/>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="462"/>
         <source>Printing</source>
         <translation>Tisk</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="497"/>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="468"/>
         <source>Select to print background colours and images</source>
         <translation>Vybrat pro tisk barev pozadí a obrázků</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="500"/>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="471"/>
         <source>Print background colours and images</source>
         <translation>Tisknout barvy pozadí a obrázky</translation>
     </message>
@@ -13730,52 +13773,52 @@
         <translation>Nastavit výchozí domovskou stranu</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="294"/>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="265"/>
         <source>History</source>
         <translation>Historie</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="300"/>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="271"/>
         <source>Remove history items:</source>
         <translation>Odebrat položky historie:</translation>
     </message>
     <message>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="284"/>
+        <source>Select the period for expiration of history entries</source>
+        <translation>Vybrat interval pro vypršení platnosti položek historie</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="288"/>
+        <source>After one day</source>
+        <translation>Po jednom dni</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="293"/>
+        <source>After one week</source>
+        <translation>Po týdnu</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="298"/>
+        <source>After two weeks</source>
+        <translation>Po dvou týdnech</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="303"/>
+        <source>After one month</source>
+        <translation>Po měsíci</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="308"/>
+        <source>After one year</source>
+        <translation>Po roce</translation>
+    </message>
+    <message>
         <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="313"/>
-        <source>Select the period for expiration of history entries</source>
-        <translation>Vybrat interval pro vypršení platnosti položek historie</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="317"/>
-        <source>After one day</source>
-        <translation>Po jednom dni</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="322"/>
-        <source>After one week</source>
-        <translation>Po týdnu</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="327"/>
-        <source>After two weeks</source>
-        <translation>Po dvou týdnech</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="332"/>
-        <source>After one month</source>
-        <translation>Po měsíci</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="337"/>
-        <source>After one year</source>
-        <translation>Po roce</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="342"/>
         <source>Manually</source>
         <translation>Ručně</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="347"/>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="318"/>
         <source>On application exit</source>
         <translation>Při ukončení aplikace</translation>
     </message>
@@ -13802,60 +13845,50 @@
     <message>
         <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="265"/>
         <source>Security</source>
-        <translation>Bezpečnost</translation>
+        <translation type="obsolete">Bezpečnost</translation>
     </message>
     <message>
         <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="271"/>
         <source>Select to save passwords</source>
-        <translation>Vybrat pro uložení hesel</translation>
+        <translation type="obsolete">Vybrat pro uložení hesel</translation>
     </message>
     <message>
         <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="274"/>
         <source>Save passwords</source>
-        <translation>Uložit hesla</translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="281"/>
-        <source>Select to enable DNS prefetch</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="284"/>
-        <source>Use DNS prefetching to improve page loading</source>
+        <translation type="obsolete">Uložit hesla</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="342"/>
+        <source>Policy</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="348"/>
+        <source>Select to prefer the network</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="351"/>
+        <source>Keep cache in sync</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="358"/>
+        <source>Select to prefer cached data</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="361"/>
+        <source>Use cache whenever possible</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="368"/>
+        <source>Select to use cached data only</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
         <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="371"/>
-        <source>Policy</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="377"/>
-        <source>Select to prefer the network</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="380"/>
-        <source>Keep cache in sync</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="387"/>
-        <source>Select to prefer cached data</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="390"/>
-        <source>Use cache whenever possible</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="397"/>
-        <source>Select to use cached data only</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="400"/>
         <source>Offline browsing mode</source>
         <translation type="unfinished"></translation>
     </message>
@@ -13880,17 +13913,17 @@
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="452"/>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="423"/>
         <source>Web Search</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="458"/>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="429"/>
         <source>Language:</source>
         <translation type="unfinished">Jazyk:</translation>
     </message>
     <message>
-        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="465"/>
+        <location filename="Preferences/ConfigurationPages/HelpWebBrowserPage.ui" line="436"/>
         <source>Select the language to be used for web searches</source>
         <translation type="unfinished"></translation>
     </message>
@@ -14749,7 +14782,7 @@
         <translation>Filtrováno: </translation>
     </message>
     <message>
-        <location filename="Helpviewer/HelpWindow.py" line="2062"/>
+        <location filename="Helpviewer/HelpWindow.py" line="2076"/>
         <source>Could not find an associated content.</source>
         <translation>Asociovaný obsah nelze nalézt.</translation>
     </message>
@@ -14814,22 +14847,22 @@
         <translation>&lt;b&gt;Znovu indexovat dokumentaci&lt;/b&gt;&lt;p&gt;Přeindexuje dokumentaci.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="Helpviewer/HelpWindow.py" line="2171"/>
+        <location filename="Helpviewer/HelpWindow.py" line="2185"/>
         <source>Updating search index</source>
         <translation>Aktualizovat index pro hledání</translation>
     </message>
     <message>
-        <location filename="Helpviewer/HelpWindow.py" line="2223"/>
+        <location filename="Helpviewer/HelpWindow.py" line="2237"/>
         <source>Looking for Documentation...</source>
         <translation>Vyhledat dokumentaci...</translation>
     </message>
     <message>
-        <location filename="Helpviewer/HelpWindow.py" line="2253"/>
+        <location filename="Helpviewer/HelpWindow.py" line="2267"/>
         <source>Unfiltered</source>
         <translation>Nefiltrováno</translation>
     </message>
     <message>
-        <location filename="Helpviewer/HelpWindow.py" line="2272"/>
+        <location filename="Helpviewer/HelpWindow.py" line="2286"/>
         <source>Help Engine</source>
         <translation>Engine nápovědy</translation>
     </message>
@@ -15341,7 +15374,7 @@
         <translation>&lt;b&gt;Ad Block...&lt;/b&gt;&lt;p&gt;Otevře dialog pro konfiguraci AdBlock odebírání a pravidel.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="Helpviewer/HelpWindow.py" line="2232"/>
+        <location filename="Helpviewer/HelpWindow.py" line="2246"/>
         <source>eric5 Web Browser</source>
         <translation>eric5 web prohlížeč</translation>
     </message>
@@ -15411,37 +15444,37 @@
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Helpviewer/HelpWindow.py" line="2587"/>
+        <location filename="Helpviewer/HelpWindow.py" line="2601"/>
         <source>ISO</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Helpviewer/HelpWindow.py" line="2588"/>
+        <location filename="Helpviewer/HelpWindow.py" line="2602"/>
         <source>Windows</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Helpviewer/HelpWindow.py" line="2589"/>
+        <location filename="Helpviewer/HelpWindow.py" line="2603"/>
         <source>ISCII</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Helpviewer/HelpWindow.py" line="2590"/>
+        <location filename="Helpviewer/HelpWindow.py" line="2604"/>
         <source>Unicode</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Helpviewer/HelpWindow.py" line="2591"/>
+        <location filename="Helpviewer/HelpWindow.py" line="2605"/>
         <source>Other</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Helpviewer/HelpWindow.py" line="2592"/>
+        <location filename="Helpviewer/HelpWindow.py" line="2606"/>
         <source>IBM</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Helpviewer/HelpWindow.py" line="2614"/>
+        <location filename="Helpviewer/HelpWindow.py" line="2628"/>
         <source>Default Encoding</source>
         <translation type="unfinished"></translation>
     </message>
@@ -15501,12 +15534,12 @@
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Helpviewer/HelpWindow.py" line="2717"/>
+        <location filename="Helpviewer/HelpWindow.py" line="2731"/>
         <source>VirusTotal Scan</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Helpviewer/HelpWindow.py" line="2717"/>
+        <location filename="Helpviewer/HelpWindow.py" line="2731"/>
         <source>&lt;p&gt;The VirusTotal scan could not be scheduled.&lt;p&gt;
 &lt;p&gt;Reason: {0}&lt;/p&gt;</source>
         <translation type="unfinished"></translation>
@@ -23397,6 +23430,79 @@
     </message>
 </context>
 <context>
+    <name>MasterPasswordEntryDialog</name>
+    <message>
+        <location filename="Preferences/ConfigurationPages/MasterPasswordEntryDialog.ui" line="14"/>
+        <source>Master Password</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/MasterPasswordEntryDialog.ui" line="23"/>
+        <source>&lt;p&gt;Enter your master password below. This password will be used to encrypt sensitive data. You will be asked once per session for this password when the data needs to be accessed for the first time.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Note: If you forget the master password, the encrypted data cannot be recovered!&lt;/b&gt;&lt;/p&gt;</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/MasterPasswordEntryDialog.ui" line="48"/>
+        <source>Current Password:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/MasterPasswordEntryDialog.ui" line="55"/>
+        <source>Enter the current password</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/MasterPasswordEntryDialog.ui" line="65"/>
+        <source>New Password:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/MasterPasswordEntryDialog.ui" line="72"/>
+        <source>Enter the new password</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/MasterPasswordEntryDialog.ui" line="82"/>
+        <source>New Password (again):</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/MasterPasswordEntryDialog.ui" line="89"/>
+        <source>Repeat the new password</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/MasterPasswordEntryDialog.ui" line="101"/>
+        <source>Shows an indication for the password strength</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/MasterPasswordEntryDialog.py" line="36"/>
+        <source>(not defined yet)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/MasterPasswordEntryDialog.py" line="51"/>
+        <source>Wrong password entered.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/MasterPasswordEntryDialog.py" line="55"/>
+        <source>New password must not be empty.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/MasterPasswordEntryDialog.py" line="60"/>
+        <source>Repeated password is wrong.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/MasterPasswordEntryDialog.py" line="65"/>
+        <source>Old and new password must not be the same.</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
     <name>MdiArea</name>
     <message>
         <location filename="Plugins/ViewManagerPlugins/MdiArea/MdiArea.py" line="211"/>
@@ -25178,6 +25284,16 @@
         <source>When download finished successfully</source>
         <translation type="unfinished"></translation>
     </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/NetworkPage.ui" line="309"/>
+        <source>Press to clear the saved proxy passwords</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/NetworkPage.ui" line="312"/>
+        <source>Clear Proxy Passwords</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>NetworkProtocolUnknownErrorReply</name>
@@ -25695,50 +25811,55 @@
 <context>
     <name>PasswordManager</name>
     <message>
-        <location filename="Helpviewer/Passwords/PasswordManager.py" line="193"/>
+        <location filename="Helpviewer/Passwords/PasswordManager.py" line="196"/>
         <source>Saving login data</source>
         <translation>Uložit login data</translation>
     </message>
     <message>
-        <location filename="Helpviewer/Passwords/PasswordManager.py" line="233"/>
+        <location filename="Helpviewer/Passwords/PasswordManager.py" line="236"/>
         <source>Loading login data</source>
         <translation>Nahrávání login dat</translation>
     </message>
     <message>
-        <location filename="Helpviewer/Passwords/PasswordManager.py" line="378"/>
+        <location filename="Helpviewer/Passwords/PasswordManager.py" line="382"/>
         <source>&lt;b&gt;Would you like to save this password?&lt;/b&gt;&lt;br/&gt;To review passwords you have saved and remove them, use the password management dialog of the Settings menu.</source>
         <translation>&lt;b&gt;Chcete uložit toto heslo?&lt;/b&gt;&lt;br/&gt;Pro kontrolu uložených a odebraných hesel použijte dialog správce hesel v menu nastavení.</translation>
     </message>
     <message>
-        <location filename="Helpviewer/Passwords/PasswordManager.py" line="385"/>
+        <location filename="Helpviewer/Passwords/PasswordManager.py" line="389"/>
         <source>Never for this site</source>
         <translation>Nikdy pro tento web</translation>
     </message>
     <message>
-        <location filename="Helpviewer/Passwords/PasswordManager.py" line="387"/>
+        <location filename="Helpviewer/Passwords/PasswordManager.py" line="391"/>
         <source>Not now</source>
         <translation>Teď ne</translation>
     </message>
     <message>
-        <location filename="Helpviewer/Passwords/PasswordManager.py" line="193"/>
+        <location filename="Helpviewer/Passwords/PasswordManager.py" line="196"/>
         <source>&lt;p&gt;Login data could not be saved to &lt;b&gt;{0}&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Reason: {1}&lt;/p&gt;</source>
         <translation>&lt;p&gt;Login data nelze uložit do &lt;b&gt;{0}&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Důvod: {1}&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="Helpviewer/Passwords/PasswordManager.py" line="210"/>
+        <location filename="Helpviewer/Passwords/PasswordManager.py" line="213"/>
         <source>&lt;p&gt;Login data could not be loaded from &lt;b&gt;{0}&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Reason: {1}&lt;/p&gt;</source>
         <translation>&lt;p&gt;Login data nelze z &lt;b&gt;{0}&lt;/b&gt; nahrát&lt;/p&gt;&lt;p&gt;Důvod: {1}&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="Helpviewer/Passwords/PasswordManager.py" line="233"/>
+        <location filename="Helpviewer/Passwords/PasswordManager.py" line="236"/>
         <source>&lt;p&gt;Login data could not be loaded from &lt;b&gt;{0}&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Reason: Wrong input format&lt;/p&gt;</source>
         <translation>&lt;p&gt;Login data nelze z &lt;b&gt;{0}&lt;/b&gt; nahrát&lt;/p&gt;&lt;p&gt;Důvod: Chybný vstupní formát&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="Helpviewer/Passwords/PasswordManager.py" line="378"/>
+        <location filename="Helpviewer/Passwords/PasswordManager.py" line="382"/>
         <source>Save password</source>
         <translation type="unfinished"></translation>
     </message>
+    <message>
+        <location filename="Helpviewer/Passwords/PasswordManager.py" line="586"/>
+        <source>Re-encoding saved passwords...</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>PasswordModel</name>
@@ -26946,17 +27067,17 @@
 <context>
     <name>Preferences</name>
     <message>
-        <location filename="Preferences/__init__.py" line="940"/>
+        <location filename="Preferences/__init__.py" line="942"/>
         <source>Export Preferences</source>
         <translation>Předvolby exportu</translation>
     </message>
     <message>
-        <location filename="Preferences/__init__.py" line="967"/>
+        <location filename="Preferences/__init__.py" line="969"/>
         <source>Import Preferences</source>
         <translation>Předvolby importu</translation>
     </message>
     <message>
-        <location filename="Preferences/__init__.py" line="967"/>
+        <location filename="Preferences/__init__.py" line="969"/>
         <source>Properties File (*.ini);;All Files (*)</source>
         <translation type="unfinished"></translation>
     </message>
@@ -33030,17 +33151,17 @@
 <context>
     <name>SearchReplaceWidget</name>
     <message>
-        <location filename="QScintilla/SearchReplaceWidget.py" line="476"/>
+        <location filename="QScintilla/SearchReplaceWidget.py" line="478"/>
         <source>&apos;{0}&apos; was not found.</source>
         <translation>&apos;{0}&apos; nebyl nalezen.</translation>
     </message>
     <message>
-        <location filename="QScintilla/SearchReplaceWidget.py" line="548"/>
+        <location filename="QScintilla/SearchReplaceWidget.py" line="550"/>
         <source>Replaced {0} occurrences.</source>
         <translation>Nahrazeno {0} výskytů.</translation>
     </message>
     <message>
-        <location filename="QScintilla/SearchReplaceWidget.py" line="552"/>
+        <location filename="QScintilla/SearchReplaceWidget.py" line="554"/>
         <source>Nothing replaced because &apos;{0}&apos; was not found.</source>
         <translation>Nebylo nic nahrazeno, protože &apos;{0}&apos; nebyl nalezen.</translation>
     </message>
@@ -33119,6 +33240,64 @@
     </message>
 </context>
 <context>
+    <name>SecurityPage</name>
+    <message>
+        <location filename="Preferences/ConfigurationPages/SecurityPage.ui" line="37"/>
+        <source>Passwords</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/SecurityPage.ui" line="43"/>
+        <source>Select to save passwords</source>
+        <translation type="unfinished">Vybrat pro uložení hesel</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/SecurityPage.ui" line="46"/>
+        <source>Save passwords</source>
+        <translation type="unfinished">Uložit hesla</translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/SecurityPage.ui" line="55"/>
+        <source>Select to use a master password</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/SecurityPage.ui" line="58"/>
+        <source>Use Master Password</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/SecurityPage.ui" line="81"/>
+        <source>Press to change the master password</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/SecurityPage.ui" line="84"/>
+        <source>Change Master Password...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/SecurityPage.ui" line="96"/>
+        <source>DNS</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/SecurityPage.ui" line="102"/>
+        <source>Select to enable DNS prefetch</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/SecurityPage.ui" line="105"/>
+        <source>Use DNS prefetching to improve page loading</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Preferences/ConfigurationPages/SecurityPage.ui" line="17"/>
+        <source>&lt;b&gt;Configure security settings&lt;/b&gt;</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
     <name>Shell</name>
     <message>
         <location filename="QScintilla/Shell.py" line="56"/>
@@ -42954,753 +43133,753 @@
 <context>
     <name>UserInterface</name>
     <message>
-        <location filename="UI/UserInterface.py" line="257"/>
+        <location filename="UI/UserInterface.py" line="261"/>
         <source>Generating Main User Interface...</source>
         <translation>Generování hlavního uživatelského rozhraní...</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="283"/>
+        <location filename="UI/UserInterface.py" line="287"/>
         <source>Setting up connections...</source>
         <translation>Nastavení připojení...</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="475"/>
+        <location filename="UI/UserInterface.py" line="479"/>
         <source>Initializing Tools...</source>
         <translation>Inicializace nástrojů...</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="484"/>
+        <location filename="UI/UserInterface.py" line="488"/>
         <source>Registering Objects...</source>
         <translation>Registrování objektů...</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="506"/>
-        <source>Initializing Actions...</source>
-        <translation>Inicializace akcí...</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="508"/>
-        <source>Initializing Menus...</source>
-        <translation>Inicializace menu...</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="510"/>
-        <source>Initializing Toolbars...</source>
-        <translation>Inicializace nástrojových lišt...</translation>
+        <source>Initializing Actions...</source>
+        <translation>Inicializace akcí...</translation>
     </message>
     <message>
         <location filename="UI/UserInterface.py" line="512"/>
+        <source>Initializing Menus...</source>
+        <translation>Inicializace menu...</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="514"/>
+        <source>Initializing Toolbars...</source>
+        <translation>Inicializace nástrojových lišt...</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="516"/>
         <source>Initializing Statusbar...</source>
         <translation>Inicializace statusbaru...</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="536"/>
+        <location filename="UI/UserInterface.py" line="540"/>
         <source>Initializing Single Application Server...</source>
         <translation>Inicializace jednouživatelského aplikačního serveru...</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="611"/>
+        <location filename="UI/UserInterface.py" line="615"/>
         <source>Loading Style Sheet</source>
         <translation>Načtení kaskádového stylu</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1350"/>
+        <location filename="UI/UserInterface.py" line="1354"/>
         <source>Project-Viewer</source>
         <translation>Prohlížeč projektu</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1391"/>
+        <location filename="UI/UserInterface.py" line="1395"/>
         <source>Debug-Viewer</source>
         <translation>Prohlížeč debugeru</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1473"/>
+        <location filename="UI/UserInterface.py" line="1477"/>
         <source>Log-Viewer</source>
         <translation>Prohlížeč logu</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1493"/>
+        <location filename="UI/UserInterface.py" line="1497"/>
         <source>Task-Viewer</source>
         <translation>Prohlížeč úloh</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1513"/>
-        <source>Template-Viewer</source>
-        <translation>Prohlížeč šablon</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1411"/>
-        <source>Shell</source>
-        <translation></translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1452"/>
-        <source>File-Browser</source>
-        <translation>Browser souborů</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1302"/>
-        <source>Quit</source>
-        <translation>Konec</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1302"/>
-        <source>&amp;Quit</source>
-        <translation>&amp;Konec</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1302"/>
-        <source>Ctrl+Q</source>
-        <comment>File|Quit</comment>
-        <translation></translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1307"/>
-        <source>Quit the IDE</source>
-        <translation>Ukončit IDE</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1308"/>
-        <source>&lt;b&gt;Quit the IDE&lt;/b&gt;&lt;p&gt;This quits the IDE. Any unsaved changes may be saved first. Any Python program being debugged will be stopped and the preferences will be written to disc.&lt;/p&gt;</source>
-        <translation>&lt;b&gt;Ukončit IDE&lt;/b&gt;&lt;p&gt;Ukončí se IDE. Nejdříve by se měly uložit neuložené změny. Python programy běžící v debug procesu budou ukončeny a nastavení budou uložena.&lt;/p&gt;</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1319"/>
-        <source>Edit Profile</source>
-        <translation>Editační profil</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1324"/>
-        <source>Activate the edit view profile</source>
-        <translation>Aktivovat profil editace</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1325"/>
-        <source>&lt;b&gt;Edit Profile&lt;/b&gt;&lt;p&gt;Activate the &quot;Edit View Profile&quot;. Windows being shown, if this profile is active, may be configured with the &quot;View Profile Configuration&quot; dialog.&lt;/p&gt;</source>
-        <translation>&lt;b&gt;Editační profil&lt;/b&gt;&lt;p&gt;Aktivování skupiny &apos;Editační profil&apos;. Okna, která se v tomto profilu zobrazí lze nastavit v dialogu &apos;Konfigurace profilu pohledů&apos;.&lt;/p&gt;</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1334"/>
-        <source>Debug Profile</source>
-        <translation>Debugovací profil</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1339"/>
-        <source>Activate the debug view profile</source>
-        <translation>Aktivovat debugovací profil</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1341"/>
-        <source>&lt;b&gt;Debug Profile&lt;/b&gt;&lt;p&gt;Activate the &quot;Debug View Profile&quot;. Windows being shown, if this profile is active, may be configured with the &quot;View Profile Configuration&quot; dialog.&lt;/p&gt;</source>
-        <translation>&lt;b&gt;Debugovací profil&lt;/b&gt;&lt;p&gt;Aktivování skupiny &apos;Debugovací profil&apos;. Okna, která se v tomto profilu zobrazí lze nastavit v dialogu &apos;Konfigurace profilu pohledů&apos;.&lt;/p&gt;</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1350"/>
-        <source>&amp;Project-Viewer</source>
-        <translation>Prohlížeč &amp;projektu</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1352"/>
-        <source>Toggle the Project-Viewer window</source>
-        <translation>Přepnout okno Prohlížeč projektu</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1353"/>
-        <source>&lt;b&gt;Toggle the Project-Viewer window&lt;/b&gt;&lt;p&gt;If the Project-Viewer window is hidden then display it. If it is displayed then close it.&lt;/p&gt;</source>
-        <translation>&lt;b&gt;Přepnout okno Prohlížeč projektu&lt;/b&gt;&lt;p&gt;Pokud bylo okno skryto, tak se zobrazí. Pokud se zobrazovalo, tak se skryje.&lt;/p&gt;</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1361"/>
-        <source>Activate Project-Viewer</source>
-        <translation>Aktivovat prohlížeč projektu</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1361"/>
-        <source>Alt+Shift+P</source>
-        <translation></translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1402"/>
-        <source>Alt+Shift+D</source>
-        <translation></translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1411"/>
-        <source>&amp;Shell</source>
-        <translation>&amp;Shell</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1413"/>
-        <source>Toggle the Shell window</source>
-        <translation>Zobrazit/skrýt Shell okno</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1414"/>
-        <source>&lt;b&gt;Toggle the Shell window&lt;/b&gt;&lt;p&gt;If the Shell window is hidden then display it. If it is displayed then close it.&lt;/p&gt;</source>
-        <translation>&lt;b&gt;Zobrazit/skrýt Shell okno&lt;/b&gt;&lt;p&gt;Pokud je shell okno skryté zobrazí se. Pokud se okno zobrazuje, tak se skryje.&lt;/p&gt;</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1423"/>
-        <source>Activate Shell</source>
-        <translation>Aktivovat Shell</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1423"/>
-        <source>Alt+Shift+S</source>
-        <translation></translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1452"/>
-        <source>File-&amp;Browser</source>
-        <translation>&amp;Browser souborů</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1454"/>
-        <source>Toggle the File-Browser window</source>
-        <translation>Zobrazit/skrýt browser souborů</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1455"/>
-        <source>&lt;b&gt;Toggle the File-Browser window&lt;/b&gt;&lt;p&gt;If the File-Browser window is hidden then display it. If it is displayed then close it.&lt;/p&gt;</source>
-        <translation>&lt;b&gt;Zobrazit/skrýt browser souborů&lt;/b&gt;&lt;p&gt;Pokud je okno skryté zobrazí se. Pokud se okno zobrazuje, tak se skryje.&lt;/p&gt;</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1464"/>
-        <source>Activate File-Browser</source>
-        <translation>Aktivovat Browser souborů</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1464"/>
-        <source>Alt+Shift+F</source>
-        <translation></translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1473"/>
-        <source>&amp;Log-Viewer</source>
-        <translation>&amp;Log prohlížeč</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1475"/>
-        <source>Toggle the Log-Viewer window</source>
-        <translation>Zobrazit/skrýt Log prohlížeč</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1476"/>
-        <source>&lt;b&gt;Toggle the Log-Viewer window&lt;/b&gt;&lt;p&gt;If the Log-Viewer window is hidden then display it. If it is displayed then close it.&lt;/p&gt;</source>
-        <translation>&lt;b&gt;Zobrazit/skrýt Log prohlížeč&lt;/b&gt;&lt;p&gt;Pokud je okno skryté zobrazí se. Pokud se okno zobrazuje, tak se skryje.&lt;/p&gt;</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1484"/>
-        <source>Activate Log-Viewer</source>
-        <translation>Aktivovat Log prohlížeč</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1484"/>
-        <source>Alt+Shift+G</source>
-        <translation></translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1493"/>
-        <source>T&amp;ask-Viewer</source>
-        <translation>Pr&amp;ohlížeč úloh</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1495"/>
-        <source>Toggle the Task-Viewer window</source>
-        <translation>Zobrazit/skrýt prohlížeč úloh</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1496"/>
-        <source>&lt;b&gt;Toggle the Task-Viewer window&lt;/b&gt;&lt;p&gt;If the Task-Viewer window is hidden then display it. If it is displayed then close it.&lt;/p&gt;</source>
-        <translation>&lt;b&gt;Zobrazit/skrýt prohlížeč úloh&lt;/b&gt;&lt;p&gt;Pokud je okno skryté zobrazí se. Pokud se okno zobrazuje, tak se skryje.&lt;/p&gt;</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1504"/>
-        <source>Activate Task-Viewer</source>
-        <translation>Aktivovat prohlížeč úloh</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1504"/>
-        <source>Alt+Shift+T</source>
-        <translation></translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1515"/>
-        <source>Toggle the Template-Viewer window</source>
-        <translation>Zobrazit/skrýt prohlížeč šablon</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="1517"/>
+        <source>Template-Viewer</source>
+        <translation>Prohlížeč šablon</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1415"/>
+        <source>Shell</source>
+        <translation></translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1456"/>
+        <source>File-Browser</source>
+        <translation>Browser souborů</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1306"/>
+        <source>Quit</source>
+        <translation>Konec</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1306"/>
+        <source>&amp;Quit</source>
+        <translation>&amp;Konec</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1306"/>
+        <source>Ctrl+Q</source>
+        <comment>File|Quit</comment>
+        <translation></translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1311"/>
+        <source>Quit the IDE</source>
+        <translation>Ukončit IDE</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1312"/>
+        <source>&lt;b&gt;Quit the IDE&lt;/b&gt;&lt;p&gt;This quits the IDE. Any unsaved changes may be saved first. Any Python program being debugged will be stopped and the preferences will be written to disc.&lt;/p&gt;</source>
+        <translation>&lt;b&gt;Ukončit IDE&lt;/b&gt;&lt;p&gt;Ukončí se IDE. Nejdříve by se měly uložit neuložené změny. Python programy běžící v debug procesu budou ukončeny a nastavení budou uložena.&lt;/p&gt;</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1323"/>
+        <source>Edit Profile</source>
+        <translation>Editační profil</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1328"/>
+        <source>Activate the edit view profile</source>
+        <translation>Aktivovat profil editace</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1329"/>
+        <source>&lt;b&gt;Edit Profile&lt;/b&gt;&lt;p&gt;Activate the &quot;Edit View Profile&quot;. Windows being shown, if this profile is active, may be configured with the &quot;View Profile Configuration&quot; dialog.&lt;/p&gt;</source>
+        <translation>&lt;b&gt;Editační profil&lt;/b&gt;&lt;p&gt;Aktivování skupiny &apos;Editační profil&apos;. Okna, která se v tomto profilu zobrazí lze nastavit v dialogu &apos;Konfigurace profilu pohledů&apos;.&lt;/p&gt;</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1338"/>
+        <source>Debug Profile</source>
+        <translation>Debugovací profil</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1343"/>
+        <source>Activate the debug view profile</source>
+        <translation>Aktivovat debugovací profil</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1345"/>
+        <source>&lt;b&gt;Debug Profile&lt;/b&gt;&lt;p&gt;Activate the &quot;Debug View Profile&quot;. Windows being shown, if this profile is active, may be configured with the &quot;View Profile Configuration&quot; dialog.&lt;/p&gt;</source>
+        <translation>&lt;b&gt;Debugovací profil&lt;/b&gt;&lt;p&gt;Aktivování skupiny &apos;Debugovací profil&apos;. Okna, která se v tomto profilu zobrazí lze nastavit v dialogu &apos;Konfigurace profilu pohledů&apos;.&lt;/p&gt;</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1354"/>
+        <source>&amp;Project-Viewer</source>
+        <translation>Prohlížeč &amp;projektu</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1356"/>
+        <source>Toggle the Project-Viewer window</source>
+        <translation>Přepnout okno Prohlížeč projektu</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1357"/>
+        <source>&lt;b&gt;Toggle the Project-Viewer window&lt;/b&gt;&lt;p&gt;If the Project-Viewer window is hidden then display it. If it is displayed then close it.&lt;/p&gt;</source>
+        <translation>&lt;b&gt;Přepnout okno Prohlížeč projektu&lt;/b&gt;&lt;p&gt;Pokud bylo okno skryto, tak se zobrazí. Pokud se zobrazovalo, tak se skryje.&lt;/p&gt;</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1365"/>
+        <source>Activate Project-Viewer</source>
+        <translation>Aktivovat prohlížeč projektu</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1365"/>
+        <source>Alt+Shift+P</source>
+        <translation></translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1406"/>
+        <source>Alt+Shift+D</source>
+        <translation></translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1415"/>
+        <source>&amp;Shell</source>
+        <translation>&amp;Shell</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1417"/>
+        <source>Toggle the Shell window</source>
+        <translation>Zobrazit/skrýt Shell okno</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1418"/>
+        <source>&lt;b&gt;Toggle the Shell window&lt;/b&gt;&lt;p&gt;If the Shell window is hidden then display it. If it is displayed then close it.&lt;/p&gt;</source>
+        <translation>&lt;b&gt;Zobrazit/skrýt Shell okno&lt;/b&gt;&lt;p&gt;Pokud je shell okno skryté zobrazí se. Pokud se okno zobrazuje, tak se skryje.&lt;/p&gt;</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1427"/>
+        <source>Activate Shell</source>
+        <translation>Aktivovat Shell</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1427"/>
+        <source>Alt+Shift+S</source>
+        <translation></translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1456"/>
+        <source>File-&amp;Browser</source>
+        <translation>&amp;Browser souborů</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1458"/>
+        <source>Toggle the File-Browser window</source>
+        <translation>Zobrazit/skrýt browser souborů</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1459"/>
+        <source>&lt;b&gt;Toggle the File-Browser window&lt;/b&gt;&lt;p&gt;If the File-Browser window is hidden then display it. If it is displayed then close it.&lt;/p&gt;</source>
+        <translation>&lt;b&gt;Zobrazit/skrýt browser souborů&lt;/b&gt;&lt;p&gt;Pokud je okno skryté zobrazí se. Pokud se okno zobrazuje, tak se skryje.&lt;/p&gt;</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1468"/>
+        <source>Activate File-Browser</source>
+        <translation>Aktivovat Browser souborů</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1468"/>
+        <source>Alt+Shift+F</source>
+        <translation></translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1477"/>
+        <source>&amp;Log-Viewer</source>
+        <translation>&amp;Log prohlížeč</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1479"/>
+        <source>Toggle the Log-Viewer window</source>
+        <translation>Zobrazit/skrýt Log prohlížeč</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1480"/>
+        <source>&lt;b&gt;Toggle the Log-Viewer window&lt;/b&gt;&lt;p&gt;If the Log-Viewer window is hidden then display it. If it is displayed then close it.&lt;/p&gt;</source>
+        <translation>&lt;b&gt;Zobrazit/skrýt Log prohlížeč&lt;/b&gt;&lt;p&gt;Pokud je okno skryté zobrazí se. Pokud se okno zobrazuje, tak se skryje.&lt;/p&gt;</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1488"/>
+        <source>Activate Log-Viewer</source>
+        <translation>Aktivovat Log prohlížeč</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1488"/>
+        <source>Alt+Shift+G</source>
+        <translation></translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1497"/>
+        <source>T&amp;ask-Viewer</source>
+        <translation>Pr&amp;ohlížeč úloh</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1499"/>
+        <source>Toggle the Task-Viewer window</source>
+        <translation>Zobrazit/skrýt prohlížeč úloh</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1500"/>
+        <source>&lt;b&gt;Toggle the Task-Viewer window&lt;/b&gt;&lt;p&gt;If the Task-Viewer window is hidden then display it. If it is displayed then close it.&lt;/p&gt;</source>
+        <translation>&lt;b&gt;Zobrazit/skrýt prohlížeč úloh&lt;/b&gt;&lt;p&gt;Pokud je okno skryté zobrazí se. Pokud se okno zobrazuje, tak se skryje.&lt;/p&gt;</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1508"/>
+        <source>Activate Task-Viewer</source>
+        <translation>Aktivovat prohlížeč úloh</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1508"/>
+        <source>Alt+Shift+T</source>
+        <translation></translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1519"/>
+        <source>Toggle the Template-Viewer window</source>
+        <translation>Zobrazit/skrýt prohlížeč šablon</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1521"/>
         <source>&lt;b&gt;Toggle the Template-Viewer window&lt;/b&gt;&lt;p&gt;If the Template-Viewer window is hidden then display it. If it is displayed then close it.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Zobrazit/skrýt prohlížeč šablon&lt;/b&gt;&lt;p&gt;Pokud je okno skryté zobrazí se. Pokud se okno zobrazuje, tak se skryje.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1525"/>
+        <location filename="UI/UserInterface.py" line="1529"/>
         <source>Activate Template-Viewer</source>
         <translation>Aktivovat prohlížeč šablon</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1382"/>
+        <location filename="UI/UserInterface.py" line="1386"/>
         <source>Alt+Shift+M</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1646"/>
+        <location filename="UI/UserInterface.py" line="1650"/>
         <source>What&apos;s This?</source>
         <translation>Co je to?</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1646"/>
+        <location filename="UI/UserInterface.py" line="1650"/>
         <source>&amp;What&apos;s This?</source>
         <translation>&amp;Co je to?</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1646"/>
+        <location filename="UI/UserInterface.py" line="1650"/>
         <source>Shift+F1</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1651"/>
+        <location filename="UI/UserInterface.py" line="1655"/>
         <source>Context sensitive help</source>
         <translation>Kontextově senzitivní nápověda</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1652"/>
+        <location filename="UI/UserInterface.py" line="1656"/>
         <source>&lt;b&gt;Display context sensitive help&lt;/b&gt;&lt;p&gt;In What&apos;s This? mode, the mouse cursor shows an arrow with a question mark, and you can click on the interface elements to get a short description of what they do and how to use them. In dialogs, this feature can be accessed using the context help button in the titlebar.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Zobrazit kontextově senzitivní nápovědu&lt;/b&gt;&lt;p&gt;V režimu &quot;Co je to?&quot; se nad různými prvky aplikace u kurzoru zobrazí otazník. Když pak kliknete na tyto prvky, zobrazí se krátký popis co daný prvek znamená a jak jej použít. V dialogových oknech se tato funkce spustí tlačítkem kontextové nápovědy na horní liště.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1663"/>
+        <location filename="UI/UserInterface.py" line="1667"/>
         <source>Helpviewer</source>
         <translation>Prohlížeč nápovědy</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1663"/>
+        <location filename="UI/UserInterface.py" line="1667"/>
         <source>&amp;Helpviewer...</source>
         <translation>Pro&amp;hlížeč nápovědy...</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1663"/>
+        <location filename="UI/UserInterface.py" line="1667"/>
         <source>F1</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1668"/>
+        <location filename="UI/UserInterface.py" line="1672"/>
         <source>Open the helpviewer window</source>
         <translation>Otevřít okno prohlížeče nápovědy</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1686"/>
+        <location filename="UI/UserInterface.py" line="1690"/>
         <source>Show Versions</source>
         <translation>Zobrazit verze</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1686"/>
+        <location filename="UI/UserInterface.py" line="1690"/>
         <source>Show &amp;Versions</source>
         <translation>Zobrazit &amp;verze</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1688"/>
+        <location filename="UI/UserInterface.py" line="1692"/>
         <source>Display version information</source>
         <translation>Zobrazit informace o verzích</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1689"/>
+        <location filename="UI/UserInterface.py" line="1693"/>
         <source>&lt;b&gt;Show Versions&lt;/b&gt;&lt;p&gt;Display version information.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Zobrazit verze&lt;/b&gt;&lt;p&gt;Zobrazí informace o verzích.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1698"/>
+        <location filename="UI/UserInterface.py" line="1702"/>
         <source>Check for Updates</source>
         <translation>Zjistit aktualizace</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1696"/>
+        <location filename="UI/UserInterface.py" line="1700"/>
         <source>Check for &amp;Updates...</source>
         <translation>Zjistit akt&amp;ualizace...</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2787"/>
+        <location filename="UI/UserInterface.py" line="2791"/>
         <source>Report Bug</source>
         <translation>Reportovat Bugy</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1719"/>
+        <location filename="UI/UserInterface.py" line="1723"/>
         <source>Report &amp;Bug...</source>
         <translation>Reportovat &amp;Bugy...</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1721"/>
+        <location filename="UI/UserInterface.py" line="1725"/>
         <source>Report a bug</source>
         <translation>Reportovat bug</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1722"/>
+        <location filename="UI/UserInterface.py" line="1726"/>
         <source>&lt;b&gt;Report Bug...&lt;/b&gt;&lt;p&gt;Opens a dialog to report a bug.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Reportovat bug...&lt;/b&gt;&lt;p&gt;Otevře se dialog pro reportování bugu.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2409"/>
+        <location filename="UI/UserInterface.py" line="2413"/>
         <source>Unittest</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1741"/>
-        <source>&amp;Unittest...</source>
-        <translation>&amp;Unittest...</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="1745"/>
+        <source>&amp;Unittest...</source>
+        <translation>&amp;Unittest...</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1749"/>
         <source>Start unittest dialog</source>
         <translation>Otevřít dialog unittestu</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1746"/>
+        <location filename="UI/UserInterface.py" line="1750"/>
         <source>&lt;b&gt;Unittest&lt;/b&gt;&lt;p&gt;Perform unit tests. The dialog gives you the ability to select and run a unittest suite.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Unittest&lt;/b&gt;&lt;p&gt;Provést unittesty. V dialogovém okně se nastaví který test se má provést.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1754"/>
-        <source>Unittest Restart</source>
-        <translation>Restart unittestu</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1754"/>
-        <source>&amp;Restart Unittest...</source>
-        <translation>&amp;Restart unittestu...</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="1758"/>
+        <source>Unittest Restart</source>
+        <translation>Restart unittestu</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1758"/>
+        <source>&amp;Restart Unittest...</source>
+        <translation>&amp;Restart unittestu...</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1762"/>
         <source>Restart last unittest</source>
         <translation>Restart posledního unittestu</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1759"/>
+        <location filename="UI/UserInterface.py" line="1763"/>
         <source>&lt;b&gt;Restart Unittest&lt;/b&gt;&lt;p&gt;Restart the unittest performed last.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Restart unittestu&lt;/b&gt;&lt;p&gt;Restartuje se poslední provedený unittest.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1767"/>
+        <location filename="UI/UserInterface.py" line="1771"/>
         <source>Unittest Script</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1767"/>
-        <source>Unittest &amp;Script...</source>
-        <translation>Unittest &amp;Script...</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="1771"/>
+        <source>Unittest &amp;Script...</source>
+        <translation>Unittest &amp;Script...</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1775"/>
         <source>Run unittest with current script</source>
         <translation>Spustit unittest s aktuálním skriptem</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1772"/>
+        <location filename="UI/UserInterface.py" line="1776"/>
         <source>&lt;b&gt;Unittest Script&lt;/b&gt;&lt;p&gt;Run unittest with current script.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Unittest Script&lt;/b&gt;&lt;p&gt;Spustit unittest s aktuálním skriptem.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="4001"/>
+        <location filename="UI/UserInterface.py" line="4005"/>
         <source>Unittest Project</source>
         <translation>Unittest Projekt</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1780"/>
-        <source>Unittest &amp;Project...</source>
-        <translation>Unittest &amp;Projekt...</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="1784"/>
+        <source>Unittest &amp;Project...</source>
+        <translation>Unittest &amp;Projekt...</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1788"/>
         <source>Run unittest with current project</source>
         <translation>Spustit unittest s aktuálním projektem</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1785"/>
+        <location filename="UI/UserInterface.py" line="1789"/>
         <source>&lt;b&gt;Unittest Project&lt;/b&gt;&lt;p&gt;Run unittest with current project.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Unittest projekt&lt;/b&gt;&lt;p&gt;Spustit unittest s aktuálním projektem.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1798"/>
-        <source>Qt-Designer 4</source>
-        <translation></translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1801"/>
-        <source>Start Qt-Designer 4</source>
-        <translation>Spustit Qt-Designer 4</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="1802"/>
+        <source>Qt-Designer 4</source>
+        <translation></translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1805"/>
+        <source>Start Qt-Designer 4</source>
+        <translation>Spustit Qt-Designer 4</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1806"/>
         <source>&lt;b&gt;Qt-Designer 4&lt;/b&gt;&lt;p&gt;Start Qt-Designer 4.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Qt-Designer 4&lt;/b&gt;&lt;p&gt;Spustit Qt-Designer 4.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1815"/>
-        <source>Qt-Linguist 4</source>
-        <translation></translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1818"/>
-        <source>Start Qt-Linguist 4</source>
-        <translation>Spustit Qt-Linguist 4</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="1819"/>
+        <source>Qt-Linguist 4</source>
+        <translation></translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1822"/>
+        <source>Start Qt-Linguist 4</source>
+        <translation>Spustit Qt-Linguist 4</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1823"/>
         <source>&lt;b&gt;Qt-Linguist 4&lt;/b&gt;&lt;p&gt;Start Qt-Linguist 4.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Qt-Linguist 4&lt;/b&gt;&lt;p&gt;Spustit Qt-Linguist 4.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1828"/>
-        <source>UI Previewer</source>
-        <translation></translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1828"/>
-        <source>&amp;UI Previewer...</source>
-        <translation>&amp;UI Previewer...</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1831"/>
-        <source>Start the UI Previewer</source>
-        <translation>Spustit UI Previewer</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="1832"/>
+        <source>UI Previewer</source>
+        <translation></translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1832"/>
+        <source>&amp;UI Previewer...</source>
+        <translation>&amp;UI Previewer...</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1835"/>
+        <source>Start the UI Previewer</source>
+        <translation>Spustit UI Previewer</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1836"/>
         <source>&lt;b&gt;UI Previewer&lt;/b&gt;&lt;p&gt;Start the UI Previewer.&lt;/p&gt;</source>
         <translation>&lt;b&gt;UI Previewer&lt;/b&gt;&lt;p&gt;Spustit UI Previewer.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1839"/>
-        <source>Translations Previewer</source>
-        <translation>Náhled překladů</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1839"/>
-        <source>&amp;Translations Previewer...</source>
-        <translation>Náhled &amp;překladů...</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1842"/>
-        <source>Start the Translations Previewer</source>
-        <translation>Spustit Previewer překladů</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="1843"/>
+        <source>Translations Previewer</source>
+        <translation>Náhled překladů</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1843"/>
+        <source>&amp;Translations Previewer...</source>
+        <translation>Náhled &amp;překladů...</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1846"/>
+        <source>Start the Translations Previewer</source>
+        <translation>Spustit Previewer překladů</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1847"/>
         <source>&lt;b&gt;Translations Previewer&lt;/b&gt;&lt;p&gt;Start the Translations Previewer.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Previewer překladů&lt;/b&gt;&lt;p&gt;Spustit Previewer překladů.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1850"/>
+        <location filename="UI/UserInterface.py" line="1854"/>
         <source>Compare Files</source>
         <translation>Porovnat soubory</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1850"/>
-        <source>&amp;Compare Files...</source>
-        <translation>&amp;Porovnat soubory...</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1865"/>
-        <source>Compare two files</source>
-        <translation>Porovnat dva soubory</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="1854"/>
+        <source>&amp;Compare Files...</source>
+        <translation>&amp;Porovnat soubory...</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1869"/>
+        <source>Compare two files</source>
+        <translation>Porovnat dva soubory</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1858"/>
         <source>&lt;b&gt;Compare Files&lt;/b&gt;&lt;p&gt;Open a dialog to compare two files.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Porovnat soubory&lt;/b&gt;&lt;p&gt;Otevře dialog pro porovnání dvou souborů.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1861"/>
+        <location filename="UI/UserInterface.py" line="1865"/>
         <source>Compare Files side by side</source>
         <translation>Porovnat soubory stranu proti straně</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1861"/>
+        <location filename="UI/UserInterface.py" line="1865"/>
         <source>Compare Files &amp;side by side...</source>
         <translation>Porovnat soubory &amp;stranu proti straně...</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1866"/>
+        <location filename="UI/UserInterface.py" line="1870"/>
         <source>&lt;b&gt;Compare Files side by side&lt;/b&gt;&lt;p&gt;Open a dialog to compare two files and show the result side by side.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Porovnat soubory stranu proti straně&lt;/b&gt;&lt;p&gt;Otevře dialog pro porovnání souborů a zobrazení rozdílů strany proti straně.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1922"/>
+        <location filename="UI/UserInterface.py" line="1926"/>
         <source>Preferences</source>
         <translation>Nastavení</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1922"/>
-        <source>&amp;Preferences...</source>
-        <translation>Na&amp;stavení...</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1925"/>
-        <source>Set the prefered configuration</source>
-        <translation>Nastavení konfigurace</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="1926"/>
+        <source>&amp;Preferences...</source>
+        <translation>Na&amp;stavení...</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1929"/>
+        <source>Set the prefered configuration</source>
+        <translation>Nastavení konfigurace</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1930"/>
         <source>&lt;b&gt;Preferences&lt;/b&gt;&lt;p&gt;Set the configuration items of the application with your prefered values.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Nastavení&lt;/b&gt;&lt;p&gt;Upravit konfiguraci aplikace podle požadavků uživatele.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1957"/>
+        <location filename="UI/UserInterface.py" line="1961"/>
         <source>Reload APIs</source>
         <translation>Obnovit API</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1957"/>
+        <location filename="UI/UserInterface.py" line="1961"/>
         <source>Reload &amp;APIs</source>
         <translation>Obnovit &amp;API</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1959"/>
+        <location filename="UI/UserInterface.py" line="1963"/>
         <source>Reload the API information</source>
         <translation>Obnovit API nastavení</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1960"/>
+        <location filename="UI/UserInterface.py" line="1964"/>
         <source>&lt;b&gt;Reload APIs&lt;/b&gt;&lt;p&gt;Reload the API information.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Obnovit API&lt;/b&gt;&lt;p&gt;Obnovit API nastavení.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1979"/>
+        <location filename="UI/UserInterface.py" line="1983"/>
         <source>View Profiles</source>
         <translation>Profily pohledů</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1979"/>
-        <source>&amp;View Profiles...</source>
-        <translation>Profily &amp;pohledů...</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="1982"/>
-        <source>Configure view profiles</source>
-        <translation>Konfigurace profilů pohledů</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="1983"/>
+        <source>&amp;View Profiles...</source>
+        <translation>Profily &amp;pohledů...</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1986"/>
+        <source>Configure view profiles</source>
+        <translation>Konfigurace profilů pohledů</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="1987"/>
         <source>&lt;b&gt;View Profiles&lt;/b&gt;&lt;p&gt;Configure the view profiles. With this dialog you may set the visibility of the various windows for the predetermined view profiles.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Profily pohledů&lt;/b&gt;&lt;p&gt;Konfigurace profilu pohledů. V tomto dialogu můžete nastavit zobrazování různých typů pohledů - editačních oken.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2005"/>
+        <location filename="UI/UserInterface.py" line="2009"/>
         <source>Keyboard Shortcuts</source>
         <translation>Klávesové zkratky</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2005"/>
-        <source>Keyboard &amp;Shortcuts...</source>
-        <translation>Klávesové &amp;zkratky...</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="2008"/>
-        <source>Set the keyboard shortcuts</source>
-        <translation>Nastavení klávesových zkratek</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="2009"/>
+        <source>Keyboard &amp;Shortcuts...</source>
+        <translation>Klávesové &amp;zkratky...</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="2012"/>
+        <source>Set the keyboard shortcuts</source>
+        <translation>Nastavení klávesových zkratek</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="2013"/>
         <source>&lt;b&gt;Keyboard Shortcuts&lt;/b&gt;&lt;p&gt;Set the keyboard shortcuts of the application with your prefered values.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Klávesové zkratky&lt;/b&gt;&lt;p&gt;Nastavení klávesových zkratek aplikace podle zvyklostí uživatele.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="5001"/>
+        <location filename="UI/UserInterface.py" line="5023"/>
         <source>Export Keyboard Shortcuts</source>
         <translation>Exportovat klávesové zkratky</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2017"/>
-        <source>&amp;Export Keyboard Shortcuts...</source>
-        <translation>&amp;Exportovat klávesové zkratky...</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="2021"/>
+        <source>&amp;Export Keyboard Shortcuts...</source>
+        <translation>&amp;Exportovat klávesové zkratky...</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="2025"/>
         <source>Export the keyboard shortcuts</source>
         <translation>Export klávesových zkratek</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2022"/>
+        <location filename="UI/UserInterface.py" line="2026"/>
         <source>&lt;b&gt;Export Keyboard Shortcuts&lt;/b&gt;&lt;p&gt;Export the keyboard shortcuts of the application.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Export klávesových zkratek&lt;/b&gt;&lt;p&gt;Exportují se klávesové zkratky z aplikace.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="5024"/>
+        <location filename="UI/UserInterface.py" line="5046"/>
         <source>Import Keyboard Shortcuts</source>
         <translation>Import klávesových zkratek</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2029"/>
-        <source>&amp;Import Keyboard Shortcuts...</source>
-        <translation>&amp;Import klávesových zkratek...</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="2033"/>
+        <source>&amp;Import Keyboard Shortcuts...</source>
+        <translation>&amp;Import klávesových zkratek...</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="2037"/>
         <source>Import the keyboard shortcuts</source>
         <translation>Import klávesových zkratek</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2034"/>
+        <location filename="UI/UserInterface.py" line="2038"/>
         <source>&lt;b&gt;Import Keyboard Shortcuts&lt;/b&gt;&lt;p&gt;Import the keyboard shortcuts of the application.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Import klávesových zkratek&lt;/b&gt;&lt;p&gt;Do aplikace se importují klávesové zkratky.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2041"/>
+        <location filename="UI/UserInterface.py" line="2045"/>
         <source>Activate current editor</source>
         <translation>Aktivovat aktuální editor</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2041"/>
+        <location filename="UI/UserInterface.py" line="2045"/>
         <source>Alt+Shift+E</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2050"/>
+        <location filename="UI/UserInterface.py" line="2054"/>
         <source>Ctrl+Alt+Tab</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2058"/>
+        <location filename="UI/UserInterface.py" line="2062"/>
         <source>Shift+Ctrl+Alt+Tab</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2137"/>
+        <location filename="UI/UserInterface.py" line="2141"/>
         <source>Qt4 Documentation</source>
         <translation>Qt4 dokumentace</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2137"/>
+        <location filename="UI/UserInterface.py" line="2141"/>
         <source>Qt&amp;4 Documentation</source>
         <translation>Qt&amp;4 dokumentace</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2139"/>
+        <location filename="UI/UserInterface.py" line="2143"/>
         <source>Open Qt4 Documentation</source>
         <translation>Otevřít Qt4 dokumentaci</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2140"/>
+        <location filename="UI/UserInterface.py" line="2144"/>
         <source>&lt;b&gt;Qt4 Documentation&lt;/b&gt;&lt;p&gt;Display the Qt4 Documentation. Dependant upon your settings, this will either show the help in Eric&apos;s internal help viewer, or execute a web browser or Qt Assistant. &lt;/p&gt;</source>
         <translation>&lt;b&gt;Qt4 dokumentace&lt;/b&gt;&lt;p&gt;Zobrazit Qt4 dokumentaci. V závislosti na vašich nastaveních zobrazí interní Eric prohlížeč nápovědy nebo spustí webový prohlížeč nebo Qt Assistant.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2149"/>
+        <location filename="UI/UserInterface.py" line="2153"/>
         <source>PyQt4 Documentation</source>
         <translation>PyQt4 dokumentace</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2149"/>
+        <location filename="UI/UserInterface.py" line="2153"/>
         <source>P&amp;yQt4 Documentation</source>
         <translation>P&amp;yQt4 dokumentace</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2151"/>
+        <location filename="UI/UserInterface.py" line="2155"/>
         <source>Open PyQt4 Documentation</source>
         <translation>Otevřít PyQt4 dokumentaci</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2152"/>
+        <location filename="UI/UserInterface.py" line="2156"/>
         <source>&lt;b&gt;PyQt4 Documentation&lt;/b&gt;&lt;p&gt;Display the PyQt4 Documentation. Dependant upon your settings, this will either show the help in Eric&apos;s internal help viewer, or execute a web browser or Qt Assistant. &lt;/p&gt;</source>
         <translation>&lt;b&gt;PyQt4 dokumentace&lt;/b&gt;&lt;p&gt;Zobrazit PyQt4 dokumentaci. V závislosti na vašich nastaveních zobrazí interní Eric prohlížeč nápovědy nebo spustí webový prohlížeč nebo Qt Assistant.&lt;/p&gt;</translation>
     </message>
@@ -43725,287 +43904,287 @@
         <translation type="obsolete">&lt;b&gt;Python dokumentace&lt;/b&gt;&lt;p&gt;Zobrazí python dokumentaci. Pokud není adresář dokumentace nastaven, tak ve Windows se dokumentace hledá v adresáři odkud se python spouští a na Unixu v doc adresáři &lt;i&gt;/usr/share/doc/packages/python/html&lt;/i&gt;. Pokud chcete jiný, nastavte si proměnnou prostředí PYTHONDOCDIR.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2201"/>
+        <location filename="UI/UserInterface.py" line="2205"/>
         <source>Eric API Documentation</source>
         <translation>Eric API dokumentace</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2201"/>
+        <location filename="UI/UserInterface.py" line="2205"/>
         <source>&amp;Eric API Documentation</source>
         <translation>&amp;Eric API dokumentace</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2203"/>
+        <location filename="UI/UserInterface.py" line="2207"/>
         <source>Open Eric API Documentation</source>
         <translation>Otevřít Eric API dokumentaci</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2257"/>
+        <location filename="UI/UserInterface.py" line="2261"/>
         <source>&amp;Unittest</source>
         <translation>&amp;Unittest</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2272"/>
+        <location filename="UI/UserInterface.py" line="2276"/>
         <source>E&amp;xtras</source>
         <translation>E&amp;xtra funkce</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2284"/>
+        <location filename="UI/UserInterface.py" line="2288"/>
         <source>&amp;Tools</source>
         <translation>&amp;Nástroje</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2287"/>
+        <location filename="UI/UserInterface.py" line="2291"/>
         <source>Select Tool Group</source>
         <translation>Vybrat skupinu nástrojů</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2293"/>
+        <location filename="UI/UserInterface.py" line="2297"/>
         <source>Se&amp;ttings</source>
         <translation>Nas&amp;tavení</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2311"/>
+        <location filename="UI/UserInterface.py" line="2315"/>
         <source>&amp;Window</source>
         <translation>O&amp;kno</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2317"/>
+        <location filename="UI/UserInterface.py" line="2321"/>
         <source>&amp;Toolbars</source>
         <translation>&amp;Toolbary</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2342"/>
+        <location filename="UI/UserInterface.py" line="2346"/>
         <source>&amp;Help</source>
         <translation>&amp;Nápověda</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2408"/>
-        <source>Tools</source>
-        <translation>Nástroje</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="2410"/>
-        <source>Settings</source>
-        <translation>Nastavení</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="4213"/>
-        <source>Help</source>
-        <translation>Nápověda</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="2412"/>
+        <source>Tools</source>
+        <translation>Nástroje</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="2414"/>
+        <source>Settings</source>
+        <translation>Nastavení</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="4217"/>
+        <source>Help</source>
+        <translation>Nápověda</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="2416"/>
         <source>Profiles</source>
         <translation>Profily</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2736"/>
+        <location filename="UI/UserInterface.py" line="2740"/>
         <source>&lt;h3&gt;Version Numbers&lt;/h3&gt;&lt;table&gt;</source>
         <translation>&lt;h3&gt;Čísla verzí&lt;/h3&gt;&lt;table&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="5619"/>
+        <location filename="UI/UserInterface.py" line="5641"/>
         <source>&lt;/table&gt;</source>
         <translation>&lt;/table&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2787"/>
+        <location filename="UI/UserInterface.py" line="2791"/>
         <source>Email address or mail server address is empty. Please configure your Email settings in the Preferences Dialog.</source>
         <translation>Emailová adresa nebo mail server adresa jsou prázdné. Prosím, nastavte váš email v dialogovém okně Nastavení.</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="3078"/>
+        <location filename="UI/UserInterface.py" line="3082"/>
         <source>Configure Tool Groups ...</source>
         <translation>Konfigurace Skupin nástrojů...</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="3081"/>
+        <location filename="UI/UserInterface.py" line="3085"/>
         <source>Configure current Tool Group ...</source>
         <translation>Konfigurace aktuální skupiny nástrojů...</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="3129"/>
+        <location filename="UI/UserInterface.py" line="3133"/>
         <source>&amp;Builtin Tools</source>
         <translation>&amp;Vestavěné nástroje</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="4001"/>
+        <location filename="UI/UserInterface.py" line="4005"/>
         <source>There is no main script defined for the current project. Aborting</source>
         <translation>V aktuálním projektu není definován hlavní skript. Zrušeno</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="4321"/>
+        <location filename="UI/UserInterface.py" line="4325"/>
         <source>Problem</source>
         <translation>Problém</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="4454"/>
+        <location filename="UI/UserInterface.py" line="4458"/>
         <source>Process Generation Error</source>
         <translation>Chyba v procesu generování</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="4213"/>
+        <location filename="UI/UserInterface.py" line="4217"/>
         <source>Currently no custom viewer is selected. Please use the preferences dialog to specify one.</source>
         <translation>Aktuálně není vybrán žádný prohlížeč. Prosím otevřete Nastavení a nějaký vyberte.</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="4244"/>
+        <location filename="UI/UserInterface.py" line="4248"/>
         <source>&lt;p&gt;Could not start the help viewer.&lt;br&gt;Ensure that it is available as &lt;b&gt;hh&lt;/b&gt;.&lt;/p&gt;</source>
         <translation>&lt;p&gt;Nemohu spustit prohlížeč nápovědy.&lt;br&gt;Ověřte jestli je dostupný jako &lt;b&gt;hh&lt;/b&gt;.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="4804"/>
+        <location filename="UI/UserInterface.py" line="4808"/>
         <source>Documentation Missing</source>
         <translation>Dokumentace chybí</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="4789"/>
+        <location filename="UI/UserInterface.py" line="4793"/>
         <source>Documentation</source>
         <translation>Dokumentace</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="4698"/>
+        <location filename="UI/UserInterface.py" line="4702"/>
         <source>&lt;p&gt;The PyQt4 documentation starting point has not been configured.&lt;/p&gt;</source>
         <translation>&lt;p&gt;Adresář PyQt4 dokumentace není nakonfigurován.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="5143"/>
-        <source>Save tasks</source>
-        <translation>Uložit úlohy</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="5165"/>
+        <source>Save tasks</source>
+        <translation>Uložit úlohy</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="5187"/>
         <source>Read tasks</source>
         <translation>Načíst úlohy</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="5321"/>
+        <location filename="UI/UserInterface.py" line="5343"/>
         <source>Drop Error</source>
         <translation>Zahodit chybu</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="5585"/>
+        <location filename="UI/UserInterface.py" line="5607"/>
         <source>Error during updates check</source>
         <translation>Chyba během zjišťování aktualizací</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="5572"/>
+        <location filename="UI/UserInterface.py" line="5594"/>
         <source>Update available</source>
         <translation>Byla nalezena aktualizace</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1970"/>
+        <location filename="UI/UserInterface.py" line="1974"/>
         <source>Show external tools</source>
         <translation>Zobrazit externí nástroje</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1967"/>
+        <location filename="UI/UserInterface.py" line="1971"/>
         <source>Show external &amp;tools</source>
         <translation>Zobrazit externí nás&amp;troje</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="5585"/>
+        <location filename="UI/UserInterface.py" line="5607"/>
         <source>Could not perform updates check.</source>
         <translation>Kontrolu updatů nelze provést.</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="5465"/>
+        <location filename="UI/UserInterface.py" line="5487"/>
         <source>&amp;Cancel</source>
         <translation>&amp;Zrušit</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="5659"/>
+        <location filename="UI/UserInterface.py" line="5681"/>
         <source>First time usage</source>
         <translation>Spuštěno poprvé</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="252"/>
+        <location filename="UI/UserInterface.py" line="256"/>
         <source>Initializing Plugin Manager...</source>
         <translation>Inicializace Plugin manažera...</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2328"/>
+        <location filename="UI/UserInterface.py" line="2332"/>
         <source>P&amp;lugins</source>
         <translation>P&amp;luginy</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2413"/>
+        <location filename="UI/UserInterface.py" line="2417"/>
         <source>Plugins</source>
         <translation>Pluginy</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2074"/>
-        <source>Plugin Infos</source>
-        <translation>Plugin Infa</translation>
-    </message>
-    <message>
-        <location filename="UI/UserInterface.py" line="2077"/>
-        <source>Show Plugin Infos</source>
-        <translation>Zobrazit Plugin infa</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="2078"/>
+        <source>Plugin Infos</source>
+        <translation>Plugin Infa</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="2081"/>
+        <source>Show Plugin Infos</source>
+        <translation>Zobrazit Plugin infa</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="2082"/>
         <source>&lt;b&gt;Plugin Infos...&lt;/b&gt;&lt;p&gt;This opens a dialog, that show some information about loaded plugins.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Plugin Infa&lt;/b&gt;&lt;p&gt;Otevře dialog, který zobrazí informace o načtených pluginech.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2074"/>
+        <location filename="UI/UserInterface.py" line="2078"/>
         <source>&amp;Plugin Infos...</source>
         <translation>&amp;Plugin Infa...</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="3137"/>
+        <location filename="UI/UserInterface.py" line="3141"/>
         <source>&amp;Plugin Tools</source>
         <translation>&amp;Plugin nástroje</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2100"/>
+        <location filename="UI/UserInterface.py" line="2104"/>
         <source>Uninstall Plugin</source>
         <translation>Odinstalovat plugin</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2097"/>
-        <source>&amp;Uninstall Plugin...</source>
-        <translation>&amp;Odinstalovat plugin...</translation>
-    </message>
-    <message>
         <location filename="UI/UserInterface.py" line="2101"/>
+        <source>&amp;Uninstall Plugin...</source>
+        <translation>&amp;Odinstalovat plugin...</translation>
+    </message>
+    <message>
+        <location filename="UI/UserInterface.py" line="2105"/>
         <source>&lt;b&gt;Uninstall Plugin...&lt;/b&gt;&lt;p&gt;This opens a dialog to uninstall a plugin.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Odinstalovat plugin...&lt;/b&gt;&lt;p&gt;Otevře dialog pro odinstalaci pluginu.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="3290"/>
+        <location filename="UI/UserInterface.py" line="3294"/>
         <source>&amp;Show all</source>
         <translation>&amp;Zobrazit vše</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="3292"/>
+        <location filename="UI/UserInterface.py" line="3296"/>
         <source>&amp;Hide all</source>
         <translation>&amp;Skrýt vše</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="544"/>
+        <location filename="UI/UserInterface.py" line="548"/>
         <source>Activating Plugins...</source>
         <translation>Aktivace pluginů...</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2277"/>
+        <location filename="UI/UserInterface.py" line="2281"/>
         <source>Wi&amp;zards</source>
         <translation>&amp;Průvodci</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1706"/>
+        <location filename="UI/UserInterface.py" line="1710"/>
         <source>Show downloadable versions</source>
         <translation>Zobrazit verze ke stažení</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1706"/>
+        <location filename="UI/UserInterface.py" line="1710"/>
         <source>Show &amp;downloadable versions...</source>
         <translation>Zobrazit verze pro &amp;download...</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="1709"/>
+        <location filename="UI/UserInterface.py" line="1713"/>
         <source>Show the versions available for download</source>
         <translation>Zobrazit dostupné verze ke stažení</translation>
     </message>
@@ -44020,651 +44199,651 @@
         <translation type="obsolete">Nelze stáhnout soubor s verzemi.</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="5606"/>
+        <location filename="UI/UserInterface.py" line="5628"/>
         <source>&lt;h3&gt;Available versions&lt;/h3&gt;&lt;table&gt;</source>
         <translation>&lt;h3&gt;Dostupné verze&lt;/h3&gt;&lt;table&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2108"/>
+        <location filename="UI/UserInterface.py" line="2112"/>
         <source>Plugin Repository</source>
         <translation>Repozitář pluginů</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2108"/>
+        <location filename="UI/UserInterface.py" line="2112"/>
         <source>Plugin &amp;Repository...</source>
         <translation>&amp;Repozitář pluginů...</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2111"/>
+        <location filename="UI/UserInterface.py" line="2115"/>
         <source>Show Plugins available for download</source>
         <translation>Zobrazit pluginy dostupné ke stažení</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2113"/>
+        <location filename="UI/UserInterface.py" line="2117"/>
         <source>&lt;b&gt;Plugin Repository...&lt;/b&gt;&lt;p&gt;This opens a dialog, that shows a list of plugins available on the Internet.&lt;/p&gt;</source>
         <translation>&lt;b&gt;Repozitář pluginů...&lt;/b&gt;&lt;p&gt;Otevře se dialog, který zobrazí seznam pluginů dostupných ke stažení přes internet.&lt;/p&gt;</translation>
     </message>
     <message>
-        <location filename="UI/UserInterface.py" line="2089"/>
+        <location filename="UI/UserInterface.py" line="2093"/>
         <source>Install Plugins</source>