kindle/ —— Kindle Voyage 装机件 + KOReader + 词典 ================================================== 这个目录**不进 git**(约 200MB 二进制,已在 .gitignore 里)。 留这份说明是为了:万一目录没了,照着下面的 URL 能重新下回来, sha256 用来核对下回来的是不是同一份。 下面的 sha256 是「盘上这一份」的哈希,不是上游背书的校验和 (这些项目上游都没有发布官方 checksum 文件)。 下载来源和字节数当时都核过(详见 /srv/work/WORKLOG.md「9.1(四)」那节)。 服务地址:https://debate-room.cc/chat/kindle/<文件名>(走 /chat/ 那条 location) 词典另有一个下载页:https://debate-room.cc/chat/kindle/dict/ (下面第 6 项那份英汉词典在那儿有一个硬链接副本 dict-en-zh-ecdict.zip, 同一个 inode、同一个 sha256;另外多一部自己转的 CC-CEDICT 汉英词典。 说明和来源见 dict/README.txt。) 1. KOReader(阅读器本体) koreader-kindlepw2-v2026.07.1.zip 40,715,224 B sha256 ea1f575c54492a2c679d128b7f3210fd7d6a87e5f5a1ff1f7a7fe2080ff68f86 来源 GitHub koreader/koreader release v2026.07.1 的资产 https://github.com/koreader/koreader/releases/tag/v2026.07.1 注意 资产名是 koreader-kindlepw2-… 不是 koreader-kindle-pw2-…,保持原名。 Voyage 用的就是 kindlepw2 这个构建。 2. MRPI(MobileRead Package Installer,khf 构建) kual-mrinstaller-khf.zip 2,492,031 B sha256 9974dfc2d1e7687b3fc74d68f6b5aeab2428f22d83ab82e6d600a0384c607d09 来源 kindlemodding.org /jailbreaking/Legacy/post-jailbreak/installing-kual-mrpi/ (该页注明构建来源 fw.notmarek.com/khf/;不是 MobileRead 帖里那份) 3. PEKI(不装 booklet 也能出 KUAL 菜单) PEKI.zip 115,806 B sha256 f653045909ed230496c3d8176c9901d3a6a1f693c52b488569be6a60e0852499 来源 GitHub KindleTweaks/PEKI release v1.0 前提 其 README 写明「5.12.2.2+ Only, on Universal Hotfix 2.3.7 MAX」。 它靠 hotfix 的 scriptlet 机制跑 KUAL.sh —— hotfix 不带 scriptlet 支持 或版本不对时,文件放进 documents 也不会出现菜单,且不报错。 4. renameotabin(越狱步骤里改 OTA 文件名用) renameotabin.zip 1,031 B sha256 d2d333620420096e040e2f195c05bebfc97bdeeb5adf26b04c21a254e48ac439 来源 kindlemodding.org /jailbreaking/Legacy/post-jailbreak/ 5. KUAL booklet 备用件(PEKI 装不出 KUAL 时的两条退路) 取自 MobileRead KUAL 帖(t=203326)指向的 Snapshots 帖(t=225030)里 NiLuJe 的官方快照站 storage.gra.cloud.ovh.net/…/mr-public/KUAL/ KUAL-v2.7.37-gfcb45b5-20250419.tar.xz 224,876 B (原包,未改动) sha256 40c4b68712213adc7b667b9502cdd0c8099761fce1e1bf2b161b84102af54135 以下三个是从上面那个原包里取出来的,不是单独下载的: KUAL-KDK-2.0.azw2 131,070 B kindlet 路线 sha256 1d7cf02741be9e8f9c541af4eb5e1a97c00ab158819236749dba9250ad1fd4a9 注意 Voyage 走这条要**先装 MKK**。 Update_KUALBooklet_v2.7.37_install.bin 52,605 B booklet 路线,走 MRPI sha256 0ffbb284a07be036aeda5e9a8caf352ea41b76f977e206966c230243bcac864f Update_KUALBooklet_hotfix_v2.7.37_install.bin 52,313 B sha256 8688710215d06cde3a785aa353ebcd9aeb68da36dc4a3f623bd537850ac0a091 Update_KUALBooklet_v2.7.37_uninstall.bin 5,937 B sha256 c6b2c249103dd16314df4c6bc34a621ab5d23596153d6a37c0809063fd0fa3eb 6. 英汉词典(KOReader 查词用) dict-en-zh.zip 77,179,195 B sha256 86ad057401222149bce09d56d0ed217476cbbf8ca2958ff5af6e04ad577344c2 来源 GitHub skywind3000/ECDICT release 1.0.28 的 ecdict-stardict-28.zip https://github.com/skywind3000/ECDICT/releases/download/1.0.28/ecdict-stardict-28.zip 许可 MIT(包内带 LICENSE) 改动 .ifo / .idx 是上游原文件一字未动;.dict 压成了 dictzip(.dict.dz), 内容相同(整份解压后 sha256 与原文件一致),117.9MB → 45.9MB, 好处是 KOReader 只解一块就能查到词条。 包内 README-来源.txt 是这份改动的原始记录,以它为准。 装法 解压后把 stardict-ecdict-2.4.2/ 整个文件夹放进 koreader/data/dict/ 核对盘上这些文件有没有被动过: cd /var/www/companion-web/kindle && sha256sum -c <(grep -oE '^ sha256 [0-9a-f]{64}' README.txt) # 不好用,直接逐个 sha256sum 比上表 7. SimpleUI(KOReader 的主屏/导航栏插件) simpleui.koplugin-2.7.0.zip 1,638,529 B sha256 dbc296f6c6bb7034d0aab9184752aadcdf9060c782caccb058a6aef4c42171cf md5 4003c8c4729089ff7ae8e0dfaf154733 来源 GitHub doctorhetfield-cmd/simpleui.koplugin release 2.7.0(2026-08-30) https://github.com/doctorhetfield-cmd/simpleui.koplugin/releases/tag/2.7.0 原包名就是 simpleui.koplugin.zip,这里加了版本号,内容一字未动。 许可 MIT 是什么 **KOReader 内部的插件**,不是替换原生主屏的 hack —— 一个字都不碰 Kindle 原生系统。给 KOReader 加主屏(在读的书、书架、收藏、阅读统计、 每日一句、壁纸)+底部导航栏+顶栏。 装法(三步,顺序别换): 1) **先备份**:把 Kindle 上 `koreader/settings/` 整个文件夹拷到电脑上留一份。 这里面是她所有的阅读设置、统计库、各插件的配置。SimpleUI 会改 KOReader 的界面结构,出事时把这个文件夹拷回去就复原。 2) 解压 zip,把解出来的 `simpleui.koplugin` 文件夹整个拷进 Kindle 的 `koreader/plugins/`(**别拆平,也别再套一层**)。 放对了是:koreader/plugins/simpleui.koplugin/main.lua 3) 拔线,重启 KOReader。首次启动会弹一个配置向导。 不想要了:删掉 `koreader/plugins/simpleui.koplugin/` 这个文件夹,重启, 就回到原来的 KOReader。(设置残留在 koreader/settings/ 里,不影响。) 两件要知道的事: · 它带一个自动更新模块(`infra/sui_updater.lua`),会去 api.github.com 查新版本。 她那边连不上 GitHub,所以这个功能等于不存在 —— 不影响插件本身, 以后要升级还是从这个页面拿。 · 上游有一条**还开着**的 issue #313:SimpleUI 里那些会读统计库的模块, 会干扰 statistics 的**跨设备同步**。她只有这一台设备在读书,用不到跨设备同步, 所以现在不影响;但如果哪天统计数字看着不对,先想起这一条。 核过(发布前): · zip 完整、121 个文件、顶层就是 simpleui.koplugin/,含 main.lua 和 _meta.lua, `_meta.lua` 里的 version 是 "2.7.0",跟 release tag 对得上; · 68 个 .lua 全过 LuaJIT 语法(其中 7 个用了 `goto continue`, 那是 LuaJIT 认、Lua 5.1 不认的写法,**不是坏文件** —— 用 luac 5.1 查会误报); · 全仓库只有 `sui_updater.lua` 一处联网,目标是 api.github.com 的 releases 接口, 没有别的外发地址; · 从公网 URL 拉回来 md5 一致。 8. Noto Serif SC 500 / 700(KOReader 的中文正文字体,跟 library 同款同字重) NotoSerifSC-500-700.zip 20,407,846 B sha256 f48a7b618845428565a33d391ef4d0ac3afd08700f50b37d38ad5ad18f703a24 md5 0c697aa240c9d08fd0b6e9f15a247aeb 来源 GitHub notofonts/noto-cjk release Serif2.003(2024-07-30)的资产 14_NotoSerifSC.zip(68,960,596 B, sha256 c58cd035ab2adb003510846db9ec80c35b1b97755d329486c3a1e88edfe6e98e) https://github.com/notofonts/noto-cjk/releases/tag/Serif2.003 包里 SubsetOTF/SC/ 那一档就是「Noto Serif SC」(简体子集,不是整个 CJK 合集)。 原包七个字重,这里只取 Medium(500) 和 Bold(700) 两支,**字节未改**。 许可 SIL OFL 1.1(包内带上游原 LICENSE) 内容 NotoSerifSC-Medium.otf 11,734,356 B weightClass 500 sha256 见包内;NotoSerifSC-Bold.otf 12,094,336 B weightClass 700 两支各 30,928 个字符,Version 2.003。 装法(一步): 把里面的**两个 .otf 直接**放进 Kindle 的 `/mnt/us/fonts/`。 **不要放子文件夹** —— KOReader 会递归找到,但原生 Kindle 阅读器只认这一层; 放对了两边共用同一份字。重启 KOReader,字体里选 **Noto Serif SC**。 为什么两个字重要一起放: 它们在字体系统看来是同一族的两张脸 —— NotoSerifSC-Medium.otf family_name='Noto Serif SC' style='Medium' bold=否 NotoSerifSC-Bold.otf family_name='Noto Serif SC' style='Bold' bold=是 所以选 "Noto Serif SC" 之后**粗体是真粗体**,不是把 500 拉粗合成的。 中文小字号下合成粗体会把笔画间的小封闭空间糊死(网页那边早就踩过, 所以那边也是 500/700 两套都留着,见 NOTES「字体」那节)。 核过(发布前): · 两支 OS/2 weightClass 分别是 500 / 700,都不是斜体,各 30,928 字符; · 常用字表逐字查过一个不缺,西文 A-Za-z0-9 和中文标点齐全; · **用 ctypes 直接调 libfreetype 读 face.family_name / style_name / style_flags** —— 这正是 KOReader 读字体名走的那条路(fontlist.lua → freetype.lua)—— 确认两支同族、Bold 的粗体位置上; · 从公网 URL 拉回来 md5 一致。 注:`/var/www/companion-web/fonts/nsc/` 那 202 个 woff2 **不能拿来干这件事**。 那是按 unicode-range 切给浏览器按需下载的(101 块 × 500/700), KOReader 会把每一片当成一支只有几十个字的字体。要完整的脸就得是这个包。 9. readingtask.koplugin(主屏「现在读」:把 debate-room 里布置的阅读任务放上 Kindle) readingtask.koplugin-1.0.zip 16,833 B(zip 本体见下) sha256 894c6f8f6fd47bdc4447a3f199e7f151e7c222353b5f13ad0d4bbb996a1d3995 md5 c929822555b5676e2d8d295326340f01 自己写的,不是第三方件。 装法:解压,把 `readingtask.koplugin` 文件夹整个放进 `koreader/plugins/`, 重启 KOReader。装了 SimpleUI 的话,主屏的模块列表里会多出一个「现在读」, 在 SimpleUI 的排版设置里打开就行。**没装 SimpleUI 也能用** —— 工具菜单里有「debate-room · 现在读」,能看状态、能手动取一次。 它怎么工作(三条硬规矩,跟图书馆页那条是同一份数据): · **单一真相源**:任务只存在服务器的 control_tasks 表里。这边不存任务, 只存一份取回来的快照,不在本地编辑。 · **一个接口两个读者**:这边打 `/kindle/tasks`,图书馆页打 `/app/tasks/reading` —— 服务端是**同一个函数**,只是钥匙不同。 两边看到的永远是同一批。 · **断网显示缓存 + 多久前,不报错**:主屏画的时候**一次网都不打**, 只读本地缓存;取新数据是另一条路(限频 15 分钟、只在已经联网时、 排在画完之后)。**它绝不自己开 WiFi。** 钥匙跟划线插件同一套两抽屉读法(先 settings/kosync.lua,再退回 G_reader_settings)。**注意**:`kosync_key.lua` 是 debateroom 那份 auth() 的 有意重复(两个 koplugin 之间没有干净的共享办法),两个文件里都写了 "改一处必须改两处"。 跟 SimpleUI 的耦合只有一处:它 `modules/moduleregistry` 注释里写明的第三方 模块契约(`Registry.register`)。样式上不碰它的 infra,拿不到就退回 KOReader 自己的字体颜色 —— 它升级改了内部文件名,这里最多变丑,不会崩。 核过(发布前,**没有真机**): · luac 语法 + luacheck(只剩契约签名上的 unused 警告); · 写了一个替身环境把 main.lua **真的跑了一遍**(把所有 require 换成假的, 再调 build/getHeight/getMenuItems 和菜单回调),31 条断言全过: 文件管理器侧注册、阅读器侧不注册(不然关书会把主屏那条摘掉)、 build 里一次网都不打、空缓存/有缓存/断网三种落款文案、 JSON 坏掉和 HTTP 500 都只返回 false 不抛、坏条目被丢掉、 取失败不清缓存、超过 4 条时说"还有 N 条"、没装 SimpleUI 也能装上。 **没有在真 Kindle 上跑过** —— 装上之后先看工具菜单里那一项说什么。 10. zlibrary.koplugin(Z-library 客户端)—— 装之前把这一节读完 zlibrary.koplugin-1.0.47.zip 425,977 B sha256 cb743c3bd2e9d989a0843e49c8368081c634ca9f2b17e81a8fb9121509f8733c md5 cc029c52fc571964f435275bae9a5544 来源 GitHub ZlibraryKO/zlibrary.koplugin release v1.0.47(2026-08-16) 资产原名 zlibrary_plugin_v1.0.47.zip,**字节未改**,只加了版本号进文件名。 许可 AGPL-3.0 **选它的理由**:同类里维护得最好的一个。★712、38 fork、2025-05 建、 2026-08-16 还在推、open issue 只有 1 个、发版很勤(v1.0.47)。 另一个候选 OctoNezd/zlibrary.koplugin(★228)上一次推是 2026-02, open issue 6 个,落后半年多。 装法:解压之后包里是 `plugins/zlibrary.koplugin/`, 把**里面那个 `zlibrary.koplugin` 文件夹**放进 Kindle 的 `koreader/plugins/`。 (上游 zip 多包了一层 `plugins/`,别整个拷进去。) ── 审计结论(我逐个文件看过的,重点是凭据) ──────────────────────── **账号密码存在哪:明文。** 两个位置: · `koreader/settings/zlibrary.lua` —— 走 KOReader 的 LuaSettings, 就是一个明文 Lua 表; · `koreader/plugins/zlibrary.koplugin/zlibrary_credentials.lua` —— 可选的覆盖文件,也是明文(包里自带一个注释掉的模板)。 Kindle 的 `/mnt/us` 是插上电脑就能读的 U 盘分区, **所以任何人拿到这台机器、插上线,就能看到这个密码**。 → 对策:**给 z-library 用一个别处没用过的密码。** 这条不是建议,是前提。 **密码发去哪:只发给当前设置的那个镜像。** `Api.login` 把 email/password 表单编码 POST 到 `Config.getLoginUrl()`(= 当前 base URL),没有别的去处。 Cookie 是**按主机隔离**的(`jar[parsed.host]`),所以下面那些第三方请求 一个都带不上 z-lib 的会话。没有任何遥测/统计上报。 **会连的非 z-lib 域名,两类,都不带凭据:** · 自更新:`api.github.com` 取 release 信息 + 下载 release 资产; · 镜像清单:`assets/domains.json`,依次轮询 `fastly.jsdelivr.net` / `cdn.jsdelivr.net` / `raw.githubusercontent.com` / **`gh.xxooo.cf`**(第三方 GitHub 代理,给墙内用户兜底的)。 **这里有一条真正值得当心的链**(不是 bug,是设计的代价): 那份 domains.json 决定了有哪些候选镜像,而非交互路径上 `Discovery.finishDiscovery` 会把**第一个连得通的镜像自动设成 base URL**, 不问一句。base URL 又正是密码 POST 的目的地。 也就是说:谁能篡改 domains.json 那一跳,谁就能把登录请求引到自己的服务器。 jsdelivr 和 raw.githubusercontent 是可信的,**`gh.xxooo.cf` 是个不知底细的代理** (她那边多半连不上 GitHub,所以恰恰是这一条最可能被用到)。 → 对策:**在设置里把 base URL 固定成一个你信的镜像**,别让它自动漂。 **TLS:真的走 TLS,但不验证书。** 插件用的是 `socket.http`,而 KOReader 自带的 `common/socket/http.lua` 打过补丁,`https` 走 LuaSec 的 `https.tcp` (LuaSec 1.3.2,带 SNI)。但 LuaSec 的默认配置是 `verify = "none"` —— **这是 KOReader 全局如此,不是这个插件的锅**,可它意味着店里 WiFi 上 一个主动中间人可以解密这次登录。合起来看,"独立密码 + 固定镜像"这两条对策 的分量比平时更重。 **跟 Voyage + KOReader v2026.07.1 的兼容性**:17 个 .lua 全过 Lua 5.1 语法 (**一个 `goto` 都没用**,所以连方言问题都没有);用到的都是 KOReader 的公共件 (`socketutil`、`ffi/blitbuffer`、`ffi/sha2`、`ui/widget/*`),没有平台相关的东西; 下载目录默认取 `G_reader_settings.home_dir`。**没有真机验证过。** ── 一句话结论 ── 凭据没有乱飞(只去当前镜像,cookie 按主机隔离,无遥测),可以装; 但**明文存密码**和**镜像会自动漂**这两点,要用"独立密码 + 固定 base URL"顶住。 11. pinyin_enhancement.koplugin(拼音输入法增强:候选词栏) pinyin_enhancement.koplugin-1.5.3.zip 991,655 B sha256 67fc9731710c811ddd3a0276d61531bfc9fad8e7dcb68bedcea59bd93c77d69a md5 287a56c0f5bea7381d1daf43ab4b8ba0 来源 GitHub gytwo/pinyin_enhancement.koplugin release **v1.5.3**(2026-07-06) 上游资产原名 pinyin_enhancement.koplugin.zip,989,119 B, sha256 1e4fdc46ebb15d2b1ca6850df46f7001fe57278e90f143a2352106bc7c356e92 许可 见包内 LICENSE **包我重打过一次,只加了一层文件夹,文件一个字节没改。** 上游那个 zip 解开是**散文件**(README.md / main.lua / lexicon/ …直接在根上), 而它自己的 README 说"把 `pinyin_enhancement.koplugin` 文件夹放到 koreader/plugins"—— 对不上。所以我把 40 个文件原样装进一个同名文件夹再打包。 核过:**两个包的文件名单一致(40/40),逐文件 sha256 全部相同,0 个不一致**。 (所以盘上这一份的 sha256 跟上游资产的对不上是**预期**的 —— 差的就是那层文件夹。) **拼写**:派单写的是 `pinyin_enchancement`(作者在 Gitee 那边拼错的原味), 但 **GitHub 上这个仓库拼的是 `pinyin_enhancement`(正确拼法)**,包内 `_meta.lua` 里 `name = "pinyin_enhancement"` 也是正确拼法。按现场走。 另:README 顶上的 badge 显示 GitHub 这份是 **从 Gitee 同步过来的** (gytwo/gitee-sync 的 workflow),跟"Gitee 转私有、GitHub 是有效更新源"这个说法对得上。 ── 安检三条(她要的那三项)── a) **出网**:只有 `pinyin_update.lua` 一个文件会联网,去的是 `api.github.com/repos/gytwo/pinyin_enhancement.koplugin/releases…` 和 `gitee.com/api/v5/repos/…`(owner/repo 都是写死的常量),外加从返回的 `browser_download_url` 下载它自己的 release。**其余 6 个 .lua 一行网络代码都没有。** 而且**不自动查**:唯一入口是设置菜单里那颗「检查更新」(main.lua 第 620 行附近), 启动时不联网。 b) **文件读写**:读只读自己目录(`DataStorage:getDataDir().."/plugins/pinyin_enhancement.koplugin/"` 下的 lexicon/ 码表),`io.open` 全包只有一处、且是**只读**(读自己的 `_meta.lua` 取版本号)。 写有两类:① 设置项写进 **KOReader 的全局设置**(`G_reader_settings`,键名都是 `pinyin_*`) —— 这是 koplugin 的常规做法,但**严格说不在插件目录内**,如实记一笔; ② 自更新时把 zip 下到 `/tmp/`(Android 走 data_dir/plugins)再解进自己的插件目录。 c) **os.execute**:**有,9 处,全部在 `pinyin_update.lua` 的自更新流程里**, 内容是 `mkdir -p` / `curl` / `wget` / `busybox wget` / `unzip`。不是"奇怪"的用途, 但要知道两件事: · 它等于"插件能自己下载并解包覆盖自己"——**装了就有这条自更新链**; · 下载那几条把 URL 拼进 shell 命令(`curl -L ... -o '%s' '%s'`,单引号包着)。 URL 来自 GitHub/Gitee 的 API JSON。正常情况没问题,但**如果上游 release 元数据被做手脚**(URL 里塞单引号),这里是能逃出引号的。另有一条 `unzip -o %s -d %s` **没加引号**(第 475 行,非 Android 分支)——那两个路径 是写死的常量,当下不构成问题。 → 结论:**代码本身没有后门迹象**(不读通讯录式的东西、没有遥测、没有混淆、 没有 loadstring/ffi.load);风险点就是这条自更新链本身。 对策很简单:**不点「检查更新」**,要升级时照样从这儿下新包手动换。 ── 跟她那台的兼容性 ── release 说明和 README **都没写 KOReader 最低版本要求**(v1.5.3 的 release notes 只有三条功能变更)。它依赖 KOReader 自带的 `ui/data/keyboardlayouts/zh_CN_keyboard` 与 `ui/data/keyboardlayouts/zh_pinyin_data` (后者用 `pcall` 包着,缺了不会崩),其余都是公共件(`ui/widget/*`、`ffi/blitbuffer`、 `libs/libkoreader-lfs`)。她的 **kindlepw2-v2026.07.1** 比这个 release(2026-07-06) 还新一点,接口面没有理由对不上。**没有真机验证过。** ── 还没做的 ── 预载高频词(她报词之后再说);码表一个字没改,包里是上游原样。 ── 11b. 预载版(跟 11 二选一,别两个都装)── pinyin_enhancement.koplugin-1.5.3-preloaded-684d9dcab5f52609.zip 1,035,651 B sha256 4688247c881046a9692b82dbbdb2cbaae44a04a56b720913f3fdf5b57c574029 md5 28e5560b12e8d5f653265ae929dff533 **是什么**:跟 11 是同一个 v1.5.3,40 个文件里 **39 个逐字节相同**, 只有 `zh_pinyin_data_abbr.lua` 被换成「插件原表 + 你搜狗用户词库里打过 3 次以上的 17,249 个词」的合并表(13,278 键 / 56,096 条,740,088 B;同一个键里**你打过的排在前面**, 按你自己的词频从高到低,原表的词跟在后面 —— 是叠加不是替换)。 装的时候不用改名:解压出来的 `pinyin_enhancement.koplugin` 文件夹直接放进 `koreader/plugins/`。 **装前先把整个 `koreader` 文件夹备份一次**。插件自己的 README 写着: 「大量加载码表会占用大量内存,可能会导致设备因内存不足而卡死」「额外自定义码表不能太大(超过 1M)」。 这一版的码表 740 KB,比原表(615 KB)大 20%,**特意压在 1 M 以下**; 全量版(10.7 万词、约 2 MB)已经过线一倍,所以没有上架。 **跟 11 二选一**:两个包是同一个插件同一个目录名,装了这个就别再装原味那个(反之亦然)。 **文件名带一段随机后缀**:这一包里是逾水的个人输入史,而 /chat/kindle/ 下的静态文件 没有服务端闸(PIN 门是页面上的 JS,直接敲 URL 拿得到),Kindle 那头又过不了 PIN —— 所以文件名就是唯一的门。**装好之后告诉 Claude,这一包即从货架撤下。** (原味包 11 不带她的数据,文件名照旧,不用撤。) **已撤架(2026-09-19)**:她确认装好,预载包已从 /var/www/companion-web/kindle/ 删除, 下载页对应那一行也删了。原味包 11 保留。要再要一份,用 /root/kindle-dl/ 里的 zh_pinyin_data_abbr.merged-freq3.lua 按同样方式重打即可。