* fix(link): strip query and trailing slash when parsing ss:// port
Subscription-provided Shadowsocks links use the SIP002 form
ss://userinfo@host:port[/][?plugin=...]#tag. parseShadowsocks only
stripped the #fragment, so a "?plugin=" / "?type=" query and the
optional trailing slash leaked into the host:port split, strconv.Atoi
failed, and the port was silently set to 0 (the error was discarded).
Direct link import was unaffected because it runs through the frontend
parser, which already handles this.
Strip the query and the trailing slash before splitting host:port,
mirroring the frontend outbound-link-parser and the SIP002 grammar.
This complements #5432, which fixed the SS2022 generation side.
Add table-driven parseShadowsocks tests covering modern, legacy,
base64url userinfo, the SIP002 slash+plugin form, and SIP022
percent-encoded userinfo with a dual-key password.
* fix(link): surface ss:// port parse errors instead of defaulting to 0
The modern and legacy Shadowsocks branches discarded the strconv.Atoi
error when reading the port, silently yielding port 0 for any malformed
host:port. Return a parse error instead, matching defaultPort's existing
pattern in this file, so a bad link is skipped by ParseSubscriptionBody
rather than injected as an unusable port-0 outbound.