Add db merged with exact account/chat/local-ID selection and shard ambiguity checks. Preserve Int64 composite message types and parse bounded, DTD-free embedded record XML, including duplicate messages and source metadata. Revalidate cached keys against current page-1 HMAC; replace the SQL write probe with sqlite3_db_readonly. Core tests: 129 passed. Windows Session 0 database validation: 5/5; all 16 text/sender/source-ID/timestamp entries matched independent XML parsing. Read-only UI baseline: 3/3; zero sends.
42 lines
3.6 KiB
Markdown
42 lines
3.6 KiB
Markdown
# 数据库合并聊天记录展开 — 2026-09-06
|
||
|
||
## 调用方式
|
||
|
||
```text
|
||
WxAgent.Host db merged --account <account-fingerprint> --chat filehelper --local-id 149
|
||
WxAgent.Host db merged --account <account-fingerprint> --chat filehelper --local-id 149 --include-content
|
||
```
|
||
|
||
可选 `--database <relative-path>` 消除不同消息分库 local ID 重复时的歧义;支持 `--key-file` 与 `--timeout`。只使用既有账户密钥缓存,不调用内存扫描器,也不打开聊天窗口。
|
||
|
||
默认返回父记录身份、条目路径、类型、脱敏发送人标识、原消息 ID、时间戳和正文长度;正文、显示名称、合并标题和描述为 null。`--include-content` 显式启用正文/名称。源 `hashusername` 不是可确认的真实 wxid,因此不把它伪装为 wxid。
|
||
|
||
## 实现与安全
|
||
|
||
- 将数据库 `local_type` 模型和转换从 Int32 修正为 **Int64**;实测合并类型为 `81604378673`。原先直接读取此记录会发生 Int32 溢出。
|
||
- 精确按聊天表及 `local_id` 参数查询,逐个消息分库检查;多处命中必须显式选择分库,不返回第一个碰巧匹配的消息。
|
||
- 解析 `appmsg/type=19 → recorditem → recordinfo/datalist/dataitem`,保留顺序、重复正文、原始字符串 ID、秒级 Unix 时间、显示时间和发送人名称。嵌套记录拥有独立路径,不把重复 dataid 当作去重依据。
|
||
- XML 禁止 DTD/外部实体,限制文档字符数、深度、嵌套记录层数及总条目数。声明数量与实际不符、文本缺失、非法时间等明确报错,不用空结果掩盖损坏。
|
||
- Hex/Zstd 解码有尺寸上限,避免压缩消息无限膨胀。
|
||
- 每次 SQLCipher 打开前,缓存密钥重新通过**当前目标数据库 page-1 HMAC**校验;连接仍为 `Mode=ReadOnly` 与 `query_only=ON`。
|
||
- 移除原来的 `CREATE TABLE` 写拒绝探针,改为读取 `sqlite3_db_readonly`,不尝试任何数据库写入。打开失败时也释放连接。
|
||
- 仅输出允许的附件元数据,不导出 CDN 地址/AES 密钥,不下载附件或绕过协议。
|
||
|
||
## 真机验收
|
||
|
||
- 微信 `4.1.13.63`,Windows `10.1.1.101`。
|
||
- 最终发布:`C:\Users\Rogee\wx-agent\releases\db-merged-20260906T120104`。
|
||
- EXE SHA-256:`5DB6A6422F6DAD9AE76C6C4D5A522576C7B7EB0534396434A536190D4E0DEEF8`。
|
||
- Linux **129/129 Core 测试通过**,完整 Release build 无警告/错误。
|
||
- `Test-DatabaseMerged.ps1` 在 **SSH Session 0** 运行,5/5 通过:默认脱敏输出、显式正文输出、数据库只读状态、非法 ID、缺失 ID。数据库读操作无需微信所在交互桌面;没有在 Session 0 执行 UI 自动化。
|
||
- 既有交互会话另行执行 doctor、inspect-ui、`smoke --read-only`,3/3 通过。
|
||
- 文件传输助手中父记录 local ID **149** 展开 **16 条文本消息**。
|
||
- 用独立 Python XML 解析器逐条对照数据库原始嵌入 XML:正文、发送人、原始消息 ID、时间戳 **各 16/16 完全一致**。
|
||
- 全程发送/转发次数 **0**。完整正文仅保留于忽略的私有验证产物,不进入 Git。
|
||
|
||
脱敏证据:[`evidence/Database-Merged-20260906/`](evidence/Database-Merged-20260906/)。第一次验证脚本误读 `metadata.WritesRejected` 的嵌套层次,修正脚本后同一二进制通过;并非数据库接受了写入。
|
||
|
||
## 验收范围
|
||
|
||
真实样本为 16 条文本;嵌套记录、附件元数据、恶意/截断 XML、重复条目和解压上限有离线测试。尚无混合图片/视频/文件、嵌套合并的真机样本;附件正文/原文件下载不属于本次展开结果。字段缺失保留 null,不补造身份或时间。
|