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(): def derive_key_v1(passwd, salt=None):
    key_len = crypto_secretbox_keybytes()
    if key_len != 32:
        raise RuntimeError('secretbox key length has changed')
    if salt is None:
        salt = generate_salt_v1()
    if not isinstance(passwd, bytes):
        passwd = passwd.encode('utf-8')
    out = create_string_buffer(key_len)
    sbuf = cast(salt, c_ubyte_p)
    if crypto_pwhash_scryptsalsa208sha256(
            cast(out, c_ubyte_p), key_len, passwd, len(passwd), sbuf,
            crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(), crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive()) != 0:
        raise MemoryError('Out of memory deriving key from password')
    key = out.raw
    lock_python_bytes(key)
    return key, salt def generate_salt_v1():
    return random_bytes(crypto_pwhash_scryptsalsa208sha256_saltbytes()) def nonce_size_v1():
    return crypto_secretbox_noncebytes() def decrypt_v1(encrypted_data, nonce, key):
    if crypto_secretbox_primitive() != b'xsalsa20poly1305':
        raise RuntimeError('libsodium cryptobox primitive has changed')
    ans = create_string_buffer(len(encrypted_data) - crypto_secretbox_macbytes())
    if crypto_secretbox_open_easy(cast(ans, c_ubyte_p), cast(encrypted_data, c_ubyte_p), len(encrypted_data),
                                  cast(nonce, c_ubyte_p), cast(key, c_ubyte_p)) != 0:
        raise MessageForged('Message forged!')
    return ans.raw def encrypt_v1(data, key):
    if crypto_secretbox_primitive() != b'xsalsa20poly1305':
        raise RuntimeError('libsodium cryptobox primitive has changed')
    if not isinstance(data, bytes):
        data = data.encode('utf-8')
    nonce = create_string_buffer(nonce_size_v1())
    randombytes_buf(nonce, nonce_size_v1())
    ciphertext_len = len(data) + crypto_secretbox_macbytes()
    ciphertext = create_string_buffer(ciphertext_len)
    crypto_secretbox_easy(cast(ciphertext, c_ubyte_p), cast(data, c_ubyte_p), len(data), cast(nonce, c_ubyte_p), cast(key, c_ubyte_p))
    return ciphertext.raw, nonce.raw def lock_python_bytes(data):
    if sodium_mlock(cast(data, c_void_p), len(data)) != 0:
        raise RuntimeError('Failed to lock memory') class MessageForged(ValueError):
    pass def atomic_write(dest, data_or_file):
    tdest = dest + '-atomic'
    try:
        with open(tdest, 'wb') as f:
            if hasattr(data_or_file, 'read'):
                shutil.copyfileobj(data_or_file, f)
            else:
                f.write(data_or_file)
        try:
            shutil.copystat(dest, tdest)
        except FileNotFoundError:
            pass
        os.replace(tdest, dest)
    finally:
        try:
            os.remove(tdest)
        except FileNotFoundError:
            pass class DynamicPrefs:

    def __init__(self, name):
        self.path = os.path.join(config_dir, '%s.sqlite' % name)
        self._conn = None
        self._cache = {}
        self.defaults = defaultdict(lambda: nodef)
        self.pending_commits = {}
        self._buffer_commits = False

    @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 prefs (id INTEGER PRIMARY KEY, name TEXT NOT NULL, value TEXT NOT NULL, UNIQUE(name)); PRAGMA user_version=1;')
            c.close()
        return self._conn

    def get(self, name, default=None):
        ans = self[name]
        return default if ans is nodef else ans

    def set(self, name, val):
        self[name] = val

    def __getitem__(self, name):
        try:
            return self._cache[name]
        except KeyError:
            try:
                val = next(self.conn.cursor().execute('SELECT value FROM prefs WHERE name=?', (name,)))[0]
                val = json.loads(val, object_hook=from_json)
            except StopIteration:
                val = self.defaults[name]
            self._cache[name] = val
            return val

    def __setitem__(self, name, val):
        if self._buffer_commits:
            self.pending_commits[name] = val
            return
        self._cache.pop(name, None)
        c = self.conn.cursor()
        if val == self.defaults[name]:
            c.execute('DELETE FROM prefs WHERE name=?', (name,))
        else:
            self._cache[name] = val
            val = json.dumps(val, ensure_ascii=False, indent=2, default=to_json)
            c.execute('INSERT or REPLACE INTO prefs(name, value) VALUES (?, ?)', (name, val))

    def __delitem__(self, name):
        self._cache.pop(name, None)
        c = self.conn.cursor()
        c.execute('DELETE FROM prefs WHERE name=?', (name,))

    @property
    def buffer_commits(self):
        return self._buffer_commits

    @buffer_commits.setter
    def buffer_commits(self, val):
        if val:
            self._buffer_commits = True
        else:
            self._buffer_commits = False
            with self.conn:
                for k, v in self.pending_commits.items():
                    self[k] = v

    def __enter__(self):
        self.buffer_commits = True
        return self

    def __exit__(self, *args):
        self.buffer_commits = False
import json
import os
import hashlib
import struct
import tempfile
            import traceback
                import traceback
    import csv
from binascii import hexlify, unhexlify
from threading import Thread
from urllib.parse import urlparse
from ..constants import config_dir
from ..crypto import derive_key_v1, generate_salt_v1, nonce_size_v1, decrypt_v1, encrypt_v1, lock_python_bytes, MessageForged
from ..utils import atomic_write
from ..settings import DynamicPrefs
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>



password_exclusions = DynamicPrefs('password-exclusions')


class PasswordWrong(ValueError):
    pass


class PasswordStore:  # {{{

    @classmethod
    def has_password(self, dirpath=None):
        dirpath = os.path.realpath(dirpath or os.path.join(config_dir, 'passwd'))
        try:
            with open(os.path.join(dirpath, 'metadata.json'), 'rb') as f:
                metadata = json.loads(f.read().decode('utf-8'))
            return 'sentinel' in metadata
        except FileNotFoundError:
            return False
        except Exception:
            traceback.print_exc()
            return False

    def __init__(self, password, dirpath=None, pw_is_key=False):
        dirpath = os.path.realpath(dirpath or os.path.join(config_dir, 'passwd'))
        self.root = dirpath
        if isinstance(password, str):
            password = password.encode('utf-8')
        lock_python_bytes(password)
        try:
            os.makedirs(self.root)
        except FileExistsError:
            pass
        self.metadata_path = os.path.join(self.root, 'metadata.json')
        try:
            with open(self.metadata_path, 'rb') as f:
                self.metadata = json.loads(f.read().decode('utf-8'))
        except FileNotFoundError:
            self.metadata = {
                'version': 1,
                'salt': hexlify(generate_salt_v1()).decode('ascii')
            }
        if pw_is_key:
            self.password = self.key_error = None
            self.key = password
            lock_python_bytes(self.key)
        else:
            self.password = password
            self.run_derive()

    def run_derive(self):
        self.key = self.key_error = None
        self.derive_worker = Thread(name='DeriveKey', target=self.derive_key)
        self.derive_worker.daemon = True
        self.derive_worker.start()

    def commit_metadata(self):
        raw = json.dumps(self.metadata, indent=2, ensure_ascii=False).encode('utf-8')
        atomic_write(self.metadata_path, raw)

    def derive_key(self):
        pw, self.password = self.password, None
        try:
            self.key = derive_key_v1(pw, unhexlify(self.metadata['salt']))[0]

            lock_python_bytes(self.key)