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 try: wallet = self.daemon.load_wallet(path, None) except BaseException as e: traceback.print_exc(file=sys.stdout) QMessageBox.warning(None, _('Error'), _('Cannot load wallet') + ' (1):\n' + str(e)) # if app is starting, still let wizard to appear if not app_is_starting: return if not wallet: wallet = self._start_wizard_to_select_or_create_wallet(path) 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: traceback.print_exc(file=sys.stdout) QMessageBox.warning(None, _('Error'), _('Cannot create window for wallet') + ':\n' + str(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
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: storage = WalletStorage(path, manual_upgrades=True) wizard = InstallWizard(self.config, self.app, self.plugins, storage) try: wallet = wizard.run_and_get_wallet(self.daemon.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
def select_storage(self, path, get_wallet_from_daemon) -> Tuple[str, Optional[WalletStorage]]: vbox = QVBoxLayout() hbox = QHBoxLayout() hbox.addWidget(QLabel(_('Wallet') + ':')) self.name_e = QLineEdit() hbox.addWidget(self.name_e) button = QPushButton(_('Choose...')) hbox.addWidget(button) vbox.addLayout(hbox) self.msg_label = WWLabel('') vbox.addWidget(self.msg_label) hbox2 = QHBoxLayout() self.pw_e = QLineEdit('', self) self.pw_e.setFixedWidth(17 * char_width_in_lineedit()) self.pw_e.setEchoMode(2) self.pw_label = QLabel(_('Password') + ':') hbox2.addWidget(self.pw_label) hbox2.addWidget(self.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=_('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: self.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, manual_upgrades=True) 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') self.msg_label.setText(msg) widget_create_new.setVisible(bool(temp_storage and temp_storage.file_exists())) if user_needs_to_enter_password: self.pw_label.show() self.pw_e.show() self.pw_e.setFocus() else: self.pw_label.hide() self.pw_e.hide() button.clicked.connect(on_choose) button_create_new.clicked.connect( partial( self.name_e.setText, get_new_wallet_name(wallet_folder))) self.name_e.textChanged.connect(on_filename) self.name_e.setText(os.path.basename(path)) 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 = self.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 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') return temp_storage.path, (temp_storage if temp_storage.file_exists() else None)
def start_new_window( self, path, uri: Optional[str], *, app_is_starting: bool = False, force_wizard: bool = False, ) -> Optional[ElectrumWindow]: '''Raises the window for the wallet if it is open. Otherwise opens the wallet and creates a new window for it''' wallet = None # Try to open with daemon first. If this succeeds, there won't be a wizard at all # (the wallet main window will appear directly). if not force_wizard: try: wallet = self.daemon.load_wallet(path, None) except Exception 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 appear if not app_is_starting: return # Open a wizard window. This lets the user e.g. enter a password, or select # a different wallet. try: if not wallet: wallet = self._start_wizard_to_select_or_create_wallet(path) if not wallet: return # create or raise window for window in self.windows: if window.wallet.storage.path == wallet.storage.path: break else: window = self._create_window_for_wallet(wallet) except Exception as e: self.logger.exception('') custom_message_box(icon=QMessageBox.Warning, parent=None, title=_('Error'), text=_('Cannot load wallet') + '(2) :\n' + repr(e)) if app_is_starting: # If we raise in this context, there are no more fallbacks, we will shut down. # Worst case scenario, we might have gotten here without user interaction, # in which case, if we raise now without user interaction, the same sequence of # events is likely to repeat when the user restarts the process. # So we play it safe: clear path, clear uri, force a wizard to appear. try: wallet_dir = os.path.dirname(path) filename = get_new_wallet_name(wallet_dir) except OSError: path = self.config.get_fallback_wallet_path() else: path = os.path.join(wallet_dir, filename) self.start_new_window(path, uri=None, force_wizard=True) return if uri: window.handle_payment_identifier(uri) window.bring_to_top() window.setWindowState(window.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive) window.activateWindow() return window