bugfix: only list files with proper extension delimited by dot; fix UX showing suffixes in file_picker when no suitable files found

This commit is contained in:
scgbckbone 2025-09-26 00:42:13 +02:00 committed by Peter D. Gray
parent 722facf0d9
commit 6a3eec50f1
No known key found for this signature in database
GPG Key ID: A2DCD558C2BE5D7C
5 changed files with 54 additions and 9 deletions

View File

@ -1397,7 +1397,7 @@ async def import_xprv(_1, _2, item):
else:
# only get here if NFC was not chosen
# pick a likely-looking file.
fn = await file_picker(suffix='txt', min_size=50, max_size=2000, taster=contains_xprv,
fn = await file_picker(suffix='.txt', min_size=50, max_size=2000, taster=contains_xprv,
none_msg="Must contain " + label + ".", **choice)
if not fn: return
@ -1728,6 +1728,8 @@ async def file_picker(suffix=None, min_size=1, max_size=1000000, taster=None,
# - escape: allow these chars to skip picking process
# - slot_b: None=>pick slot w/ card in it, or A if both.
# - allow_batch: adds an "all of the above" choice: ("menu label", menu_handler)
# suffix argument MUST contain the dot (.), if list of suffixes - all MUST contain the dot
if choices is None:
choices = []
@ -1744,6 +1746,8 @@ async def file_picker(suffix=None, min_size=1, max_size=1000000, taster=None,
if suffix:
if not isinstance(suffix, list):
suffix = [suffix]
assert all(s[0] == "." for s in suffix)
if not any([fn.lower().endswith(s) for s in suffix]):
continue
@ -1793,7 +1797,7 @@ async def file_picker(suffix=None, min_size=1, max_size=1000000, taster=None,
if none_msg:
msg += none_msg
if suffix:
msg += '\n\nThe filename must end in %r. ' % suffix
msg += '\n\nThe filename must end in: %s' % ",".join(["*" + s for s in suffix])
msg += '\n\nMaybe insert (another) SD card and try again?'
@ -1873,7 +1877,7 @@ async def _batch_sign(choices=None):
return
assert isinstance(picked, dict)
choices = await file_picker(suffix='psbt', min_size=50, ux=False,
choices = await file_picker(suffix='.psbt', min_size=50, ux=False,
max_size=MAX_TXN_LEN, taster=is_psbt, **picked)
if not choices:
@ -1911,7 +1915,7 @@ async def ready2sign(*a):
opt = {}
# just check if we have candidates, no UI
choices = await file_picker(suffix='psbt', min_size=50, ux=False,
choices = await file_picker(suffix='.psbt', min_size=50, ux=False,
max_size=MAX_TXN_LEN, taster=is_psbt)
if pa.tmp_value:
@ -1938,7 +1942,7 @@ from your desktop wallet software or command line tools.'''
title=title)
if isinstance(picked, dict):
opt = picked # reset options to what was chosen by user
choices = await file_picker(suffix='psbt', min_size=50, ux=False,
choices = await file_picker(suffix='.psbt', min_size=50, ux=False,
max_size=MAX_TXN_LEN, taster=is_psbt,
**opt)
if not choices:
@ -1980,7 +1984,7 @@ async def sign_message_on_sd(*a):
# min 1 line max 3 lines
return 1 <= len(lines) <= 3
fn = await file_picker(suffix=['txt', "json"], min_size=2, max_size=500, taster=is_signable,
fn = await file_picker(suffix=['.txt', ".json"], min_size=2, max_size=500, taster=is_signable,
none_msg=('Must be txt file with one msg line, optionally '
'followed by a subkey derivation path on a second line '
'and/or address format on third line. JSON msg signing '

View File

@ -587,7 +587,7 @@ class SPAddrWhitelist(MenuSystem):
pat = re.compile(r'[^A-Za-z0-9]')
# pick a likely-looking file: just looking at size and extension
fn = await file_picker(suffix=['csv', 'txt'],
fn = await file_picker(suffix=['.csv', '.txt'],
min_size=20, max_size=20000,
none_msg="Must contain payment addresses", **choice)

View File

@ -67,7 +67,7 @@ async def import_tapsigner_backup_file(_1, _2, item):
continue
break
else:
fn = await file_picker(suffix="aes", min_size=100, max_size=160, **choice)
fn = await file_picker(suffix=".aes", min_size=100, max_size=160, **choice)
if not fn: return
origin += (" (%s)" % fn)
try:

View File

@ -734,7 +734,7 @@ async def kt_send_file_psbt(*a):
picked = await import_export_prompt("PSBT", is_import=True, no_nfc=True, no_qr=True)
if picked == KEY_CANCEL:
return
choices = await file_picker(suffix='psbt', min_size=50, ux=False,
choices = await file_picker(suffix='.psbt', min_size=50, ux=False,
max_size=MAX_TXN_LEN, taster=is_psbt, **picked)
if not choices:
# error msg already shown

View File

@ -1155,6 +1155,47 @@ def test_q1_24_8char_words(set_seed_words, is_q1, goto_home, pick_menu_item, pre
assert w0 == w1 == w2 == word
def test_file_picker_suffixes(pick_menu_item, goto_home, cap_story, microsd_wipe, press_select,
microsd_path):
# make sure no .txt, .7z & .pdf files are not on the SD card
microsd_wipe()
# create files that must not be recognized, because they're missing the dot
for fn in ["backup7z", "backuptxt", "template:pdf"]:
with open(microsd_path(fn), "w") as f:
f.write("dummy")
goto_home()
pick_menu_item("Advanced/Tools")
pick_menu_item("Danger Zone")
pick_menu_item("I Am Developer.")
pick_menu_item("Restore Bkup")
time.sleep(.1)
_, story = cap_story()
assert "No suitable files found" in story
assert "The filename must end in: *.7z,*.txt" in story
press_select()
goto_home()
pick_menu_item("Advanced/Tools")
pick_menu_item("Paper Wallets")
press_select()
pick_menu_item("Don't make PDF")
time.sleep(.1)
_, story = cap_story()
assert "No suitable files found" in story
assert "The filename must end in: *.pdf" in story
goto_home()
pick_menu_item("Advanced/Tools")
pick_menu_item("File Management")
pick_menu_item("Sign Text File")
time.sleep(.1)
_, story = cap_story()
assert "No suitable files found" in story
assert "The filename must end in: *.txt,*.json" in story
microsd_wipe()
@pytest.mark.onetime
def test_dump_menutree(sim_execfile):
# saves to ../unix/work/menudump.txt