From 9bcbcb056c43abef88540c54f25bc6c1a78c7c0e Mon Sep 17 00:00:00 2001
From: Elvis Angelaccio <elvis.angelaccio@kde.org>
Date: Sat, 14 Oct 2023 17:07:16 +0200
Subject: [PATCH] Fix support for bzip2 format with shared-mime-info 2.3

shared-mime-info 2.3 explicitly separated the mimetypes for bzip2 archives
from the mimetypes for the (old and deprecated) bzip archives.

libarchive doesn't support the old bzip format, however we can't just
drop it from ark since we still need it on systems that use an old
shared-mime-info package.

So for now we drop it only when we are sure that we are using a
shared-mime-info >= 2.3
---
 kerfuffle/mimetypes.cpp                              |  2 ++
 kerfuffle/pluginmanager.cpp                          | 12 ++++++++++++
 plugins/libarchive/CMakeLists.txt                    |  2 +-
 plugins/libarchive/kerfuffle_libarchive.json.cmake   |  6 ++++++
 .../kerfuffle_libarchive_readonly.json.cmake         |  1 +
 plugins/libarchive/libarchiveplugin.cpp              | 12 ++++++++++++
 6 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/kerfuffle/mimetypes.cpp b/kerfuffle/mimetypes.cpp
index 745325f41..f5515ebac 100644
--- a/kerfuffle/mimetypes.cpp
+++ b/kerfuffle/mimetypes.cpp
@@ -76,6 +76,8 @@ QMimeType determineMimeType(const QString& filename, MimePreference mp)
          mimeFromContent == db.mimeTypeForName(QStringLiteral("application/gzip"))) ||
         (mimeFromExtension.inherits(QStringLiteral("application/x-bzip-compressed-tar")) &&
          mimeFromContent == db.mimeTypeForName(QStringLiteral("application/x-bzip"))) ||
+        (mimeFromExtension.inherits(QStringLiteral("application/x-bzip2-compressed-tar")) &&
+         mimeFromContent == db.mimeTypeForName(QStringLiteral("application/x-bzip2"))) ||
         (mimeFromExtension.inherits(QStringLiteral("application/x-xz-compressed-tar")) &&
          mimeFromContent == db.mimeTypeForName(QStringLiteral("application/x-xz"))) ||
         (mimeFromExtension.inherits(QStringLiteral("application/x-tarz")) &&
diff --git a/kerfuffle/pluginmanager.cpp b/kerfuffle/pluginmanager.cpp
index 84a8c67c1..75d7abb09 100644
--- a/kerfuffle/pluginmanager.cpp
+++ b/kerfuffle/pluginmanager.cpp
@@ -165,6 +165,18 @@ QStringList PluginManager::supportedWriteMimeTypes(MimeSortingMode mode) const
         supported.remove(QStringLiteral("application/x-tzo"));
     }
 
+    // shared-mime-info 2.3 explicitly separated application/x-bzip2-compressed-tar from application/x-bzip-compressed-tar
+    // since bzip2 is not compatible with the old (and deprecated) bzip format.
+    // See https://gitlab.freedesktop.org/xdg/shared-mime-info/-/merge_requests/239
+    // With shared-mime-info 2.3 (or newer) we can't have both mimetypes at the same time, since libarchive does not support
+    // the old deprecated bzip format. Also we can't know which version of shared-mime-info the system is actually using.
+    // For these reasons, just take the mimetype from QMimeDatabase to keep the compatibility with any shared-mime-info version.
+    if (supported.contains(QLatin1String("application/x-bzip-compressed-tar")) && supported.contains(QLatin1String("application/x-bzip2-compressed-tar"))) {
+        supported.remove(QLatin1String("application/x-bzip-compressed-tar"));
+        supported.remove(QLatin1String("application/x-bzip2-compressed-tar"));
+        supported.insert(QMimeDatabase().mimeTypeForFile(QStringLiteral("dummy.tar.bz2"), QMimeDatabase::MatchExtension).name());
+    }
+
     if (mode == SortByComment) {
         return sortByComment(supported);
     }
diff --git a/plugins/libarchive/CMakeLists.txt b/plugins/libarchive/CMakeLists.txt
index 3f75540bc..7a1b6bd44 100644
--- a/plugins/libarchive/CMakeLists.txt
+++ b/plugins/libarchive/CMakeLists.txt
@@ -4,7 +4,7 @@ include_directories(${LibArchive_INCLUDE_DIRS})
 
 # NOTE: These are the mimetypes for "single-file" archives. They must be defined in the JSON metadata together with the "normal" mimetypes.
 # However they need to be duplicated here because we need to pass them as C++ define to the plugin (see LIBARCHIVE_RAW_MIMETYPES define below).
