Skip to content

fix: support opening JSON files detected as MIME subtype#463

Merged
lzwind merged 1 commit into
linuxdeepin:masterfrom
wyu71:master
May 20, 2026
Merged

fix: support opening JSON files detected as MIME subtype#463
lzwind merged 1 commit into
linuxdeepin:masterfrom
wyu71:master

Conversation

@wyu71
Copy link
Copy Markdown
Contributor

@wyu71 wyu71 commented May 20, 2026

Files with $schema field are detected as application/schema+json instead of application/json, causing them to be rejected.

添加MIME类型继承检查,支持被系统识别为子类型的文件打开。

Log: 修复含$schema字段的JSON文件无法打开的问题
PMS: BUG-362033
Influence: 修复后所有JSON子类型(如schema+json)文件均可正常打开。

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @wyu71, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

Files with $schema field are detected as application/schema+json
instead of application/json, causing them to be rejected.

添加MIME类型继承检查,支持被系统识别为子类型的文件打开。

Log: 修复含$schema字段的JSON文件无法打开的问题
PMS: BUG-362033
Influence: 修复后所有JSON子类型(如schema+json)文件均可正常打开。
@deepin-ci-robot
Copy link
Copy Markdown

deepin pr auto review

你好!我是CodeGeeX。我已经仔细审查了你提供的Git Diff,本次修改主要涉及.gitignore更新、删除安装列表文件、更新版权声明,以及对文本文件MIME类型判断逻辑的重构。

以下是我从语法逻辑、代码质量、代码性能和代码安全四个维度提出的详细审查意见和改进建议:

1. 语法与逻辑

  • 版权声明年份逻辑问题
    • 问题:将版权年份从 2011-2024 修改为 2011-2026。通常,版权声明的结束年份应该是文件最后修改的年份(即当前年份2024或2025),直接写为未来的年份(2026)在法律和规范上是不严谨的。
    • 建议:建议改为当前年份,如 2011-20242011-2025,或者如果项目有自动化脚本更新年份,请确认其逻辑正确。
  • MIME类型继承检查逻辑
    • 问题:新增了 mime.inherits() 逻辑,这是一个非常好的改进,可以支持如 application/schema+json 这类衍生类型。但是,在循环中只检查了 SupportedTextMimeTypes 中的类型,而忽略了 text/ 前缀的基类。
    • 建议:如果某个MIME类型继承自 text/plain,当前的循环无法捕获到它。建议在循环前增加对 text/plain 的继承判断,或者将 text/plain 加入到 SupportedTextMimeTypes 列表中统一管理。

2. 代码质量

  • 静态常量提取(优秀)
    • 将原本在函数内部每次调用都重新构造的 textMimeTypes 列表提取为文件级的静态常量 SupportedTextMimeTypes,这是一个非常好的改进,避免了每次调用时的内存分配和初始化开销。
  • 调试日志过于频繁
    • 问题isMimeTypeSupport 函数中包含了大量的 qDebug() 日志。对于一个文本编辑器来说,打开目录、遍历文件时会极其频繁地调用此函数,这会产生海量的控制台输出,严重影响性能(I/O阻塞),同时也会让调试日志变得不可读。
    • 建议:建议将大部分 qDebug() 移除,仅保留错误分支或关键节点的日志。如果需要分类控制,建议使用 QLoggingCategory
  • .pub 后缀硬编码
    • 问题if (filepath.endsWith("pub")) 这种硬编码后缀的方式与MIME类型判断体系脱节,且没有检查点号(应该是 .pub),大小写敏感也未处理。
    • 建议:建议移除这个硬编码判断。如果必须支持,应改为 filepath.endsWith(".pub", Qt::CaseInsensitive),或者通过MIME类型体系来解决。

3. 代码性能

  • QMimeDatabase 对象的构造
    • 问题QMimeDatabase().mimeTypeForFile(...) 每次调用都会构造一个临时的 QMimeDatabase 对象。虽然Qt内部有缓存机制,但在高频调用场景下,频繁构造和析构依然有优化空间。
    • 建议:可以考虑将 QMimeDatabase 作为函数内的静态局部变量,或者作为类的成员变量,以复用其内部缓存。
  • QStringList::contains 的 O(N) 复杂度
    • 问题SupportedTextMimeTypes.contains(mimeType) 是线性查找 O(N)。虽然当前列表只有40多个元素,性能影响微乎其微,但作为基础工具函数,可以做到更优。
    • 建议:如果未来列表膨胀,建议将 SupportedTextMimeTypes 改为 QSet<QString>,将查找复杂度降至 O(1)。

