Ejemplo n.º 1
0
    def start_new_window(self, path, uri, *, app_is_starting=False):
        '''Raises the window for the wallet if it is open.  Otherwise
        opens the wallet and creates a new window for it'''
        wallet = None
        if self.config.get('tor_auto_on', True):
            network = self.daemon.network
            if network:
                proxy_modifiable = self.config.is_modifiable('proxy')
                if not proxy_modifiable or not network.detect_tor_proxy():
                    warn_d = TorWarnDialog(self, path)
                    warn_d.exec_()
                    if warn_d.result() < 0:
                        return
        try:
            wallet = self.daemon.load_wallet(path, None)
        except BaseException as e:
            self.logger.exception('')
            custom_message_box(icon=QMessageBox.Warning,
                               parent=None,
                               title=_('Error'),
                               text=_('Cannot load wallet') + ' (1):\n' + repr(e))
            # if app is starting, still let wizard to appear
            if not app_is_starting:
                return
        if not wallet:
            try:
                wallet = self._start_wizard_to_select_or_create_wallet(path)
            except (WalletFileException, BitcoinException) as e:
                self.logger.exception('')
                custom_message_box(icon=QMessageBox.Warning,
                                   parent=None,
                                   title=_('Error'),
                                   text=_('Cannot load wallet') + ' (2):\n' + repr(e))
        if not wallet:
            return
        # create or raise window
        try:
            for window in self.windows:
                if window.wallet.storage.path == wallet.storage.path:
                    break
            else:
                window = self._create_window_for_wallet(wallet)
        except BaseException as e:
            self.logger.exception('')
            custom_message_box(icon=QMessageBox.Warning,
                               parent=None,
                               title=_('Error'),
                               text=_('Cannot create window for wallet') + ':\n' + repr(e))
            if app_is_starting:
                wallet_dir = os.path.dirname(path)
                path = os.path.join(wallet_dir, get_new_wallet_name(wallet_dir))
                self.start_new_window(path, uri)
            return
        if uri:
            window.pay_to_URI(uri)
        window.bring_to_top()
        window.setWindowState(window.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive)

        window.activateWindow()
        return window
Ejemplo n.º 2
0
    def select_storage(self, path, get_wallet_from_daemon) -> Tuple[str, Optional[WalletStorage]]:

        vbox = QVBoxLayout()
        hbox = QHBoxLayout()
        hbox.addWidget(QLabel(_('Wallet') + ':'))
        name_e = QLineEdit()
        hbox.addWidget(name_e)
        button = QPushButton(_('Choose...'))
        hbox.addWidget(button)
        vbox.addLayout(hbox)

        msg_label = WWLabel('')
        vbox.addWidget(msg_label)
        hbox2 = QHBoxLayout()
        pw_e = PasswordLineEdit('', self)
        pw_e.setFixedWidth(17 * char_width_in_lineedit())
        pw_label = QLabel(_('Password') + ':')
        hbox2.addWidget(pw_label)
        hbox2.addWidget(pw_e)
        hbox2.addStretch()
        vbox.addLayout(hbox2)

        vbox.addSpacing(50)
        vbox_create_new = QVBoxLayout()
        vbox_create_new.addWidget(QLabel(_('Alternatively') + ':'), alignment=Qt.AlignLeft)
        button_create_new = QPushButton(_('Create New Wallet'))
        button_create_new.setMinimumWidth(120)
        vbox_create_new.addWidget(button_create_new, alignment=Qt.AlignLeft)
        widget_create_new = QWidget()
        widget_create_new.setLayout(vbox_create_new)
        vbox_create_new.setContentsMargins(0, 0, 0, 0)
        vbox.addWidget(widget_create_new)

        self.set_layout(vbox, title=_('Dash Electrum wallet'))

        temp_storage = None  # type: Optional[WalletStorage]
        wallet_folder = os.path.dirname(path)

        def on_choose():
            path, __ = QFileDialog.getOpenFileName(self, "Select your wallet file", wallet_folder)
            if path:
                name_e.setText(path)

        def on_filename(filename):
            # FIXME? "filename" might contain ".." (etc) and hence sketchy path traversals are possible
            nonlocal temp_storage
            temp_storage = None
            msg = None
            path = os.path.join(wallet_folder, filename)
            wallet_from_memory = get_wallet_from_daemon(path)
            try:
                if wallet_from_memory:
                    temp_storage = wallet_from_memory.storage  # type: Optional[WalletStorage]
                else:
                    temp_storage = WalletStorage(path)
            except (StorageReadWriteError, WalletFileException) as e:
                msg = _('Cannot read file') + f'\n{repr(e)}'
            except Exception as e:
                self.logger.exception('')
                msg = _('Cannot read file') + f'\n{repr(e)}'
            self.next_button.setEnabled(temp_storage is not None)
            user_needs_to_enter_password = False
            if temp_storage:
                if not temp_storage.file_exists():
                    msg =_("This file does not exist.") + '\n' \
                          + _("Press 'Next' to create this wallet, or choose another file.")
                elif not wallet_from_memory:
                    if temp_storage.is_encrypted_with_user_pw():
                        msg = _("This file is encrypted with a password.") + '\n' \
                              + _('Enter your password or choose another file.')
                        user_needs_to_enter_password = True
                    elif temp_storage.is_encrypted_with_hw_device():
                        msg = _("This file is encrypted using a hardware device.") + '\n' \
                              + _("Press 'Next' to choose device to decrypt.")
                    else:
                        msg = _("Press 'Next' to open this wallet.")
                else:
                    msg = _("This file is already open in memory.") + "\n" \
                        + _("Press 'Next' to create/focus window.")
            if msg is None:
                msg = _('Cannot read file')
            msg_label.setText(msg)
            widget_create_new.setVisible(bool(temp_storage and temp_storage.file_exists()))
            if user_needs_to_enter_password:
                pw_label.show()
                pw_e.show()
                pw_e.setFocus()
            else:
                pw_label.hide()
                pw_e.hide()

        button.clicked.connect(on_choose)
        button_create_new.clicked.connect(
            partial(
                name_e.setText,
                get_new_wallet_name(wallet_folder)))
        name_e.textChanged.connect(on_filename)
        name_e.setText(os.path.basename(path))

        def run_user_interaction_loop():
            while True:
                if self.loop.exec_() != 2:  # 2 = next
                    raise UserCancelled()
                assert temp_storage
                if temp_storage.file_exists() and not temp_storage.is_encrypted():
                    break
                if not temp_storage.file_exists():
                    break
                wallet_from_memory = get_wallet_from_daemon(temp_storage.path)
                if wallet_from_memory:
                    raise WalletAlreadyOpenInMemory(wallet_from_memory)
                if temp_storage.file_exists() and temp_storage.is_encrypted():
                    if temp_storage.is_encrypted_with_user_pw():
                        password = pw_e.text()
                        try:
                            temp_storage.decrypt(password)
                            break
                        except InvalidPassword as e:
                            self.show_message(title=_('Error'), msg=str(e))
                            continue
                        except BaseException as e:
                            self.logger.exception('')
                            self.show_message(title=_('Error'), msg=repr(e))
                            raise UserCancelled()
                    elif temp_storage.is_encrypted_with_hw_device():
                        try:
                            self.run('choose_hw_device', HWD_SETUP_DECRYPT_WALLET, storage=temp_storage)
                        except InvalidPassword as e:
                            self.show_message(title=_('Error'),
                                              msg=_('Failed to decrypt using this hardware device.') + '\n' +
                                                  _('If you use a passphrase, make sure it is correct.'))
                            self.reset_stack()
                            return self.select_storage(path, get_wallet_from_daemon)
                        except (UserCancelled, GoBack):
                            raise
                        except BaseException as e:
                            self.logger.exception('')
                            self.show_message(title=_('Error'), msg=repr(e))
                            raise UserCancelled()
                        if temp_storage.is_past_initial_decryption():
                            break
                        else:
                            raise UserCancelled()
                    else:
                        raise Exception('Unexpected encryption version')

        try:
            run_user_interaction_loop()
        finally:
            try:
                pw_e.clear()
            except RuntimeError:  # wrapped C/C++ object has been deleted.
                pass              # happens when decrypting with hw device

        return temp_storage.path, (temp_storage if temp_storage.file_exists() else None)
