src/eric7/WebBrowser/Passwords/PasswordManager.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
--- a/src/eric7/WebBrowser/Passwords/PasswordManager.py	Wed Jul 13 11:16:20 2022 +0200
+++ b/src/eric7/WebBrowser/Passwords/PasswordManager.py	Wed Jul 13 14:55:47 2022 +0200
@@ -10,7 +10,12 @@
 import os
 
 from PyQt6.QtCore import (
-    pyqtSignal, QObject, QByteArray, QUrl, QCoreApplication, QXmlStreamReader
+    pyqtSignal,
+    QObject,
+    QByteArray,
+    QUrl,
+    QCoreApplication,
+    QXmlStreamReader,
 )
 from PyQt6.QtWidgets import QApplication
 from PyQt6.QtWebEngineCore import QWebEngineScript
@@ -31,21 +36,22 @@
 class PasswordManager(QObject):
     """
     Class implementing the password manager.
-    
+
     @signal changed() emitted to indicate a change
     @signal passwordsSaved() emitted after the passwords were saved
     """
+
     changed = pyqtSignal()
     passwordsSaved = pyqtSignal()
-    
+
     def __init__(self, parent=None):
         """
         Constructor
-        
+
         @param parent reference to the parent object (QObject)
         """
         super().__init__(parent)
-        
+
         # setup userscript to monitor forms
         script = QWebEngineScript()
         script.setName("_eric_passwordmonitor")
@@ -55,52 +61,53 @@
         script.setSourceCode(Scripts.setupFormObserver())
         profile = WebBrowser.WebBrowserWindow.WebBrowserWindow.webProfile()
         profile.scripts().insert(script)
-        
+
         self.__logins = {}
         self.__loginForms = {}
         self.__never = []
         self.__loaded = False
         self.__saveTimer = AutoSaver(self, self.save)
-        
+
         self.changed.connect(self.__saveTimer.changeOccurred)
-    
+
     def clear(self):
         """
         Public slot to clear the saved passwords.
         """
         if not self.__loaded:
             self.__load()
-        
+
         self.__logins = {}
         self.__loginForms = {}
         self.__never = []
         self.__saveTimer.changeOccurred()
         self.__saveTimer.saveIfNeccessary()
-        
+
         self.changed.emit()
-    
+
     def getLogin(self, url, realm):
         """
         Public method to get the login credentials.
-        
+
         @param url URL to get the credentials for (QUrl)
         @param realm realm to get the credentials for (string)
         @return tuple containing the user name (string) and password (string)
         """
         if not self.__loaded:
             self.__load()
-        
+
         key = self.__createKey(url, realm)
         try:
             return self.__logins[key][0], Utilities.crypto.pwConvert(
-                self.__logins[key][1], encode=False)
+                self.__logins[key][1], encode=False
+            )
         except KeyError:
             return "", ""
-    
+
     def setLogin(self, url, realm, username, password):
         """
         Public method to set the login credentials.
-        
+
         @param url URL to set the credentials for (QUrl)
         @param realm realm to set the credentials for (string)
         @param username username for the login (string)
@@ -108,18 +115,18 @@
         """
         if not self.__loaded:
             self.__load()
-        
+
         key = self.__createKey(url, realm)
         self.__logins[key] = (
             username,
-            Utilities.crypto.pwConvert(password, encode=True)
+            Utilities.crypto.pwConvert(password, encode=True),
         )
         self.changed.emit()
-    
+
     def __createKey(self, url, realm):
         """
         Private method to create the key string for the login credentials.
-        
+
         @param url URL to get the credentials for (QUrl)
         @param realm realm to get the credentials for (string)
         @return key string (string)
@@ -129,89 +136,93 @@
             authority = authority[1:]
         key = (
             "{0}://{1} ({2})".format(url.scheme(), authority, realm)
-            if realm else
-            "{0}://{1}".format(url.scheme(), authority)
+            if realm
+            else "{0}://{1}".format(url.scheme(), authority)
         )
         return key
-    
+
     def getFileName(self):
         """
         Public method to get the file name of the passwords file.
