# Path: vise/constants.py
# DOWNLOADS_URL = 'vise:downloads'
# WELCOME_URL = 'vise:welcome'
# STATUS_BAR_HEIGHT = 24
# FOLLOW_LINK_KEY_MAP = {getattr(Qt.Key, 'Key_' + x.upper()): x for x in string.ascii_lowercase + string.digits}
# VISE_SCHEME = 'vise'
# def _get_cache_dir():
# def _get_config_dir():
# def get_windows_username():
# def local_socket_address():
# 
# Path: vise/message_box.py
# def error_dialog(parent, title, msg, det_msg='', show=True, show_copy_button=True):
#     d = MessageBox(MessageBox.ERROR, _('ERROR:') + ' ' +
#                    title, msg, det_msg, parent=parent, show_copy_button=show_copy_button)
#     return d.exec() if show else d
# 
# Path: vise/settings.py
# def to_json(obj):
# def from_json(obj):
#     def __init__(self, name):
#     def conn(self):
#     def get(self, name, default=None):
#     def set(self, name, val):
#     def __getitem__(self, name):
#     def __setitem__(self, name, val):
#     def __delitem__(self, name):
#     def buffer_commits(self):
#     def buffer_commits(self, val):
#     def __enter__(self):
#     def __exit__(self, *args):
# def safe_makedirs(path):
# def create_script(
#     name, src, world=QWebEngineScript.ScriptWorldId.ApplicationWorld, injection_point=QWebEngineScript.InjectionPoint.DocumentCreation, on_subframes=True
# ):
# def client_script():
# def insert_scripts(profile, *scripts):
# def get_spell_langs():
# def create_profile(parent=None, private=False):
# def profile():
# def do_delete_profile(profile):
# def delete_profile():
# def quickmarks():
# class DynamicPrefs:
# TITLE_TOKEN = None
#     TITLE_TOKEN = hexlify(os.urandom(32)).decode('ascii')
# 
# Path: vise/utils.py
# class Dialog(QDialog):
# 
#     '''
#     An improved version of Qt's QDialog class. This automatically remembers the
#     last used size, automatically connects the signals for QDialogButtonBox,
#     automatically sets the window title and if the dialog has an object named
#     splitter, automatically saves the splitter state.
# 
#     In order to use it, simply subclass an implement setup_ui(). You can also
#     implement sizeHint() to give the dialog a different default size when shown
#     for the first time.
#     '''
# 
#     def __init__(self, title, name, parent=None, prefs=gprefs):
#         QDialog.__init__(self, parent)
#         self.prefs_for_persistence = prefs
#         self.setWindowTitle(title)
#         self.name = name
#         self.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
#         self.bb.accepted.connect(self.accept)
#         self.bb.rejected.connect(self.reject)
# 
#         self.setup_ui()
# 
#         self.resize(self.sizeHint())
#         geom = self.prefs_for_persistence.get(name + '-geometry', None)
#         if geom is not None:
#             self.restoreGeometry(geom)
#         if hasattr(self, 'splitter'):
#             state = self.prefs_for_persistence.get(name + '-splitter-state', None)
#             if state is not None:
#                 self.splitter.restoreState(state)
# 
#     def accept(self):
#         self.prefs_for_persistence.set(self.name + '-geometry', bytearray(self.saveGeometry()))
#         if hasattr(self, 'splitter'):
#             self.prefs_for_persistence.set(self.name + '-splitter-state', bytearray(self.splitter.saveState()))
#         QDialog.accept(self)
# 
#     def reject(self):
#         self.prefs_for_persistence.set(self.name + '-geometry', bytearray(self.saveGeometry()))
#         if hasattr(self, 'splitter'):
#             self.prefs_for_persistence.set(self.name + '-splitter-state', bytearray(self.splitter.saveState()))
#         QDialog.reject(self)
# 
#     def setup_ui(self):
#         raise NotImplementedError('You must implement this method in Dialog subclasses')
# 
# def ascii_lowercase(val):
#     return re.sub('[%s]' % string.ascii_uppercase, lambda m: m.group().lower(), val)


import os
import apsw
from collections import defaultdict
from gettext import gettext as _
from PyQt6.QtWidgets import QCheckBox, QGridLayout, QLabel, QStyle, QDialogButtonBox, QDialog
from PyQt6.QtWebEngineCore import QWebEngineCertificateError
from .constants import config_dir
from .message_box import error_dialog
from .settings import gprefs
from .utils import Dialog, ascii_lowercase
        self.path = os.path.join(config_dir, 'cert-exceptions.sqlite')
        self.temporary = defaultdict(set)

    @property
    def conn(self):
        if self._conn is None:
            self._conn = apsw.Connection(self.path)
            c = self._conn.cursor()
            uv = next(c.execute('PRAGMA user_version'))[0]
            if uv == 0:
                c.execute(
                    'CREATE TABLE exceptions (id INTEGER PRIMARY KEY, domain TEXT NOT NULL, type TEXT NOT NULL, UNIQUE(domain, type)); PRAGMA user_version=1;')
            c.close()
        return self._conn

    def add_exception(self, domain, etype, permanent=True):
        domain = ascii_lowercase(domain)
        etype = code_map[etype]
        if permanent:
            c = self.conn.cursor()
            c.execute('INSERT OR REPLACE INTO exceptions(domain, type) VALUES (?, ?)', (domain, etype))
        else:
            self.temporary[domain].add(etype)

    def has_exception(self, domain, etype):
        domain = ascii_lowercase(domain)
        etype = code_map[etype]
        if etype in self.temporary[domain]:
            return True
        try:

# Path: vise/constants.py
# DOWNLOADS_URL = 'vise:downloads'
# WELCOME_URL = 'vise:welcome'
# STATUS_BAR_HEIGHT = 24
# FOLLOW_LINK_KEY_MAP = {getattr(Qt.Key, 'Key_' + x.upper()): x for x in string.ascii_lowercase + string.digits}
# VISE_SCHEME = 'vise'
# def _get_cache_dir():
# def _get_config_dir():
# def get_windows_username():
# def local_socket_address():
# 
# Path: vise/message_box.py
# def error_dialog(parent, title, msg, det_msg='', show=True, show_copy_button=True):
#     d = MessageBox(MessageBox.ERROR, _('ERROR:') + ' ' +
#                    title, msg, det_msg, parent=parent, show_copy_button=show_copy_button)
#     return d.exec() if show else d
# 
# Path: vise/settings.py
# def to_json(obj):
# def from_json(obj):
#     def __init__(self, name):
#     def conn(self):
#     def get(self, name, default=None):
#     def set(self, name, val):
#     def __getitem__(self, name):
#     def __setitem__(self, name, val):
#     def __delitem__(self, name):
#     def buffer_commits(self):
#     def buffer_commits(self, val):
#     def __enter__(self):
#     def __exit__(self, *args):
# def safe_makedirs(path):
# def create_script(
#     name, src, world=QWebEngineScript.ScriptWorldId.ApplicationWorld, injection_point=QWebEngineScript.InjectionPoint.DocumentCreation, on_subframes=True
# ):
# def client_script():
# def insert_scripts(profile, *scripts):
# def get_spell_langs():
# def create_profile(parent=None, private=False):
# def profile():
# def do_delete_profile(profile):
# def delete_profile():
# def quickmarks():
# class DynamicPrefs:
# TITLE_TOKEN = None
#     TITLE_TOKEN = hexlify(os.urandom(32)).decode('ascii')
# 
# Path: vise/utils.py
# class Dialog(QDialog):
# 
#     '''
#     An improved version of Qt's QDialog class. This automatically remembers the
#     last used size, automatically connects the signals for QDialogButtonBox,
#     automatically sets the window title and if the dialog has an object named
#     splitter, automatically saves the splitter state.
# 
#     In order to use it, simply subclass an implement setup_ui(). You can also
#     implement sizeHint() to give the dialog a different default size when shown
#     for the first time.
#     '''
# 
#     def __init__(self, title, name, parent=None, prefs=gprefs):
#         QDialog.__init__(self, parent)
#         self.prefs_for_persistence = prefs
#         self.setWindowTitle(title)
#         self.name = name
#         self.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
#         self.bb.accepted.connect(self.accept)
#         self.bb.rejected.connect(self.reject)
# 
#         self.setup_ui()
# 
#         self.resize(self.sizeHint())
#         geom = self.prefs_for_persistence.get(name + '-geometry', None)
#         if geom is not None:
#             self.restoreGeometry(geom)
#         if hasattr(self, 'splitter'):
#             state = self.prefs_for_persistence.get(name + '-splitter-state', None)
#             if state is not None:
#                 self.splitter.restoreState(state)
# 
#     def accept(self):
#         self.prefs_for_persistence.set(self.name + '-geometry', bytearray(self.saveGeometry()))
#         if hasattr(self, 'splitter'):
#             self.prefs_for_persistence.set(self.name + '-splitter-state', bytearray(self.splitter.saveState()))
#         QDialog.accept(self)
# 
#     def reject(self):
#         self.prefs_for_persistence.set(self.name + '-geometry', bytearray(self.saveGeometry()))
#         if hasattr(self, 'splitter'):
#             self.prefs_for_persistence.set(self.name + '-splitter-state', bytearray(self.splitter.saveState()))
#         QDialog.reject(self)
# 
#     def setup_ui(self):
#         raise NotImplementedError('You must implement this method in Dialog subclasses')
# 
# def ascii_lowercase(val):
#     return re.sub('[%s]' % string.ascii_uppercase, lambda m: m.group().lower(), val)


# Path: vise/certs.py
import os
import apsw
from collections import defaultdict
from gettext import gettext as _
from PyQt6.QtWidgets import QCheckBox, QGridLayout, QLabel, QStyle, QDialogButtonBox, QDialog
from PyQt6.QtWebEngineCore import QWebEngineCertificateError
from .constants import config_dir
from .message_box import error_dialog
from .settings import gprefs
from .utils import Dialog, ascii_lowercase

        self.path = os.path.join(config_dir, 'cert-exceptions.sqlite')
        self.temporary = defaultdict(set)

    @property
    def conn(self):
        if self._conn is None:
            self._conn = apsw.Connection(self.path)
            c = self._conn.cursor()
            uv = next(c.execute('PRAGMA user_version'))[0]
            if uv == 0:
                c.execute(
                    'CREATE TABLE exceptions (id INTEGER PRIMARY KEY, domain TEXT NOT NULL, type TEXT NOT NULL, UNIQUE(domain, type)); PRAGMA user_version=1;')
            c.close()
        return self._conn

    def add_exception(self, domain, etype, permanent=True):
        domain = ascii_lowercase(domain)
        etype = code_map[etype]
        if permanent:
            c = self.conn.cursor()
            c.execute('INSERT OR REPLACE INTO exceptions(domain, type) VALUES (?, ?)', (domain, etype))
        else:
            self.temporary[domain].add(etype)

    def has_exception(self, domain, etype):
        domain = ascii_lowercase(domain)
        etype = code_map[etype]
        if etype in self.temporary[domain]:
            return True
        try:

            next(self.conn.cursor().execute('SELECT domain FROM exceptions WHERE domain=? AND type=?', (domain, etype)))