eric7/WebBrowser/Network/SslErrorExceptionsDialog.py

branch
eric7
changeset 8312
800c432b34c8
parent 8243
cc717c2ae956
child 8318
962bce857696
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/WebBrowser/Network/SslErrorExceptionsDialog.py	Sat May 15 18:45:04 2021 +0200
@@ -0,0 +1,182 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2016 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to edit the SSL error exceptions.
+"""
+
+from PyQt5.QtCore import pyqtSlot, Qt, QPoint
+from PyQt5.QtWidgets import QDialog, QTreeWidgetItem, QMenu
+from PyQt5.QtWebEngineWidgets import QWebEngineCertificateError
+
+from .Ui_SslErrorExceptionsDialog import Ui_SslErrorExceptionsDialog
+
+
+class SslErrorExceptionsDialog(QDialog, Ui_SslErrorExceptionsDialog):
+    """
+    Class implementing a dialog to edit the SSL error exceptions.
+    """
+    def __init__(self, errorsDict, parent=None):
+        """
+        Constructor
+        
+        @param errorsDict error exceptions
+        @type dict of list of int
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super().__init__(parent)
+        self.setupUi(self)
+        
+        self.__errorDescriptions = {
+            QWebEngineCertificateError.Error.SslPinnedKeyNotInCertificateChain:
+                self.tr("The certificate did not match the built-in public"
+                        " keys pinned for the host name."),
+            QWebEngineCertificateError.Error.CertificateCommonNameInvalid:
+                self.tr("The certificate's common name did not match the"
+                        " host name."),
+            QWebEngineCertificateError.Error.CertificateDateInvalid:
+                self.tr("The certificate is not valid at the current date"
+                        " and time."),
+            QWebEngineCertificateError.Error.CertificateAuthorityInvalid:
+                self.tr("The certificate is not signed by a trusted"
+                        " authority."),
+            QWebEngineCertificateError.Error.CertificateContainsErrors:
+                self.tr("The certificate contains errors."),
+            QWebEngineCertificateError.Error.CertificateNoRevocationMechanism:
+                self.tr("The certificate has no mechanism for determining if"
+                        " it has been revoked."),
+            QWebEngineCertificateError.Error
+            .CertificateUnableToCheckRevocation:
+                self.tr("Revocation information for the certificate is"
+                        " not available."),
+            QWebEngineCertificateError.Error.CertificateRevoked:
+                self.tr("The certificate has been revoked."),
+            QWebEngineCertificateError.Error.CertificateInvalid:
+                self.tr("The certificate is invalid."),
+            QWebEngineCertificateError.Error.CertificateWeakSignatureAlgorithm:
+                self.tr("The certificate is signed using a weak signature"
+                        " algorithm."),
+            QWebEngineCertificateError.Error.CertificateNonUniqueName:
+                self.tr("The host name specified in the certificate is"
+                        " not unique."),
+            QWebEngineCertificateError.Error.CertificateWeakKey:
+                self.tr("The certificate contains a weak key."),
+            QWebEngineCertificateError.Error
+            .CertificateNameConstraintViolation:
+                self.tr("The certificate claimed DNS names that are in"
+                        " violation of name constraints."),
+            QWebEngineCertificateError.Error.CertificateValidityTooLong:
+                self.tr("The certificate has a validity period that is"
+                        " too long."),
+            QWebEngineCertificateError.Error.CertificateTransparencyRequired:
+                self.tr("Certificate Transparency was required for this"
+                        " connection, but the server did not provide"
+                        " information that complied with the policy."),
+        }
+        
+        for host, errors in errorsDict.items():
+            itm = QTreeWidgetItem(self.errorsTree, [host])
+            self.errorsTree.setFirstItemColumnSpanned(itm, True)
+            for error in errors:
+                try:
+                    errorDesc = self.__errorDescriptions[error]
+                except KeyError:
+                    errorDesc = self.tr("No error description available.")
+                QTreeWidgetItem(itm, [str(error), errorDesc])
+        
+        self.errorsTree.expandAll()
+        for i in range(self.errorsTree.columnCount()):
+            self.errorsTree.resizeColumnToContents(i)
+        self.errorsTree.sortItems(0, Qt.SortOrder.AscendingOrder)
+        
+        self.__setRemoveButtons()
+    
+    def __setRemoveButtons(self):
+        """
+        Private method to set the state of the 'remove' buttons.
+        """
+        if self.errorsTree.topLevelItemCount() == 0:
+            self.removeButton.setEnabled(False)
+            self.removeAllButton.setEnabled(False)
+        else:
+            self.removeAllButton.setEnabled(True)
+            self.removeButton.setEnabled(
+                len(self.errorsTree.selectedItems()) > 0)
+    
+    @pyqtSlot(QPoint)
+    def on_errorsTree_customContextMenuRequested(self, pos):
+        """
+        Private slot to show the context menu.
+        
+        @param pos cursor position
+        @type QPoint
+        """
+        menu = QMenu()
+        menu.addAction(
+            self.tr("Remove Selected"),
+            self.on_removeButton_clicked).setEnabled(
+            self.errorsTree.topLevelItemCount() > 0 and
+            len(self.errorsTree.selectedItems()) > 0)
+        menu.addAction(
+            self.tr("Remove All"),
+            self.on_removeAllButton_clicked).setEnabled(
+            self.errorsTree.topLevelItemCount() > 0)
+        
+        menu.exec(self.errorsTree.mapToGlobal(pos))
+    
+    @pyqtSlot()
+    def on_errorsTree_itemSelectionChanged(self):
+        """
+        Private slot handling the selection of entries.
+        """
+        self.__setRemoveButtons()
+    
+    @pyqtSlot()
+    def on_removeButton_clicked(self):
+        """
+        Private slot to remove the selected items.
+        """
+        for itm in self.errorsTree.selectedItems():
+            pitm = itm.parent()
+            if pitm:
+                pitm.removeChild(itm)
+            else:
+                index = self.errorsTree.indexOfTopLevelItem(itm)
+                self.errorsTree.takeTopLevelItem(index)
+            del itm
+        
+        # remove all hosts without an exception
+        for index in range(self.errorsTree.topLevelItemCount() - 1, -1, -1):
+            itm = self.errorsTree.topLevelItem(index)
+            if itm.childCount() == 0:
+                self.errorsTree.takeTopLevelItem(index)
+                del itm
+    
+    @pyqtSlot()
+    def on_removeAllButton_clicked(self):
+        """
+        Private slot to remove all entries.
+        """
+        self.errorsTree.clear()
+    
+    def getSslErrorExceptions(self):
+        """
+        Public method to retrieve the list of SSL error exceptions.
+        
+        @return error exceptions
+        @rtype dict of list of int
+        """
+        errors = {}
+        
+        for index in range(self.errorsTree.topLevelItemCount()):
+            itm = self.errorsTree.topLevelItem(index)
+            host = itm.text(0)
+            errors[host] = []
+            for cindex in range(itm.childCount()):
+                citm = itm.child(cindex)
+                errors[host].append(int(citm.text(0)))
+        
+        return errors

eric ide

mercurial