-        
+
         @return name of the passwords file (string)
         """
-        return os.path.join(Utilities.getConfigDir(),
-                            "web_browser", "logins.xml")
-    
+        return os.path.join(Utilities.getConfigDir(), "web_browser", "logins.xml")
+
     def save(self):
         """
         Public slot to save the login entries to disk.
         """
         if not self.__loaded:
             return
-        
+
         from WebBrowser.WebBrowserWindow import WebBrowserWindow
+
         if not WebBrowserWindow.isPrivate():
             from .PasswordWriter import PasswordWriter
+
             loginFile = self.getFileName()
             writer = PasswordWriter()
             if not writer.write(
-                    loginFile, self.__logins, self.__loginForms, self.__never):
+                loginFile, self.__logins, self.__loginForms, self.__never
+            ):
                 EricMessageBox.critical(
                     None,
                     self.tr("Saving login data"),
                     self.tr(
-                        """<p>Login data could not be saved to"""
-                        """ <b>{0}</b></p>"""
-                    ).format(loginFile))
+                        """<p>Login data could not be saved to""" """ <b>{0}</b></p>"""
+                    ).format(loginFile),
+                )
             else:
                 self.passwordsSaved.emit()
-    
+
     def __load(self):
         """
         Private method to load the saved login credentials.
         """
         if self.__loaded:
             return
-        
+
         loginFile = self.getFileName()
         if os.path.exists(loginFile):
             from .PasswordReader import PasswordReader
+
             reader = PasswordReader()
-            self.__logins, self.__loginForms, self.__never = reader.read(
-                loginFile)
+            self.__logins, self.__loginForms, self.__never = reader.read(loginFile)
             if reader.error() != QXmlStreamReader.Error.NoError:
                 EricMessageBox.warning(
                     None,
                     self.tr("Loading login data"),
-                    self.tr("""Error when loading login data on"""
-                            """ line {0}, column {1}:\n{2}""")
-                    .format(reader.lineNumber(),
-                            reader.columnNumber(),
-                            reader.errorString()))
-        
+                    self.tr(
+                        """Error when loading login data on"""
+                        """ line {0}, column {1}:\n{2}"""
+                    ).format(
+                        reader.lineNumber(), reader.columnNumber(), reader.errorString()
+                    ),
+                )
+
         self.__loaded = True
-    
+
     def reload(self):
         """
         Public method to reload the login data.
         """
         if not self.__loaded:
             return
-        
+
         self.__loaded = False
         self.__load()
-    
+
     def close(self):
         """
         Public method to close the passwords manager.
         """
         self.__saveTimer.saveIfNeccessary()
-    
+
     def removePassword(self, site):
         """
         Public method to remove a password entry.
-        
+
         @param site web site name (string)
         """
         if site in self.__logins:
@@ -219,49 +230,50 @@
             if site in self.__loginForms:
                 del self.__loginForms[site]
             self.changed.emit()
-    
+
     def allSiteNames(self):
         """
         Public method to get a list of all site names.
-        
+
         @return sorted list of all site names (list of strings)
         """
         if not self.__loaded:
             self.__load()
-        
+
         return sorted(self.__logins.keys())
-    
+
     def sitesCount(self):
         """
         Public method to get the number of available sites.
-        
+
         @return number of sites (integer)
         """
         if not self.__loaded:
             self.__load()
-        
+
         return len(self.__logins)
-    
+
     def siteInfo(self, site):
         """
         Public method to get a reference to the named site.
-        
+
         @param site web site name (string)
         @return tuple containing the user name (string) and password (string)
         """
         if not self.__loaded:
             self.__load()
-        
+
         if site not in self.__logins:
             return None
-        
+
         return self.__logins[site][0], Utilities.crypto.pwConvert(
-            self.__logins[site][1], encode=False)
-    
+            self.__logins[site][1], encode=False
+        )
+
     def formSubmitted(self, urlStr, userName, password, data, page):
         """
         Public method to record login data.
-        
+
         @param urlStr form submission URL
         @type str
         @param userName name of the user
@@ -276,16 +288,16 @@
         # shall passwords be saved?
         if not Preferences.getUser("SavePasswords"):
             return
-        
+
         if WebBrowser.WebBrowserWindow.WebBrowserWindow.isPrivate():
             return
-        
+
         if not self.__loaded:
             self.__load()
-        
+
         if urlStr in self.__never:
             return
-        
+
         if userName and password:
             url = QUrl(urlStr)
             url = self.__stripUrl(url)
@@ -298,13 +310,15 @@
                         """<b>Would you like to save this password?</b><br/>"""
                         """To review passwords you have saved and remove"""
                         """ them, use the password management dialog of the"""