-set(SUPPORTED_LIBARCHIVE_RAW_MIMETYPES "application/x-compress;application/gzip;application/x-bzip;application/zlib;application/zstd;application/x-lzma;application/x-xz;application/x-lz4;application/x-lzip;application/x-lrzip;application/x-lzop;")
+set(SUPPORTED_LIBARCHIVE_RAW_MIMETYPES "application/x-compress;application/gzip;application/x-bzip;application/x-bzip2;application/zlib;application/zstd;application/x-lzma;application/x-xz;application/x-lz4;application/x-lzip;application/x-lrzip;application/x-lzop;")
 
 set(INSTALLED_LIBARCHIVE_PLUGINS "")
 
diff --git a/plugins/libarchive/kerfuffle_libarchive.json.cmake b/plugins/libarchive/kerfuffle_libarchive.json.cmake
index de13b1c87..4e0e2933a 100644
--- a/plugins/libarchive/kerfuffle_libarchive.json.cmake
+++ b/plugins/libarchive/kerfuffle_libarchive.json.cmake
@@ -53,6 +53,7 @@
             "application/x-tar",
             "application/x-compressed-tar",
             "application/x-bzip-compressed-tar",
+            "application/x-bzip2-compressed-tar",
             "application/x-tarz",
             "application/x-xz-compressed-tar",
             "application/x-lzma-compressed-tar",
@@ -119,6 +120,11 @@
         "CompressionLevelMax": 9,
         "CompressionLevelMin": 1
     },
+    "application/x-bzip2-compressed-tar": {
+        "CompressionLevelDefault": 9,
+        "CompressionLevelMax": 9,
+        "CompressionLevelMin": 1
+    },
     "application/x-compressed-tar": {
         "CompressionLevelDefault": 6,
         "CompressionLevelMax": 9,
diff --git a/plugins/libarchive/kerfuffle_libarchive_readonly.json.cmake b/plugins/libarchive/kerfuffle_libarchive_readonly.json.cmake
index 9475da267..f792659c8 100644
--- a/plugins/libarchive/kerfuffle_libarchive_readonly.json.cmake
+++ b/plugins/libarchive/kerfuffle_libarchive_readonly.json.cmake
@@ -61,6 +61,7 @@
             "application/x-compress",
             "application/gzip",
             "application/x-bzip",
+            "application/x-bzip2",
             "application/x-lzma",
             "application/x-xz",
             "application/zlib",
diff --git a/plugins/libarchive/libarchiveplugin.cpp b/plugins/libarchive/libarchiveplugin.cpp
index 5729a6bc6..bf5373ecc 100644
--- a/plugins/libarchive/libarchiveplugin.cpp
+++ b/plugins/libarchive/libarchiveplugin.cpp
@@ -13,6 +13,7 @@
 
 #include <KLocalizedString>
 
+#include <QMimeDatabase>
 #include <QThread>
 #include <QFileInfo>
 #include <QDir>
@@ -34,6 +35,17 @@ LibarchivePlugin::LibarchivePlugin(QObject *parent, const QVariantList &args)
 
 #ifdef LIBARCHIVE_RAW_MIMETYPES
     m_rawMimetypes = QStringLiteral(LIBARCHIVE_RAW_MIMETYPES).split(QLatin1Char(':'), Qt::SkipEmptyParts);
+    // shared-mime-info 2.3 explicitly separated application/x-bzip2 from application/x-bzip
+    // since bzip2 is not compatible with the old (and deprecated) bzip format.
+    // See https://gitlab.freedesktop.org/xdg/shared-mime-info/-/merge_requests/239
+    // With shared-mime-info 2.3 (or newer) we can't have both mimetypes at the same time, since libarchive does not support
+    // the old deprecated bzip format. Also we can't know which version of shared-mime-info the system is actually using.
+    // For these reasons, just take the mimetype from QMimeDatabase to keep the compatibility with any shared-mime-info version.
+    if (m_rawMimetypes.contains(QLatin1String("application/x-bzip")) && m_rawMimetypes.contains(QLatin1String("application/x-bzip2"))) {
+        m_rawMimetypes.removeAll(QLatin1String("application/x-bzip"));
+        m_rawMimetypes.removeAll(QLatin1String("application/x-bzip2"));
+        m_rawMimetypes.append(QMimeDatabase().mimeTypeForFile(QStringLiteral("dummy.bz2"), QMimeDatabase::MatchExtension).name());
+    }
     qCDebug(ARK) << "# available raw mimetypes:" << m_rawMimetypes.count();
 #endif
 }
-- 
GitLab

