From 468a1dd0433571b7ba562d899e81a42508bd3967 Mon Sep 17 00:00:00 2001 From: KnifeLemon Date: Tue, 27 Oct 2026 23:50:19 +0900 Subject: [PATCH] Read .ahk, .ini, .rsc and .cmd files as plain text (#536, #630, #661, #660) AutoHotkey scripts, INI settings files, MikroTik RouterOS exports and .cmd batch scripts join the TXT format like .bat, .ps1 and .sql: recognised as text and converted to TXT, PDF, DOCX and the other text targets, never run. A .cmd offered by a web page stays refused as before, like .bat. Settings schema 49 teaches existing text donuts the new extensions, plus .sql, which #611 added without a migration; custom claims stay put. Co-Authored-By: Claude Opus 5.5 --- docs/ENGINES.md | 2 +- src/Filee.Core/Formats/FormatRegistry.cs | 7 +++--- src/Filee.Core/Settings/AppSettings.cs | 2 +- src/Filee.Core/Settings/UserDataStore.cs | 4 ++++ tests/Filee.Core.Tests/ScriptTextTests.cs | 27 +++++++++++++++++++++-- 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/docs/ENGINES.md b/docs/ENGINES.md index 42fdc3a09..e3e5c6462 100644 --- a/docs/ENGINES.md +++ b/docs/ENGINES.md @@ -12,7 +12,7 @@ Filee chooses engines automatically. Settings → *Engines* shows their status, | PDFsharp | built in (library) | images → PDF, merge, split, page ranges, page organising, lossless rotate and crop-box edits, spreadsheet print-studio assembly, **compression** (smaller PDFs, see below), PDFs without their metadata | | PDFium | built in (library) | PDF → images (multi-page TIFF/GIF supported) | | Unhwp | built in (library) | HWP/HWPX → TXT, Markdown, HTML (pictures in a `_files` folder next to the Markdown, embedded in the HTML) | -| Text & Markdown (Markdig) | built in (library) | **Markdown → HTML, TXT**; **TXT, LOG, PY, PAC, BAT, COMMAND, LUA, CSS, PS1, SQL → UTF-8 TXT**, preserving source text without running scripts (and → PDF / DOCX through the HWPX writer, rhwp or LibreOffice) | +| Text & Markdown (Markdig) | built in (library) | **Markdown → HTML, TXT**; **TXT, LOG, PY, PAC, BAT, CMD, COMMAND, LUA, CSS, PS1, SQL, AHK, INI, RSC → UTF-8 TXT**, preserving source text without running scripts (and → PDF / DOCX through the HWPX writer, rhwp or LibreOffice) | | Spreadsheets (ExcelDataReader for XLS) | built in (library) | **XLSX, XLS, ODS, CSV, TSV → XLSX, ODS, CSV, TSV** (one CSV / TSV per sheet) | | Office Open XML | built in | **DOCM / DOTX / DOTM ↔ DOCX, XLSM / XLTX ↔ XLSX, PPTM / POTX / POTM / PPSX ↔ PPTX** (macros removed for macro-free types) | | Fonts | built in | **TTF, OTF, WOFF, WOFF2, EOT ↔ each other**; **FON (NE monochrome FNT v2/v3, supported single-byte charsets) → TTF, OTF, WOFF, WOFF2, EOT only**; CFF (PostScript) outlines become TrueType for TTF and EOT | diff --git a/src/Filee.Core/Formats/FormatRegistry.cs b/src/Filee.Core/Formats/FormatRegistry.cs index 93cb0a8f6..b5d77853b 100644 --- a/src/Filee.Core/Formats/FormatRegistry.cs +++ b/src/Filee.Core/Formats/FormatRegistry.cs @@ -140,9 +140,10 @@ public static class FormatRegistry new("sda", "SDA", FormatCategory.Presentation, ["sda", "sdd"], Writable: false), // Plain text / markup - // Text logs, source/proxy scripts and style sheets are read as plain text, never executed (issues #273, #284, #254, - // #388, #368, #607). - new("txt", "TXT", FormatCategory.Text, ["txt", "log", "py", "pac", "bat", "command", "lua", "css", "ps1", "sql"]), + // Text logs, source/proxy scripts, style sheets and settings files are read as plain text, never executed (issues + // #273, #284, #254, #388, #368, #607, #536, #630, #661, #660). + new("txt", "TXT", FormatCategory.Text, + ["txt", "log", "py", "pac", "bat", "cmd", "command", "lua", "css", "ps1", "sql", "ahk", "ini", "rsc"]), new("md", "Markdown", FormatCategory.Text, ["md", "markdown"]), new("html", "HTML", FormatCategory.Text, ["html", "htm", "xhtml"]), // A web page saved with its pictures in one MIME file (Chrome, Edge, Word); read as the page it holds. diff --git a/src/Filee.Core/Settings/AppSettings.cs b/src/Filee.Core/Settings/AppSettings.cs index bede3d9c9..b5f953c47 100644 --- a/src/Filee.Core/Settings/AppSettings.cs +++ b/src/Filee.Core/Settings/AppSettings.cs @@ -123,7 +123,7 @@ public static bool IsFlipKeyAllowed(string key, IEnumerable gest public sealed class AppSettings { /// Current schema version. Increase when the format changes and add a migration. - public const int CurrentSchemaVersion = 48; + public const int CurrentSchemaVersion = 49; public int SchemaVersion { get; set; } = CurrentSchemaVersion; diff --git a/src/Filee.Core/Settings/UserDataStore.cs b/src/Filee.Core/Settings/UserDataStore.cs index f9c47a370..d4ae8582c 100644 --- a/src/Filee.Core/Settings/UserDataStore.cs +++ b/src/Filee.Core/Settings/UserDataStore.cs @@ -889,6 +889,10 @@ public static bool ApplyToLibrary(int from, List presets, List Assert.Equal("txt", FormatRegistry.Detect(name)?.Id); [Fact] @@ -46,4 +51,22 @@ public void Version_38_text_donuts_learn_powershell_scripts() Assert.Contains("ps1", profiles.Single(p => p.Id == "text").Extensions); Assert.False(SettingsMigrations.ApplyToLibrary(39, presets, profiles)); } + + [Fact] + public void Version_48_text_donuts_learn_sql_ahk_ini_rsc_and_cmd_without_taking_custom_claims() + { + string[] added = ["sql", "ahk", "ini", "rsc", "cmd"]; + var presets = BuiltInData.CreatePresets(); + var profiles = BuiltInData.CreateProfiles(); + foreach (var profile in profiles) + profile.Extensions.RemoveAll(added.Contains); + profiles.Insert(0, new ToolbarProfile { Id = "my-router", Name = "Router", Extensions = ["rsc"] }); + + Assert.True(SettingsMigrations.ApplyToLibrary(48, presets, profiles)); + + var text = profiles.Single(p => p.Id == "text").Extensions; + Assert.All(added.Where(e => e != "rsc"), e => Assert.Contains(e, text)); + Assert.DoesNotContain("rsc", text); // the user's own donut has it + Assert.False(SettingsMigrations.ApplyToLibrary(48, presets, profiles)); + } }