diff --git a/electrum/gui/qml/components/WalletDetails.qml b/electrum/gui/qml/components/WalletDetails.qml index 2676c5862..9db036f9a 100644 --- a/electrum/gui/qml/components/WalletDetails.qml +++ b/electrum/gui/qml/components/WalletDetails.qml @@ -172,8 +172,7 @@ Pane { visible: walletNameContent.editmode icon.source: '../../icons/confirmed.png' icon.color: enabled ? 'transparent' : constants.mutedForeground - enabled: walletNameEdit.text !== Daemon.currentWallet.name - && Daemon.isValidWalletName(walletNameEdit.text) + enabled: Daemon.isValidWalletName(walletNameEdit.text) onClicked: { walletNameContent.editmode = false Daemon.renameWallet(walletNameEdit.text) diff --git a/electrum/gui/qml/components/wizard/WCWalletName.qml b/electrum/gui/qml/components/wizard/WCWalletName.qml index 7dc243db5..1020b03cd 100644 --- a/electrum/gui/qml/components/wizard/WCWalletName.qml +++ b/electrum/gui/qml/components/wizard/WCWalletName.qml @@ -5,7 +5,7 @@ import QtQuick.Controls import org.electrum 1.0 WizardComponent { - valid: wiz.isValidNewWalletName(wallet_name.text) + valid: Daemon.isValidWalletName(wallet_name.text) function apply() { wizard_data['wallet_name'] = wallet_name.text diff --git a/electrum/gui/qml/qedaemon.py b/electrum/gui/qml/qedaemon.py index d9eadb324..b8509bdd9 100644 --- a/electrum/gui/qml/qedaemon.py +++ b/electrum/gui/qml/qedaemon.py @@ -13,7 +13,7 @@ from electrum.plugin import run_hook from electrum.lnchannel import ChannelState from electrum.bitcoin import is_address from electrum.bitcoin import verify_usermessage_with_address -from electrum.storage import StorageReadWriteError +from electrum.storage import StorageReadWriteError, WalletStorage from .auth import AuthMixin, auth_protect from .qefx import QEFX @@ -311,15 +311,33 @@ class QEDaemon(AuthMixin, QObject): self.availableWallets.remove_wallet(path) + def wallet_path_from_wallet_name(self, wallet_name: str) -> str: + return os.path.join(self.daemon.config.get_datadir_wallet_path(), wallet_name) + @pyqtSlot(str, result=bool) def isValidWalletName(self, wallet_name: str) -> bool: if not wallet_name: return False if self.availableWallets.wallet_name_exists(wallet_name): return False - # ensure wallet_name is not interpreted as path + # note: we should probably restrict wallet names to be alphanumeric (plus underscore, etc)... + # try to prevent sketchy path traversals: + for forbidden_char in ("/", "\\", ): + if forbidden_char in wallet_name: + return False if os.path.basename(wallet_name) != wallet_name: # '/foo/bar/' returns 'bar' return False + wallet_path = self.wallet_path_from_wallet_name(wallet_name) + # validate that the path looks sane to the filesystem: + try: + temp_storage = WalletStorage(wallet_path) + except (StorageReadWriteError, WalletFileException): + return False + except Exception: + self._logger.exception("") + return False + if temp_storage.file_exists(): + return False return True @pyqtSlot(str) diff --git a/electrum/gui/qml/qewizard.py b/electrum/gui/qml/qewizard.py index ca1961f8c..3bd3f33ec 100644 --- a/electrum/gui/qml/qewizard.py +++ b/electrum/gui/qml/qewizard.py @@ -7,8 +7,7 @@ from electrum.base_crash_reporter import send_exception_to_crash_reporter from electrum.logging import get_logger from electrum import mnemonic from electrum.wizard import NewWalletWizard, ServerConnectWizard, TermsOfUseWizard -from electrum.storage import WalletStorage, StorageReadWriteError -from electrum.util import WalletFileException, UserFacingException +from electrum.util import UserFacingException from electrum.gui import messages if TYPE_CHECKING: @@ -125,35 +124,6 @@ class QENewWalletWizard(NewWalletWizard, QEAbstractWizard): 'can_passphrase': can_passphrase } - def _wallet_path_from_wallet_name(self, wallet_name: str) -> str: - return os.path.join(self._qedaemon.daemon.config.get_datadir_wallet_path(), wallet_name) - - @pyqtSlot(str, result=bool) - def isValidNewWalletName(self, wallet_name: str) -> bool: - if not wallet_name: - return False - if self._qedaemon.availableWallets.wallet_name_exists(wallet_name): - return False - wallet_path = self._wallet_path_from_wallet_name(wallet_name) - # note: we should probably restrict wallet names to be alphanumeric (plus underscore, etc)... - # try to prevent sketchy path traversals: - for forbidden_char in ("/", "\\", ): - if forbidden_char in wallet_name: - return False - if os.path.basename(wallet_name) != wallet_name: - return False - # validate that the path looks sane to the filesystem: - try: - temp_storage = WalletStorage(wallet_path) - except (StorageReadWriteError, WalletFileException) as e: - return False - except Exception as e: - self._logger.exception("") - return False - if temp_storage.file_exists(): - return False - return True - @pyqtSlot('QJSValue', bool, str) def createStorage(self, js_data, single_password_enabled, single_password): self._logger.info('Creating wallet from wizard data') @@ -163,7 +133,7 @@ class QENewWalletWizard(NewWalletWizard, QEAbstractWizard): data['encrypt'] = True data['password'] = single_password - path = self._wallet_path_from_wallet_name(data['wallet_name']) + path = self._qedaemon.wallet_path_from_wallet_name(data['wallet_name']) try: self.create_storage(path, data)