NaiveFmt.ToUri percent-encodes the username and password, so a
password-only profile with the password a:b is exported as
naive+https://a%3Ab@host. Resolve decoded the user info before
looking for the ':' separator and imported it as username "a",
password "b". Split the raw user info first and decode each part.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Use generated JSON type metadata and propagate mapped SQLite types through CRUD and transactional bulk operations. Cover serialization options, affected counts, rollback and native test compatibility without changing UI models or persistence entities.
For a SIP002 link whose user info is "method:password" rather than
base64 (the 2022-blake3 form), ResolveSip002 unescapes the whole user
info and then unescapes the password a second time. A password that
still holds a valid percent sequence after the first pass decays:
p%41ss is written as p%2541ss and imported as pAss.
Same double-decoding as #10027 fixed for query values.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The AnyTLS URI scheme makes the port optional and defaults it to 443,
and two of its three examples leave it out. The naive+https:// and
naive+quic:// link format does the same: the port is omitted when it is
443, and none of its examples carries one.
System.Uri answers -1 for an unregistered scheme with no port, so these
links were imported with Port = -1 and the profile failed IsValid().
Apply the same default Hysteria2Fmt already uses (#10026). An explicit
":0" is still kept as 0.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
SocksFmt.Resolve tries ResolveSocksNew first and only falls back to the
legacy socks://base64(user:pass@host:port) parser when System.Uri
rejects the link. System.Uri accepts most legacy links, though: it takes
the base64 as the host (lower-cased) and anything after a '/' as the
path. It only rejects a base64 that ends in '=' padding and has no '/',
so links without padding, or with a '/' or '_' in the base64, were
imported with the base64 as the address, port -1 and no credentials.
A legacy link has no port of its own, so let ResolveSocksNew give up
when the URI has none and leave the link to ResolveSocks.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A speed test only stored a speed above zero, so a node that was skipped
because its delay test failed, or whose download failed, kept the speed
of the previous run. The list showed the skip or error text until it was
sorted or refreshed; then the old speed came back and the node sorted as
if it had been measured. Clear the stored speed when a speed or mixed
test starts.