-                        """ Settings menu."""),
-                    modal=True, parent=page.view())
+                        """ Settings menu."""
+                    ),
+                    modal=True,
+                    parent=page.view(),
+                )
                 neverButton = mb.addButton(
-                    self.tr("Never for this site"),
-                    EricMessageBox.DestructiveRole)
-                noButton = mb.addButton(
-                    self.tr("Not now"), EricMessageBox.RejectRole)
+                    self.tr("Never for this site"), EricMessageBox.DestructiveRole
+                )
+                noButton = mb.addButton(self.tr("Not now"), EricMessageBox.RejectRole)
                 mb.addButton(EricMessageBox.Yes)
                 mb.exec()
                 if mb.clickedButton() == neverButton:
@@ -312,111 +326,114 @@
                     return
                 elif mb.clickedButton() == noButton:
                     return
-        
+
             self.__logins[key] = (
                 userName,
-                Utilities.crypto.pwConvert(password, encode=True)
+                Utilities.crypto.pwConvert(password, encode=True),
             )
             from .LoginForm import LoginForm
+
             form = LoginForm()
             form.url = url
             form.name = userName
             form.postData = Utilities.crypto.pwConvert(
-                bytes(data).decode("utf-8"), encode=True)
+                bytes(data).decode("utf-8"), encode=True
+            )
             self.__loginForms[key] = form
             self.changed.emit()
-    
+
     def __stripUrl(self, url):
         """
         Private method to strip off all unneeded parts of a URL.
-        
+
         @param url URL to be stripped (QUrl)
         @return stripped URL (QUrl)
         """
         cleanUrl = QUrl(url)
         cleanUrl.setQuery("")
         cleanUrl.setUserInfo("")
-        
+
         authority = cleanUrl.authority()
         if authority.startswith("@"):
             authority = authority[1:]
-        cleanUrl = QUrl("{0}://{1}{2}".format(
-            cleanUrl.scheme(), authority, cleanUrl.path()))
+        cleanUrl = QUrl(
+            "{0}://{1}{2}".format(cleanUrl.scheme(), authority, cleanUrl.path())
+        )
         cleanUrl.setFragment("")
         return cleanUrl
-    
+
     def completePage(self, page):
         """
         Public slot to complete login forms with saved data.
-        
+
         @param page reference to the web page (WebBrowserPage)
         """
         if page is None:
             return
-        
+
         if not self.__loaded:
             self.__load()
-        
+
         url = page.url()
         url = self.__stripUrl(url)
         key = self.__createKey(url, "")
-        if (
-            key not in self.__loginForms or
-            key not in self.__logins
-        ):
+        if key not in self.__loginForms or key not in self.__logins:
             return
-        
+
         form = self.__loginForms[key]
         if form.url != url:
             return
-        
-        postData = QByteArray(Utilities.crypto.pwConvert(
-            form.postData, encode=False).encode("utf-8"))
+
+        postData = QByteArray(
+            Utilities.crypto.pwConvert(form.postData, encode=False).encode("utf-8")
+        )
         script = Scripts.completeFormData(postData)
         page.runJavaScript(script, WebBrowserPage.SafeJsWorld)
-    
+
     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 = EricProgressDialog(
             self.tr("Re-encoding saved passwords..."),
-            None, 0, len(self.__logins) + len(self.__loginForms),
+            None,
+            0,
+            len(self.__logins) + len(self.__loginForms),
             self.tr("%v/%m Passwords"),
-            QApplication.activeModalWidget())
+            QApplication.activeModalWidget(),
+        )
         progress.setMinimumDuration(0)
         progress.setWindowTitle(self.tr("Passwords"))
         count = 0
-        
+
         # step 1: do the logins
         for key in self.__logins:
             progress.setValue(count)
             QCoreApplication.processEvents()
             username, pwHash = self.__logins[key]
-            pwHash = Utilities.crypto.pwRecode(
-                pwHash, oldPassword, newPassword)
+            pwHash = Utilities.crypto.pwRecode(pwHash, oldPassword, newPassword)
             self.__logins[key] = (username, pwHash)
             count += 1
-        
+
         # step 2: do the login forms
         for key in self.__loginForms:
             progress.setValue(count)
             QCoreApplication.processEvents()
             postData = self.__loginForms[key].postData
-            postData = Utilities.crypto.pwRecode(
-                postData, oldPassword, newPassword)
+            postData = Utilities.crypto.pwRecode(postData, oldPassword, newPassword)
             self.__loginForms[key].postData = postData
             count += 1
-        
+
         progress.setValue(len(self.__logins) + len(self.__loginForms))
         QCoreApplication.processEvents()
         self.changed.emit()
 
+
 #
 # eflag: noqa = Y113

eric ide

mercurial