Skip to content

Conversation

@IgorEisberg
Copy link
Collaborator

@IgorEisberg IgorEisberg commented Jan 5, 2026

Fixes #4059
Fixes: #2890

This makes the splitting of the attributes part of a StyledString span's tag stricter.
Unfortunately, the way these tags are encoded is very ambiguous, so we make a best guess approach to cover all known cases.

Example: <span href="https://test.com/1234#param=val" style="font-family: serif; font-size:12px;">
Is encoded as: span;href=https://test.com/1234#param=val;style=font-family: serif; font-size:12px;

The keys have a specific set of valid characters, but the values can contain any character, including the separators ; and =.
We're splitting on ; but with a lookahead for a valid key followed by =.
This is not 100% fail-proof and won't decode accurately if a value contains a ; followed by a valid key format, but at least it won't crash (discussed in the comment below).

Added test cases as well.

@IgorEisberg IgorEisberg enabled auto-merge (squash) January 5, 2026 10:15
@IgorEisberg
Copy link
Collaborator Author

IgorEisberg commented Jan 5, 2026

This can't handle the case in #2890 (doesn't crash now though).

a;href=intent:#Intent;action=android.settings.SYSTEM_UPDATE_SETTINGS;end

Here, ";action=" is wrongly identified as another attribute key, but it's part of intent:.

However, that tag is not valid in ARSC to begin with and is a translation mistake.
Android itself only reads the "intent:#Intent" part and the rest is assumed to be a separate subtag.
https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-16.0.0_r4/core/java/android/content/res/StringBlock.java#507
Printing the spans in the spanned string on Android outputs URLSpan{URL='intent:#Intent'}, and action is ignored because it's unknown.
As you can see, these span tags are not HTML, just predefined HTML-like tags translated explicitly:
https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-16.0.0_r4/core/java/android/content/res/StringBlock.java#356

The default string escapes the tag (&lt; instead of <) and then programmatically parsed using Html.fromHtml(), which is the correct way to deal with this special case. This PR can be merged as-is for now.

Improperly translated string, for example:

<string name="assistant_dictation_ineligible_android_old_version">Pokud chcete použít hlasové zadávání pomocí Asistenta, aktualizujte systém Android. <a href="intent:#Intent;action=android.settings.SYSTEM_UPDATE_SETTINGS;end"> Aktualizovat </a> <br/><br/><a href="https://support.google.com/gboard/answer/11197787#update_app"> Další informace </a></string>

The proper default string, for reference:

<string name="assistant_dictation_ineligible_android_old_version">To use Assistant voice typing, update your Android System. &lt;a href=intent:#Intent;action=android.settings.SYSTEM_UPDATE_SETTINGS;end> Update &lt;/a> &lt;br/>&lt;br/>&lt;a href=https://support.google.com/gboard/answer/11197787#update_app> Learn more &lt;/a></string>

@IgorEisberg IgorEisberg merged commit d0ba27f into main Jan 6, 2026
18 checks passed
@IgorEisberg IgorEisberg deleted the fix-span branch January 6, 2026 13:54
@iBotPeaches iBotPeaches added this to the 3.0.0 milestone Jan 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Apktool can't unpack com.foreo.foreoapp's resources [BUG] Chunk [end] is not a valid entry

3 participants