fix(qr): hide QR for post-quantum links on client QR page

Opening the client sublinks/QR modal crashed when a link used
post-quantum keys (ML-DSA-65 / ML-KEM-768): the encoded URL exceeds
the antd QRCode capacity and the component throws. The client QR modal
rendered the QRCode unconditionally, so it took down the page.

The names don't appear verbatim in a share link — mldsa65Verify rides
inside pqv=<base64> and ML-KEM-768 inside encryption=mlkem768x25519plus.
The QR modal and inbound QR modal used a literal-substring guard that
missed those encoded forms, leaving the QR (and the crash) in place.

Consolidate detection into a single isPostQuantumLink() helper in
inbound-link.ts and reuse it across the client QR, inbound QR, client
info, and sub surfaces. The copy/download link still works; only the
QR image is suppressed for oversized post-quantum links.

Closes #4656
This commit is contained in:
MHSanaei
2026-05-29 17:04:30 +02:00
parent 90a64a1b22
commit 5d0081a3b9
5 changed files with 19 additions and 29 deletions
+1 -13
View File
@@ -31,6 +31,7 @@ import {
} from '@ant-design/icons';
import { ClipboardManager, IntlUtil, LanguageManager } from '@/utils';
import { isPostQuantumLink } from '@/lib/xray/inbound-link';
import { setMessageInstance } from '@/utils/messageBus';
import { pauseAnimationsUntilLeave, useTheme } from '@/hooks/useTheme';
import SubUsageSummary from './SubUsageSummary';
@@ -90,19 +91,6 @@ function trimEmail(remark: string, email: string): string {
.trim();
}
// Post-quantum keys blow up the encoded URL past what a single QR can
// hold. The algorithm names don't appear as plain text in the URL —
// they ride inside query params: mldsa65Verify → `pqv=<base64>`,
// ML-KEM-768 → `encryption=mlkem768x25519plus.<...>`. The literal
// substrings are also matched in case a config (e.g. wireguard) embeds
// them directly.
function isPostQuantumLink(link: string): boolean {
if (/[?&]pqv=/.test(link)) return true;
if (link.includes('mlkem768') || link.includes('mldsa65')) return true;
if (link.includes('ML-KEM-768')) return true;
return false;
}
// Decode a base64 string as UTF-8. atob() returns a binary string where
// each char holds one raw byte (Latin-1 interpretation), which mangles
// any multi-byte UTF-8 sequence in the payload — most commonly the