diff --git a/core_lib/src/qminiz.cpp b/core_lib/src/qminiz.cpp index c445b0e163..b7f7ece7e5 100644 --- a/core_lib/src/qminiz.cpp +++ b/core_lib/src/qminiz.cpp @@ -15,11 +15,11 @@ GNU General Public License for more details. */ #include "qminiz.h" +#include #include #include #include #include -#include "miniz.h" #include "util.h" @@ -38,8 +38,18 @@ bool MiniZ::isZip(const QString& sZipFilePath) return (num > 0); } +size_t MiniZ::istreamReadCallback(void *pOpaque, mz_uint64 file_ofs, void * pBuf, size_t n) +{ + std::istream *stream = static_cast(pOpaque); + mz_int64 cur_ofs = stream->tellg(); + if ((mz_int64)file_ofs < 0 || (cur_ofs != (mz_int64)file_ofs && stream->seekg((mz_int64)file_ofs, std::ios_base::beg))) + return 0; + stream->read(static_cast(pBuf), n); + return stream->gcount(); +} + // ReSharper disable once CppInconsistentNaming -Status MiniZ::compressFolder(QString zipFilePath, QString srcFolderPath, const QStringList& fileList) +Status MiniZ::compressFolder(QString zipFilePath, QString srcFolderPath, const QStringList& fileList, QString mimetype) { DebugDetails dd; dd << QString("Creating Zip %1 from folder %2").arg(zipFilePath, srcFolderPath); @@ -65,11 +75,26 @@ Status MiniZ::compressFolder(QString zipFilePath, QString srcFolderPath, const Q dd << QString("Miniz writer init failed: error %1, %2").arg(static_cast(err)).arg(mz_zip_get_error_string(err));; } + // Add special uncompressed mimetype file to help with the identification of projects + { + QByteArray mimeData = mimetype.toUtf8(); + std::stringstream mimeStream(mimeData.toStdString()); + ok = mz_zip_writer_add_read_buf_callback(mz, "mimetype", MiniZ::istreamReadCallback, &mimeStream, mimeData.length(), + 0, "", 0, MZ_NO_COMPRESSION, 0, 0, + 0, 0); + if (!ok) + { + mz_zip_error err = mz_zip_get_last_error(mz); + dd << QString("Cannot add mimetype: error %1").arg(static_cast(err)).arg(mz_zip_get_error_string(err)); + } + } + //qDebug() << "SrcFolder=" << srcFolderPath; for (const QString& filePath : fileList) { QString sRelativePath = filePath; sRelativePath.remove(srcFolderPath); + if (sRelativePath == "mimetype") continue; dd << QString("Add file to zip: ").append(sRelativePath); @@ -166,6 +191,7 @@ Status MiniZ::uncompressFolder(QString zipFilePath, QString destPath) if (!stat->m_is_directory) { + if (QString(stat->m_filename) == "mimetype") continue; QString sFullPath = baseDir.filePath(QString::fromUtf8(stat->m_filename)); dd << QString("Unzip file: ").append(sFullPath); bool b = QFileInfo(sFullPath).absoluteDir().mkpath("."); diff --git a/core_lib/src/qminiz.h b/core_lib/src/qminiz.h index 4627cfda62..9528b2f7cd 100644 --- a/core_lib/src/qminiz.h +++ b/core_lib/src/qminiz.h @@ -17,12 +17,14 @@ GNU General Public License for more details. #define QMINIZ_H #include +#include "miniz.h" #include "pencilerror.h" namespace MiniZ { bool isZip(const QString& sZipFilePath); - Status compressFolder(QString zipFilePath, QString srcFolderPath, const QStringList& fileList); + size_t istreamReadCallback(void *pOpaque, mz_uint64 file_ofs, void * pBuf, size_t n); + Status compressFolder(QString zipFilePath, QString srcFolderPath, const QStringList& fileList, QString mimetype); Status uncompressFolder(QString zipFilePath, QString destPath); } #endif diff --git a/core_lib/src/structure/filemanager.cpp b/core_lib/src/structure/filemanager.cpp index 8a7f88811f..de1a7f9111 100644 --- a/core_lib/src/structure/filemanager.cpp +++ b/core_lib/src/structure/filemanager.cpp @@ -317,7 +317,7 @@ Status FileManager::save(const Object* object, const QString& sFileName) QString sBackupFile = backupPreviousFile(sFileName); - Status stMiniz = MiniZ::compressFolder(sFileName, sTempWorkingFolder, filesToZip); + Status stMiniz = MiniZ::compressFolder(sFileName, sTempWorkingFolder, filesToZip, "application/x-pencil2d-pclx"); if (!stMiniz.ok()) { dd.collect(stMiniz.details());