Skip to content

Commit 90329bd

Browse files
committed
Handle decrypted text from encrypted QR codes
1 parent ff10f25 commit 90329bd

3 files changed

Lines changed: 61 additions & 2 deletions

File tree

src/seedsigner/gui/screens/tools_screens.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,14 +1136,16 @@ def _run(self):
11361136
class ToolsTextQRReviewTextScreen(ButtonListScreen):
11371137
textToEncode: str = None
11381138
title: str = None
1139+
max_lines: int = 5
1140+
visible_space: bool = True
11391141

11401142
def __post_init__(self):
11411143
# Customize defaults
11421144
self.is_bottom_list = True
11431145

11441146
super().__post_init__()
11451147

1146-
if " " in self.textToEncode:
1148+
if self.visible_space and " " in self.textToEncode:
11471149
self.textToEncode = self.textToEncode.replace(" ", "\u2589")
11481150

11491151
review_font_name = (
@@ -1155,7 +1157,7 @@ def __post_init__(self):
11551157
max_font_size = GUIConstants.get_top_nav_title_font_size() + 8
11561158
min_font_size = GUIConstants.get_top_nav_title_font_size() - 4
11571159
font_size = max_font_size
1158-
max_lines = 5
1160+
max_lines = self.max_lines
11591161
max_chars_per_line = -1
11601162
found_solution = False
11611163
for font_size in range(max_font_size, min_font_size-1, -2):

src/seedsigner/views/scan_views.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,18 @@ def _route_decrypted_payload(self, word_bytes: bytes) -> Destination:
839839
skip_current_view=True,
840840
)
841841

842+
try:
843+
decoded_text = word_bytes.decode("utf-8")
844+
except UnicodeDecodeError:
845+
decoded_text = None
846+
847+
if decoded_text:
848+
return Destination(
849+
ScanDecryptedTextView,
850+
view_args=dict(text=decoded_text),
851+
skip_current_view=True,
852+
)
853+
842854
return Destination(ScanInvalidQRTypeView)
843855

844856

@@ -905,3 +917,26 @@ def run(self):
905917
)
906918

907919
return Destination(MainMenuView, clear_history=True)
920+
921+
922+
class ScanDecryptedTextView(View):
923+
def __init__(self, text: str):
924+
super().__init__()
925+
self.text = text
926+
927+
def run(self):
928+
from seedsigner.gui.screens.tools_screens import ToolsTextQRReviewTextScreen
929+
930+
DONE = ButtonOption("Done")
931+
932+
self.run_screen(
933+
ToolsTextQRReviewTextScreen,
934+
title=_("Decrypted Text"),
935+
textToEncode=self.text,
936+
max_lines=8,
937+
visible_space=False,
938+
button_data=[DONE],
939+
show_back_button=False,
940+
)
941+
942+
return Destination(MainMenuView, clear_history=True)

tests/test_seedqr_ambiguity.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,25 @@ def test_decrypt_route_returns_prompt_for_nested_ambiguous_payload(self, monkeyp
155155
QRType.SEED__ENCRYPTEDQR,
156156
]
157157
assert destination.view_args["public_data"] == ENCRYPTED_PUBLIC_DATA
158+
159+
def test_decrypt_route_shows_text_when_payload_is_not_known_qr_type(self, monkeypatch):
160+
monkeypatch.setattr(
161+
DecodeQR,
162+
"analyze_bytedata_payload",
163+
staticmethod(
164+
lambda segment: PayloadAnalysis(
165+
segment=segment,
166+
candidate_types=[],
167+
public_data=None,
168+
encrypted_qr=None,
169+
)
170+
),
171+
)
172+
monkeypatch.setattr(DecodeQR, "resolve_payload_type", staticmethod(lambda _analysis: None))
173+
174+
view = scan_views.ScanDecryptEncryptedQRView(encryption_key="outer key", encrypted_data=b"unused")
175+
destination = view._route_decrypted_payload(b"UTF-8 TEXT")
176+
177+
assert isinstance(destination, Destination)
178+
assert destination.View_cls == scan_views.ScanDecryptedTextView
179+
assert destination.view_args["text"] == "UTF-8 TEXT"

0 commit comments

Comments
 (0)