Ejemplo n.º 3
0
    def start_new_window(self, path, uri, app_is_starting=False):
        '''Raises the window for the wallet if it is open.  Otherwise
        opens the wallet and creates a new window for it'''
        try:
            wallet = self.daemon.load_wallet(path, None)
        except BaseException as e:
            traceback.print_exc(file=sys.stdout)
            d = QMessageBox(QMessageBox.Warning, _('Error'),
                            _('Cannot load wallet') + ' (1):\n' + str(e))
            d.exec_()
            if app_is_starting:
                # do not return so that the wizard can appear
                wallet = None
            else:
                return
        if not wallet:
            wizard = InstallWizard(self.config, self.app, self.plugins, None)
            try:
                if wizard.select_storage(path, self.daemon.get_wallet):
                    wallet = wizard.run_and_get_wallet()
            except UserCancelled:
                pass
            except GoBack as e:
                self.print_error(
                    '[start_new_window] Exception caught (GoBack)', e)
            except (WalletFileException, BitcoinException) as e:
                traceback.print_exc(file=sys.stderr)
                d = QMessageBox(QMessageBox.Warning, _('Error'),
                                _('Cannot load wallet') + ' (2):\n' + str(e))
                d.exec_()
                return
            finally:
                wizard.terminate()
            if not wallet:
                return

            if not self.daemon.get_wallet(wallet.storage.path):
                # wallet was not in memory
                wallet.start_network(self.daemon.network)
                self.daemon.add_wallet(wallet)
        try:
            for w in self.windows:
                if w.wallet.storage.path == wallet.storage.path:
                    break
            else:
                w = self.create_window_for_wallet(wallet)
        except BaseException as e:
            traceback.print_exc(file=sys.stdout)
            d = QMessageBox(
                QMessageBox.Warning, _('Error'),
                _('Cannot create window for wallet') + ':\n' + str(e))
            d.exec_()
            if app_is_starting:
                wallet_dir = os.path.dirname(path)
                path = os.path.join(wallet_dir,
                                    get_new_wallet_name(wallet_dir))
                self.start_new_window(path, uri)
            return
        if uri:
            w.pay_to_URI(uri)
        w.bring_to_top()
        w.setWindowState(w.windowState() & ~QtCore.Qt.WindowMinimized
                         | QtCore.Qt.WindowActive)

        # this will activate the window
        w.activateWindow()
        return w