mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-15 17:16:07 +00:00
fix(frontend): decode URL-safe base64 when parsing an imported share link
Base64.decode called window.atob directly, which rejects the base64url alphabet (- and _) and unpadded input. But the panel's own share-link emitter uses Base64.encode(x, true) (URL-safe, unpadded), and real SIP002 links do too, so importing a Shadowsocks link whose method:password encodes with a - or _ threw, fell back to the raw undecoded string, and produced a wrong method and garbage password (the vmess parser shared the same limitation). Normalize base64url and re-pad before atob so decode round-trips every emitted link.
This commit is contained in:
@@ -250,6 +250,19 @@ describe('parseShadowsocksLink', () => {
|
||||
expect(settings.servers[0].method).toBe('aes-256-gcm');
|
||||
expect(settings.servers[0].password).toBe('legacypw');
|
||||
});
|
||||
|
||||
it('decodes URL-safe base64 userinfo (as the emitter writes it)', () => {
|
||||
// genShadowsocksLink emits Base64.encode(method:password, true) — URL-safe,
|
||||
// so a password whose encoding contains - or _ must still round-trip.
|
||||
const method = 'aes-256-gcm';
|
||||
const password = '>>>';
|
||||
const userinfo = Base64.encode(`${method}:${password}`, true);
|
||||
expect(userinfo).toMatch(/[-_]/);
|
||||
const out = parseShadowsocksLink(`ss://${userinfo}@1.2.3.4:8388#urlsafe`);
|
||||
const settings = out?.settings as { servers: Array<{ method: string; password: string }> };
|
||||
expect(settings.servers[0].method).toBe(method);
|
||||
expect(settings.servers[0].password).toBe(password);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseHysteria2Link', () => {
|
||||
|
||||
@@ -641,8 +641,10 @@ export class Base64 {
|
||||
}
|
||||
|
||||
static decode(content: string = ''): string {
|
||||
const normalized = content.replace(/-/g, '+').replace(/_/g, '/');
|
||||
const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, '=');
|
||||
return new TextDecoder().decode(
|
||||
Uint8Array.from(window.atob(content), (c) => c.charCodeAt(0)),
|
||||
Uint8Array.from(window.atob(padded), (c) => c.charCodeAt(0)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user