4. 代码安全

  • application/octet-stream 的危险性
    • 问题SupportedTextMimeTypes 中包含了 "application/octet-stream"。这是二进制文件的默认MIME类型!如果将所有未知二进制文件(如 .exe, .bin, 压缩包等)都判定为文本并尝试读取,不仅会导致界面显示乱码,还可能因为文件过大导致内存激增甚至程序崩溃(OOM)。
    • 建议强烈建议移除 "application/octet-stream"。对于真正需要作为文本打开的二进制文件,应该通过文件后缀名特殊处理,而不是一刀切地放行所有二进制流。
  • 超大文件处理缺失
    • 问题isMimeTypeSupport 仅判断了文件类型,没有对文件大小进行限制。如果用户尝试打开几个GB的日志文件或二进制文件(由于上述 octet-stream 的存在),会导致严重的性能问题或内存溢出。
    • 建议:在判断MIME类型之前或之后,增加文件大小的检查(例如超过50MB则提示用户或拒绝直接全量加载)。

改进后的代码建议

以下是针对 src/common/utils.cpp 中修改部分的改进代码示例:

// 1. 使用 QSet 提升查找性能,并移除危险的 application/octet-stream
static const QSet<QString> SupportedTextMimeTypes = {
    "application/cmd",
    "application/javascript",
    "application/json",
    "application/pkix-cert",
    // "application/octet-stream", // 严重安全风险,建议移除!
    "application/sql",
    "application/vnd.apple.mpegurl",
    "application/vnd.nokia.qt.qmakeprofile",
    "application/vnd.nokia.xml.qt.resource",
    "application/x-desktop",
    "application/x-designer",
    "application/x-empty",
    "application/x-msdos-program",
    "application/x-pearl",
    "application/x-php",
    "application/x-shellscript",
    "application/x-sh",
    "application/x-theme",
    "application/x-cue",
    "application/x-csh",
    "application/x-asp",
    "application/x-subrip",
    "application/x-text",
    "application/x-trash",
    "application/x-xbel",
    "application/x-yaml",
    "application/x-pem-key",
    "application/xml",
    "application/yaml",
    "application/x-zerosize",
    "image/svg+xml",
    "application/x-perl",
    "application/x-ruby",
    "application/x-mpegURL",
    "application/x-wine-extension-ini",
    "model/vrml",
    "application/pkix-cert+pem",
    "application/x-pak",
    "application/x-code-workspace",
    "application/toml",
    "audio/x-mod",
    "application/pkix-attr-cert",
    "application/x-x509-ca-cert",
    "text/plain" // 建议将 text/plain 加入集合,统一通过 inherits 处理
};

bool Utils::isMimeTypeSupport(const QString &filepath)
{
    // 减少不必要的调试输出,或使用 QLoggingCategory
    // qDebug() << "Checking MIME support for:" << filepath;

    // 复用 QMimeDatabase 对象,利用其内部缓存
    static QMimeDatabase mimeDatabase;
    QMimeType mime = mimeDatabase.mimeTypeForFile(filepath, QMimeDatabase::MatchMode::MatchContent);
    
    if (!mime.isValid()) {
        return false;
    }

    QString mimeType = mime.name();

    // 1. 快速路径:直接匹配或者是 text/ 前缀
    if (SupportedTextMimeTypes.contains(mimeType) || mimeType.startsWith("text/")) {
        return true;
    }

    // 2. 兼容 .pub 后缀(修正大小写和点号)
    if (filepath.endsWith(".pub", Qt::CaseInsensitive)) {
        return true;
    }

    // 3. 检查继承关系 (包含了对 text/plain 及其他文本类型的继承)
    for (const QString &supported : SupportedTextMimeTypes) {
        if (mime.inherits(supported)) {
            return true;
        }
    }

    return false;
}

关于被删除的 org.deepin.editor.install 文件
删除这个包含194行绝对路径的安装列表文件是合理的,这些硬编码的绝对路径(如 /opt/apps/...)通常应该由构建系统(如 CMake/Cpack)动态生成,放在代码仓库里容易导致合并冲突且难以维护。只要确认你们的构建打包流程已经不再依赖此文件即可。

@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: lzwind, wyu71

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@lzwind lzwind merged commit d6b8a7b into linuxdeepin:master May 20, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants