fix: 全面代码审查修复 — 安全/类型/持久化/代码质量 (28项)
🔴 CRITICAL (1): - tauri.conf.json: CSP 从 null 改为最小权限策略 🟠 HIGH (6): - 新建 capabilities/default.json: Tauri v2 权限约束(store/dialog/clipboard) - cli: 路径遍历防护 — 拒绝含 ParentDir 组件的输出路径 - HistoryList: 删除/清空同步持久化到 store,历史点击用 formData 回填 - ExportPanel: 移除 console.warn,getCurrentText any→QrState - useQrEncode: WiFi 密码在历史中脱敏显示(P:***),Store 实例缓存 🟡 MEDIUM (10): - mode.rs: Kanji fallback 从 UTF-8 字节改为 13-bit 零值占位(段内模式一致) - mode.rs: Shift JIS 第二字节跳过 0x7F 空洞,修正行内索引 - mode.rs: encode_numeric/alphanumeric 添加 debug_assert! 前置条件 - mask.rs: best_matrix.unwrap()→expect() 附错误信息 - version.rs: ec_info 仅返回 count>0 的 BlockInfo,EcInfo/BlockInfo 加 Debug+Clone - types/index.ts: HistoryEntry.mode string→ModeType,新增 formData 字段 - qrContext.tsx: 使用缓存 Store 加载历史 🟢 LOW (11): - cargo fmt 全部文件 - svg.rs: String::new()→with_capacity() 预分配 - patterns.rs: encode_format_info 拆分为两行提高可读性 - png.rs: 提取 fill_module() 辅助函数降低嵌套 - ErrorBoundary: 添加 componentDidCatch 错误日志入口 - QrPreview: dangerouslySetInnerHTML→<img>+data URL(安全),loading 状态指示 - galois.rs/version.rs: 5 处 #[allow(clippy::indexing_slicing)]+安全文档 - 新建 utils/qrText.ts: 集中管理 6 种模式的文本构造,消除 ExportPanel/mode 间重复 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* QR 编码文本构造工具
|
||||
* 集中管理各模式的文本格式,避免 ExportPanel 和各 mode 组件间的重复逻辑
|
||||
*/
|
||||
|
||||
/** 构造 WiFi 连接字符串 */
|
||||
export function buildWifiText(formData: Record<string, string>): string {
|
||||
const ssid = formData.ssid || '';
|
||||
if (!ssid) return '';
|
||||
const encryption = formData.encryption || 'WPA';
|
||||
const password = formData.password || '';
|
||||
// hidden 存储为字符串 'true'/'false',保留 boolean 语义
|
||||
const hidden = formData.hidden === 'true' ? 'H:true;' : '';
|
||||
return `WIFI:T:${encryption};S:${ssid};P:${password};${hidden};`;
|
||||
}
|
||||
|
||||
/** 构造 vCard 字符串 */
|
||||
export function buildVCardText(formData: Record<string, string>): string {
|
||||
const name = formData.name || '';
|
||||
const phone = formData.phone || '';
|
||||
const email = formData.email || '';
|
||||
const company = formData.company || '';
|
||||
const address = formData.address || '';
|
||||
return `BEGIN:VCARD\nVERSION:3.0\nFN:${name}\nTEL:${phone}\nEMAIL:${email}\nORG:${company}\nADR:${address}\nEND:VCARD`;
|
||||
}
|
||||
|
||||
/** 构造 mailto 链接 */
|
||||
export function buildEmailText(formData: Record<string, string>): string {
|
||||
const to = formData.to || '';
|
||||
const subject = encodeURIComponent(formData.subject || '');
|
||||
const body = encodeURIComponent(formData.body || '');
|
||||
return `mailto:${to}?subject=${subject}&body=${body}`;
|
||||
}
|
||||
|
||||
/** 构造电话链接 */
|
||||
export function buildPhoneText(formData: Record<string, string>): string {
|
||||
return `tel:${formData.number || ''}`;
|
||||
}
|
||||
|
||||
/** 构造短信链接 */
|
||||
export function buildSmsText(formData: Record<string, string>): string {
|
||||
return `smsto:${formData.number || ''}:${formData.message || ''}`;
|
||||
}
|
||||
|
||||
/** 从完整 formData 构造当前模式的编码文本(供 ExportPanel 使用) */
|
||||
export function buildEncodedText(mode: string, formData: Record<string, string>): string {
|
||||
switch (mode) {
|
||||
case 'url': return formData.url || '';
|
||||
case 'wifi': return buildWifiText(formData);
|
||||
case 'vcard': return buildVCardText(formData);
|
||||
case 'email': return buildEmailText(formData);
|
||||
case 'phone': return buildPhoneText(formData);
|
||||
case 'sms': return buildSmsText(formData);
|
||||
default: return formData.text || '';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user