Merge pull request #10604 from f321x/dedup_valid_wallet_name

qml: deduplicate wallet name validation
This commit is contained in:
ghost43
2026-04-23 14:30:13 +00:00
committed by GitHub
4 changed files with 24 additions and 37 deletions
@@ -172,8 +172,7 @@ Pane {
visible: walletNameContent.editmode visible: walletNameContent.editmode
icon.source: '../../icons/confirmed.png' icon.source: '../../icons/confirmed.png'
icon.color: enabled ? 'transparent' : constants.mutedForeground icon.color: enabled ? 'transparent' : constants.mutedForeground
enabled: walletNameEdit.text !== Daemon.currentWallet.name enabled: Daemon.isValidWalletName(walletNameEdit.text)
&& Daemon.isValidWalletName(walletNameEdit.text)
onClicked: { onClicked: {
walletNameContent.editmode = false walletNameContent.editmode = false
Daemon.renameWallet(walletNameEdit.text) Daemon.renameWallet(walletNameEdit.text)
@@ -5,7 +5,7 @@ import QtQuick.Controls
import org.electrum 1.0 import org.electrum 1.0
WizardComponent { WizardComponent {
valid: wiz.isValidNewWalletName(wallet_name.text) valid: Daemon.isValidWalletName(wallet_name.text)
function apply() { function apply() {
wizard_data['wallet_name'] = wallet_name.text wizard_data['wallet_name'] = wallet_name.text
+20 -2
View File
@@ -13,7 +13,7 @@ from electrum.plugin import run_hook
from electrum.lnchannel import ChannelState from electrum.lnchannel import ChannelState
from electrum.bitcoin import is_address from electrum.bitcoin import is_address
from electrum.bitcoin import verify_usermessage_with_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 .auth import AuthMixin, auth_protect
from .qefx import QEFX from .qefx import QEFX
@@ -311,15 +311,33 @@ class QEDaemon(AuthMixin, QObject):
self.availableWallets.remove_wallet(path) 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) @pyqtSlot(str, result=bool)
def isValidWalletName(self, wallet_name: str) -> bool: def isValidWalletName(self, wallet_name: str) -> bool:
if not wallet_name: if not wallet_name:
return False return False
if self.availableWallets.wallet_name_exists(wallet_name): if self.availableWallets.wallet_name_exists(wallet_name):
return False 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' if os.path.basename(wallet_name) != wallet_name: # '/foo/bar/' returns 'bar'
return False 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 return True
@pyqtSlot(str) @pyqtSlot(str)
+2 -32
View File
@@ -7,8 +7,7 @@ from electrum.base_crash_reporter import send_exception_to_crash_reporter
from electrum.logging import get_logger from electrum.logging import get_logger
from electrum import mnemonic from electrum import mnemonic
from electrum.wizard import NewWalletWizard, ServerConnectWizard, TermsOfUseWizard from electrum.wizard import NewWalletWizard, ServerConnectWizard, TermsOfUseWizard
from electrum.storage import WalletStorage, StorageReadWriteError from electrum.util import UserFacingException
from electrum.util import WalletFileException, UserFacingException
from electrum.gui import messages from electrum.gui import messages
if TYPE_CHECKING: if TYPE_CHECKING:
@@ -125,35 +124,6 @@ class QENewWalletWizard(NewWalletWizard, QEAbstractWizard):
'can_passphrase': can_passphrase '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) @pyqtSlot('QJSValue', bool, str)
def createStorage(self, js_data, single_password_enabled, single_password): def createStorage(self, js_data, single_password_enabled, single_password):
self._logger.info('Creating wallet from wizard data') self._logger.info('Creating wallet from wizard data')
@@ -163,7 +133,7 @@ class QENewWalletWizard(NewWalletWizard, QEAbstractWizard):
data['encrypt'] = True data['encrypt'] = True
data['password'] = single_password 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: try:
self.create_storage(path, data) self.create_storage(path, data)