├── .gitignore ├── CSGO-Toolbox.pro ├── CSGO-Toolbox.pro.user ├── CSGO-Toolbox.pro.user.a843b07 ├── LICENSE ├── README.md ├── dll.qrc ├── dll ├── SolveVAC.bat ├── boiler.exe ├── libShareCodeToURL.dll ├── libShareCodeToURLcs.dll ├── quazip.dll ├── quazipd.dll ├── steam_api.dll └── steam_appid.txt ├── img └── Loading.png ├── lib.qrc ├── lib ├── JlCompress.cpp ├── JlCompress.h ├── crypt.h ├── ioapi.h ├── qioapi.cpp ├── quaadler32.cpp ├── quaadler32.h ├── quachecksum32.h ├── quacrc32.cpp ├── quacrc32.h ├── quagzipfile.cpp ├── quagzipfile.h ├── quaziodevice.cpp ├── quaziodevice.h ├── quazip.cpp ├── quazip.h ├── quazip.lib ├── quazip.pro ├── quazip_global.h ├── quazipd.lib ├── quazipdir.cpp ├── quazipdir.h ├── quazipfile.cpp ├── quazipfile.h ├── quazipfileinfo.cpp ├── quazipfileinfo.h ├── quazipnewinfo.cpp ├── quazipnewinfo.h ├── unzip.c ├── unzip.h ├── zip.c └── zip.h ├── libShareCodeToURLcs.lib ├── logo.ico ├── logo.png ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui ├── qtconfig.qrc └── src.qrc /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /CSGO-Toolbox.pro: -------------------------------------------------------------------------------- 1 | QT += core gui 2 | 3 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 4 | 5 | CONFIG += c++11 6 | 7 | # The following define makes your compiler emit warnings if you use 8 | # any Qt feature that has been marked deprecated (the exact warnings 9 | # depend on your compiler). Please consult the documentation of the 10 | # deprecated API in order to know how to port your code away from it. 11 | DEFINES += QT_DEPRECATED_WARNINGS 12 | 13 | # You can also make your code fail to compile if it uses deprecated APIs. 14 | # In order to do so, uncomment the following line. 15 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 16 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 17 | 18 | SOURCES += \ 19 | main.cpp\ 20 | MainWindow.cpp 21 | 22 | HEADERS += \ 23 | MainWindow.h 24 | 25 | FORMS += \ 26 | MainWindow.ui 27 | 28 | # Default rules for deployment. 29 | qnx: target.path = /tmp/$${TARGET}/bin 30 | else: unix:!android: target.path = /opt/$${TARGET}/bin 31 | !isEmpty(target.path): INSTALLS += target 32 | 33 | DISTFILES += 34 | 35 | RESOURCES += \ 36 | dll.qrc \ 37 | lib.qrc \ 38 | src.qrc 39 | 40 | QMAKE_CXXFLAGS+=/execution-charset:utf-8 41 | 42 | RC_CODEPAGE = 65001 43 | 44 | VERSION = 1.0.3 45 | 46 | DEFINES += APP_VERSION=\\\"$$VERSION\\\" 47 | 48 | QMAKE_TARGET_PRODUCT = "CSGO ToolBox" 49 | QMAKE_PROJECT_NAME = "CSGO工具箱" 50 | 51 | RC_ICONS = logo.ico 52 | 53 | SUBDIRS += \ 54 | 55 | INCLUDEPATH += $$[QT_INSTALL_HEADERS]/QtZlib 56 | INCLUDEPATH += $$PWD/. 57 | DEPENDPATH += $$PWD/. 58 | 59 | win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lquazip 60 | else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lquazipd 61 | win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/lib/libquazip.a 62 | else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/lib/libquazipd.a 63 | else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/lib/quazip.lib 64 | else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/lib/quazipd.lib 65 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Purp1e 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 1. # CSGO工具箱 项目说明 2 | 3 | > Qt版项目已经搁置,正在使用Go+Wails+Vue重构。 4 | 5 | ## 一、CSGO工具箱介绍 6 | 7 | CSGO工具箱是旨在方便CSGO玩家调整、修改、保存、备份和转移设置等的工具性质的GUI程序,减少玩家在调整设置等事项上花费的时间,从而节省出更多的时间投入游戏本身。 8 | 9 | > CSGO Toolbox is dedicated to enabling CSGO players to modify their configs, game settings etc much more swiftly, thus more time is saved to put on game itself. 10 | 11 | ## 二、项目开发须知 12 | 13 | ### 1. 开发环境 14 | 15 | 本项目使用[Qt 5.14.0](http://download.qt.io/archive/qt/5.14/5.14.0/) + [MSVC 2017](ed2k://|file|en_visual_studio_community_2015_x86_dvd_6847364.iso|3965825024|6A7D8489BB2877E6BB8ACB2DD187B637|/) + [qt-vsaddin-msvc2017-2.4.3](http://download.qt.io/archive/vsaddin/2.4.3/) + Git,系统Win10 64位。如果需要参与开发,请配置好这些环境。 16 | 17 | 当前项目要用到一些外部文件,在`.dll/`中,需要手动将这些文件移动到`debug`或`release`文件夹中。 18 | 19 | ### 2. 参与开发 20 | 21 | 可联系邮箱`438518244@qq.com`,或者QQ群`759990621`,开发过程中需要用到[Git操作](https://www.jianshu.com/p/02cf41f38b6a),请提前备好相关知识。 22 | 23 | ### 3. 讨论&添加功能|特性须知 24 | 25 | 使用GitHub的[issues](https://github.com/Purple-CSGO/CSGO-Toolbox/issues)和[milestone](https://github.com/Purple-CSGO/CSGO-Toolbox/milestones)实现: 26 | 27 | 1. 有任何打算实现或者将要实现或者提议都发布在issues里,标题简述功能,内容详细说明,分成n条,管理者根据情况打上`将要实现`的标签。 28 | 2. 某功能相关建议或说明第一次提出时创建`milestone`,并将该issue加入。 29 | 3. 当开发者正在实现某功能时,标签改为`正在实现`。 30 | 4. 功能已经调试完成之后,标签改为`已实现`。 31 | 5. 功能完整加入程序中并确认无误之后,标签改为`已部署`,并关闭issue。 32 | -------------------------------------------------------------------------------- /dll.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | dll/boiler.exe 4 | dll/libShareCodeToURL.dll 5 | dll/libShareCodeToURLcs.dll 6 | dll/steam_api.dll 7 | dll/steam_appid.txt 8 | dll/quazipd.dll 9 | dll/quazip.dll 10 | 11 | 12 | -------------------------------------------------------------------------------- /dll/SolveVAC.bat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Purple-CSGO/CSGO-Toolbox-Qt/bf425be542e3173298e84675e41c75ab21ab1bed/dll/SolveVAC.bat -------------------------------------------------------------------------------- /dll/boiler.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Purple-CSGO/CSGO-Toolbox-Qt/bf425be542e3173298e84675e41c75ab21ab1bed/dll/boiler.exe -------------------------------------------------------------------------------- /dll/libShareCodeToURL.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Purple-CSGO/CSGO-Toolbox-Qt/bf425be542e3173298e84675e41c75ab21ab1bed/dll/libShareCodeToURL.dll -------------------------------------------------------------------------------- /dll/libShareCodeToURLcs.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Purple-CSGO/CSGO-Toolbox-Qt/bf425be542e3173298e84675e41c75ab21ab1bed/dll/libShareCodeToURLcs.dll -------------------------------------------------------------------------------- /dll/quazip.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Purple-CSGO/CSGO-Toolbox-Qt/bf425be542e3173298e84675e41c75ab21ab1bed/dll/quazip.dll -------------------------------------------------------------------------------- /dll/quazipd.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Purple-CSGO/CSGO-Toolbox-Qt/bf425be542e3173298e84675e41c75ab21ab1bed/dll/quazipd.dll -------------------------------------------------------------------------------- /dll/steam_api.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Purple-CSGO/CSGO-Toolbox-Qt/bf425be542e3173298e84675e41c75ab21ab1bed/dll/steam_api.dll -------------------------------------------------------------------------------- /dll/steam_appid.txt: -------------------------------------------------------------------------------- 1 | 730 -------------------------------------------------------------------------------- /img/Loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Purple-CSGO/CSGO-Toolbox-Qt/bf425be542e3173298e84675e41c75ab21ab1bed/img/Loading.png -------------------------------------------------------------------------------- /lib.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | libShareCodeToURLcs.lib 4 | 5 | 6 | 7 | 8 | lib/quazip.lib 9 | lib/quazipd.lib 10 | lib/crypt.h 11 | lib/ioapi.h 12 | lib/JlCompress.cpp 13 | lib/JlCompress.h 14 | lib/qioapi.cpp 15 | lib/quaadler32.cpp 16 | lib/quaadler32.h 17 | lib/quachecksum32.h 18 | lib/quacrc32.cpp 19 | lib/quacrc32.h 20 | lib/quagzipfile.cpp 21 | lib/quagzipfile.h 22 | lib/quaziodevice.cpp 23 | lib/quaziodevice.h 24 | lib/quazip.cpp 25 | lib/quazip.h 26 | lib/quazip.pro 27 | lib/quazip_global.h 28 | lib/quazipdir.cpp 29 | lib/quazipdir.h 30 | lib/quazipfile.cpp 31 | lib/quazipfile.h 32 | lib/quazipfileinfo.cpp 33 | lib/quazipfileinfo.h 34 | lib/quazipnewinfo.cpp 35 | lib/quazipnewinfo.h 36 | lib/unzip.c 37 | lib/unzip.h 38 | lib/zip.c 39 | lib/zip.h 40 | 41 | 42 | -------------------------------------------------------------------------------- /lib/JlCompress.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2010 Roberto Pompermaier 3 | Copyright (C) 2005-2014 Sergey A. Tachenov 4 | 5 | This file is part of QuaZIP. 6 | 7 | QuaZIP is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Lesser General Public License as published by 9 | the Free Software Foundation, either version 2.1 of the License, or 10 | (at your option) any later version. 11 | 12 | QuaZIP is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License 18 | along with QuaZIP. If not, see . 19 | 20 | See COPYING file for the full LGPL text. 21 | 22 | Original ZIP package is copyrighted by Gilles Vollant and contributors, 23 | see quazip/(un)zip.h files for details. Basically it's the zlib license. 24 | */ 25 | 26 | #include "JlCompress.h" 27 | #include 28 | 29 | static bool copyData(QIODevice &inFile, QIODevice &outFile) 30 | { 31 | while (!inFile.atEnd()) { 32 | char buf[4096]; 33 | qint64 readLen = inFile.read(buf, 4096); 34 | if (readLen <= 0) 35 | return false; 36 | if (outFile.write(buf, readLen) != readLen) 37 | return false; 38 | } 39 | return true; 40 | } 41 | 42 | bool JlCompress::compressFile(QuaZip* zip, QString fileName, QString fileDest) { 43 | // zip: oggetto dove aggiungere il file 44 | // fileName: nome del file reale 45 | // fileDest: nome del file all'interno del file compresso 46 | 47 | // Controllo l'apertura dello zip 48 | if (!zip) return false; 49 | if (zip->getMode()!=QuaZip::mdCreate && 50 | zip->getMode()!=QuaZip::mdAppend && 51 | zip->getMode()!=QuaZip::mdAdd) return false; 52 | 53 | // Apro il file originale 54 | QFile inFile; 55 | inFile.setFileName(fileName); 56 | if(!inFile.open(QIODevice::ReadOnly)) return false; 57 | 58 | // Apro il file risulato 59 | QuaZipFile outFile(zip); 60 | if(!outFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileDest, inFile.fileName()))) return false; 61 | 62 | // Copio i dati 63 | if (!copyData(inFile, outFile) || outFile.getZipError()!=UNZ_OK) { 64 | return false; 65 | } 66 | 67 | // Chiudo i file 68 | outFile.close(); 69 | if (outFile.getZipError()!=UNZ_OK) return false; 70 | inFile.close(); 71 | 72 | return true; 73 | } 74 | 75 | bool JlCompress::compressSubDir(QuaZip* zip, QString dir, QString origDir, bool recursive, QDir::Filters filters) { 76 | // zip: oggetto dove aggiungere il file 77 | // dir: cartella reale corrente 78 | // origDir: cartella reale originale 79 | // (path(dir)-path(origDir)) = path interno all'oggetto zip 80 | 81 | // Controllo l'apertura dello zip 82 | if (!zip) return false; 83 | if (zip->getMode()!=QuaZip::mdCreate && 84 | zip->getMode()!=QuaZip::mdAppend && 85 | zip->getMode()!=QuaZip::mdAdd) return false; 86 | 87 | // Controllo la cartella 88 | QDir directory(dir); 89 | if (!directory.exists()) return false; 90 | 91 | QDir origDirectory(origDir); 92 | if (dir != origDir) { 93 | QuaZipFile dirZipFile(zip); 94 | if (!dirZipFile.open(QIODevice::WriteOnly, 95 | QuaZipNewInfo(origDirectory.relativeFilePath(dir) + "/", dir), 0, 0, 0)) { 96 | return false; 97 | } 98 | dirZipFile.close(); 99 | } 100 | 101 | 102 | // Se comprimo anche le sotto cartelle 103 | if (recursive) { 104 | // Per ogni sotto cartella 105 | QFileInfoList files = directory.entryInfoList(QDir::AllDirs|QDir::NoDotAndDotDot|filters); 106 | Q_FOREACH (QFileInfo file, files) { 107 | // Comprimo la sotto cartella 108 | if(!compressSubDir(zip,file.absoluteFilePath(),origDir,recursive,filters)) return false; 109 | } 110 | } 111 | 112 | // Per ogni file nella cartella 113 | QFileInfoList files = directory.entryInfoList(QDir::Files|filters); 114 | Q_FOREACH (QFileInfo file, files) { 115 | // Se non e un file o e il file compresso che sto creando 116 | if(!file.isFile()||file.absoluteFilePath()==zip->getZipName()) continue; 117 | 118 | // Creo il nome relativo da usare all'interno del file compresso 119 | QString filename = origDirectory.relativeFilePath(file.absoluteFilePath()); 120 | 121 | // Comprimo il file 122 | if (!compressFile(zip,file.absoluteFilePath(),filename)) return false; 123 | } 124 | 125 | return true; 126 | } 127 | 128 | bool JlCompress::extractFile(QuaZip* zip, QString fileName, QString fileDest) { 129 | // zip: oggetto dove aggiungere il file 130 | // filename: nome del file reale 131 | // fileincompress: nome del file all'interno del file compresso 132 | 133 | // Controllo l'apertura dello zip 134 | if (!zip) return false; 135 | if (zip->getMode()!=QuaZip::mdUnzip) return false; 136 | 137 | // Apro il file compresso 138 | if (!fileName.isEmpty()) 139 | zip->setCurrentFile(fileName); 140 | QuaZipFile inFile(zip); 141 | if(!inFile.open(QIODevice::ReadOnly) || inFile.getZipError()!=UNZ_OK) return false; 142 | 143 | // Controllo esistenza cartella file risultato 144 | QDir curDir; 145 | if (fileDest.endsWith('/')) { 146 | if (!curDir.mkpath(fileDest)) { 147 | return false; 148 | } 149 | } else { 150 | if (!curDir.mkpath(QFileInfo(fileDest).absolutePath())) { 151 | return false; 152 | } 153 | } 154 | 155 | QuaZipFileInfo64 info; 156 | if (!zip->getCurrentFileInfo(&info)) 157 | return false; 158 | 159 | QFile::Permissions srcPerm = info.getPermissions(); 160 | if (fileDest.endsWith('/') && QFileInfo(fileDest).isDir()) { 161 | if (srcPerm != 0) { 162 | QFile(fileDest).setPermissions(srcPerm); 163 | } 164 | return true; 165 | } 166 | 167 | // Apro il file risultato 168 | QFile outFile; 169 | outFile.setFileName(fileDest); 170 | if(!outFile.open(QIODevice::WriteOnly)) return false; 171 | 172 | // Copio i dati 173 | if (!copyData(inFile, outFile) || inFile.getZipError()!=UNZ_OK) { 174 | outFile.close(); 175 | removeFile(QStringList(fileDest)); 176 | return false; 177 | } 178 | outFile.close(); 179 | 180 | // Chiudo i file 181 | inFile.close(); 182 | if (inFile.getZipError()!=UNZ_OK) { 183 | removeFile(QStringList(fileDest)); 184 | return false; 185 | } 186 | 187 | if (srcPerm != 0) { 188 | outFile.setPermissions(srcPerm); 189 | } 190 | return true; 191 | } 192 | 193 | bool JlCompress::removeFile(QStringList listFile) { 194 | bool ret = true; 195 | // Per ogni file 196 | for (int i=0; iopen(QuaZip::mdUnzip)) { 395 | delete zip; 396 | return QStringList(); 397 | } 398 | 399 | // Estraggo i nomi dei file 400 | QStringList lst; 401 | QuaZipFileInfo64 info; 402 | for(bool more=zip->goToFirstFile(); more; more=zip->goToNextFile()) { 403 | if(!zip->getCurrentFileInfo(&info)) { 404 | delete zip; 405 | return QStringList(); 406 | } 407 | lst << info.name; 408 | //info.name.toLocal8Bit().constData() 409 | } 410 | 411 | // Chiudo il file zip 412 | zip->close(); 413 | if(zip->getZipError()!=0) { 414 | delete zip; 415 | return QStringList(); 416 | } 417 | delete zip; 418 | return lst; 419 | } 420 | 421 | QStringList JlCompress::extractDir(QIODevice *ioDevice, QString dir) 422 | { 423 | QuaZip zip(ioDevice); 424 | return extractDir(zip, dir); 425 | } 426 | 427 | QStringList JlCompress::getFileList(QIODevice *ioDevice) 428 | { 429 | QuaZip *zip = new QuaZip(ioDevice); 430 | return getFileList(zip); 431 | } 432 | 433 | QString JlCompress::extractFile(QIODevice *ioDevice, QString fileName, QString fileDest) 434 | { 435 | QuaZip zip(ioDevice); 436 | return extractFile(zip, fileName, fileDest); 437 | } 438 | 439 | QStringList JlCompress::extractFiles(QIODevice *ioDevice, QStringList files, QString dir) 440 | { 441 | QuaZip zip(ioDevice); 442 | return extractFiles(zip, files, dir); 443 | } 444 | -------------------------------------------------------------------------------- /lib/JlCompress.h: -------------------------------------------------------------------------------- 1 | #ifndef JLCOMPRESSFOLDER_H_ 2 | #define JLCOMPRESSFOLDER_H_ 3 | 4 | /* 5 | Copyright (C) 2010 Roberto Pompermaier 6 | Copyright (C) 2005-2016 Sergey A. Tachenov 7 | 8 | This file is part of QuaZIP. 9 | 10 | QuaZIP is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU Lesser General Public License as published by 12 | the Free Software Foundation, either version 2.1 of the License, or 13 | (at your option) any later version. 14 | 15 | QuaZIP is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public License 21 | along with QuaZIP. If not, see . 22 | 23 | See COPYING file for the full LGPL text. 24 | 25 | Original ZIP package is copyrighted by Gilles Vollant and contributors, 26 | see quazip/(un)zip.h files for details. Basically it's the zlib license. 27 | */ 28 | 29 | #include "quazip.h" 30 | #include "quazipfile.h" 31 | #include "quazipfileinfo.h" 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | /// Utility class for typical operations. 38 | /** 39 | This class contains a number of useful static functions to perform 40 | simple operations, such as mass ZIP packing or extraction. 41 | */ 42 | class QUAZIP_EXPORT JlCompress { 43 | private: 44 | static QStringList extractDir(QuaZip &zip, const QString &dir); 45 | static QStringList getFileList(QuaZip *zip); 46 | static QString extractFile(QuaZip &zip, QString fileName, QString fileDest); 47 | static QStringList extractFiles(QuaZip &zip, const QStringList &files, const QString &dir); 48 | /// Compress a single file. 49 | /** 50 | \param zip Opened zip to compress the file to. 51 | \param fileName The full path to the source file. 52 | \param fileDest The full name of the file inside the archive. 53 | \return true if success, false otherwise. 54 | */ 55 | static bool compressFile(QuaZip* zip, QString fileName, QString fileDest); 56 | /// Compress a subdirectory. 57 | /** 58 | \param parentZip Opened zip containing the parent directory. 59 | \param dir The full path to the directory to pack. 60 | \param parentDir The full path to the directory corresponding to 61 | the root of the ZIP. 62 | \param recursive Whether to pack sub-directories as well or only 63 | files. 64 | \return true if success, false otherwise. 65 | */ 66 | static bool compressSubDir(QuaZip* parentZip, QString dir, QString parentDir, bool recursive, 67 | QDir::Filters filters); 68 | /// Extract a single file. 69 | /** 70 | \param zip The opened zip archive to extract from. 71 | \param fileName The full name of the file to extract. 72 | \param fileDest The full path to the destination file. 73 | \return true if success, false otherwise. 74 | */ 75 | static bool extractFile(QuaZip* zip, QString fileName, QString fileDest); 76 | /// Remove some files. 77 | /** 78 | \param listFile The list of files to remove. 79 | \return true if success, false otherwise. 80 | */ 81 | static bool removeFile(QStringList listFile); 82 | 83 | public: 84 | /// Compress a single file. 85 | /** 86 | \param fileCompressed The name of the archive. 87 | \param file The file to compress. 88 | \return true if success, false otherwise. 89 | */ 90 | static bool compressFile(QString fileCompressed, QString file); 91 | /// Compress a list of files. 92 | /** 93 | \param fileCompressed The name of the archive. 94 | \param files The file list to compress. 95 | \return true if success, false otherwise. 96 | */ 97 | static bool compressFiles(QString fileCompressed, QStringList files); 98 | /// Compress a whole directory. 99 | /** 100 | Does not compress hidden files. See compressDir(QString, QString, bool, QDir::Filters). 101 | 102 | \param fileCompressed The name of the archive. 103 | \param dir The directory to compress. 104 | \param recursive Whether to pack the subdirectories as well, or 105 | just regular files. 106 | \return true if success, false otherwise. 107 | */ 108 | static bool compressDir(QString fileCompressed, QString dir = QString(), bool recursive = true); 109 | /** 110 | * @brief Compress a whole directory. 111 | * 112 | * Unless filters are specified explicitly, packs 113 | * only regular non-hidden files (and subdirs, if @c recursive is true). 114 | * If filters are specified, they are OR-combined with 115 | * %QDir::AllDirs|%QDir::NoDotAndDotDot when searching for dirs 116 | * and with QDir::Files when searching for files. 117 | * 118 | * @param fileCompressed path to the resulting archive 119 | * @param dir path to the directory being compressed 120 | * @param recursive if true, then the subdirectories are packed as well 121 | * @param filters what to pack, filters are applied both when searching 122 | * for subdirs (if packing recursively) and when looking for files to pack 123 | * @return true on success, false otherwise 124 | */ 125 | static bool compressDir(QString fileCompressed, QString dir, 126 | bool recursive, QDir::Filters filters); 127 | 128 | public: 129 | /// Extract a single file. 130 | /** 131 | \param fileCompressed The name of the archive. 132 | \param fileName The file to extract. 133 | \param fileDest The destination file, assumed to be identical to 134 | \a file if left empty. 135 | \return The list of the full paths of the files extracted, empty on failure. 136 | */ 137 | static QString extractFile(QString fileCompressed, QString fileName, QString fileDest = QString()); 138 | /// Extract a list of files. 139 | /** 140 | \param fileCompressed The name of the archive. 141 | \param files The file list to extract. 142 | \param dir The directory to put the files to, the current 143 | directory if left empty. 144 | \return The list of the full paths of the files extracted, empty on failure. 145 | */ 146 | static QStringList extractFiles(QString fileCompressed, QStringList files, QString dir = QString()); 147 | /// Extract a whole archive. 148 | /** 149 | \param fileCompressed The name of the archive. 150 | \param dir The directory to extract to, the current directory if 151 | left empty. 152 | \return The list of the full paths of the files extracted, empty on failure. 153 | */ 154 | static QStringList extractDir(QString fileCompressed, QString dir = QString()); 155 | /// Get the file list. 156 | /** 157 | \return The list of the files in the archive, or, more precisely, the 158 | list of the entries, including both files and directories if they 159 | are present separately. 160 | */ 161 | static QStringList getFileList(QString fileCompressed); 162 | /// Extract a single file. 163 | /** 164 | \param ioDevice pointer to device with compressed data. 165 | \param fileName The file to extract. 166 | \param fileDest The destination file, assumed to be identical to 167 | \a file if left empty. 168 | \return The list of the full paths of the files extracted, empty on failure. 169 | */ 170 | static QString extractFile(QIODevice *ioDevice, QString fileName, QString fileDest = QString()); 171 | /// Extract a list of files. 172 | /** 173 | \param ioDevice pointer to device with compressed data. 174 | \param files The file list to extract. 175 | \param dir The directory to put the files to, the current 176 | directory if left empty. 177 | \return The list of the full paths of the files extracted, empty on failure. 178 | */ 179 | static QStringList extractFiles(QIODevice *ioDevice, QStringList files, QString dir = QString()); 180 | /// Extract a whole archive. 181 | /** 182 | \param ioDevice pointer to device with compressed data. 183 | \param dir The directory to extract to, the current directory if 184 | left empty. 185 | \return The list of the full paths of the files extracted, empty on failure. 186 | */ 187 | static QStringList extractDir(QIODevice *ioDevice, QString dir = QString()); 188 | /// Get the file list. 189 | /** 190 | \return The list of the files in the archive, or, more precisely, the 191 | list of the entries, including both files and directories if they 192 | are present separately. 193 | */ 194 | static QStringList getFileList(QIODevice *ioDevice); 195 | }; 196 | 197 | #endif /* JLCOMPRESSFOLDER_H_ */ 198 | -------------------------------------------------------------------------------- /lib/crypt.h: -------------------------------------------------------------------------------- 1 | /* crypt.h -- base code for crypt/uncrypt ZIPfile 2 | 3 | 4 | Version 1.01e, February 12th, 2005 5 | 6 | Copyright (C) 1998-2005 Gilles Vollant 7 | 8 | This code is a modified version of crypting code in Infozip distribution 9 | 10 | The encryption/decryption parts of this source code (as opposed to the 11 | non-echoing password parts) were originally written in Europe. The 12 | whole source package can be freely distributed, including from the USA. 13 | (Prior to January 2000, re-export from the US was a violation of US law.) 14 | 15 | This encryption code is a direct transcription of the algorithm from 16 | Roger Schlafly, described by Phil Katz in the file appnote.txt. This 17 | file (appnote.txt) is distributed with the PKZIP program (even in the 18 | version without encryption capabilities). 19 | 20 | If you don't need crypting in your application, just define symbols 21 | NOCRYPT and NOUNCRYPT. 22 | 23 | This code support the "Traditional PKWARE Encryption". 24 | 25 | The new AES encryption added on Zip format by Winzip (see the page 26 | http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong 27 | Encryption is not supported. 28 | */ 29 | 30 | #include "quazip_global.h" 31 | 32 | #define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) 33 | 34 | /*********************************************************************** 35 | * Return the next byte in the pseudo-random sequence 36 | */ 37 | static int decrypt_byte(unsigned long* pkeys, const z_crc_t FAR * pcrc_32_tab UNUSED) 38 | { 39 | //(void) pcrc_32_tab; /* avoid "unused parameter" warning */ 40 | unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an 41 | * unpredictable manner on 16-bit systems; not a problem 42 | * with any known compiler so far, though */ 43 | 44 | temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; 45 | return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); 46 | } 47 | 48 | /*********************************************************************** 49 | * Update the encryption keys with the next byte of plain text 50 | */ 51 | static int update_keys(unsigned long* pkeys,const z_crc_t FAR * pcrc_32_tab,int c) 52 | { 53 | (*(pkeys+0)) = CRC32((*(pkeys+0)), c); 54 | (*(pkeys+1)) += (*(pkeys+0)) & 0xff; 55 | (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; 56 | { 57 | register int keyshift = (int)((*(pkeys+1)) >> 24); 58 | (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); 59 | } 60 | return c; 61 | } 62 | 63 | 64 | /*********************************************************************** 65 | * Initialize the encryption keys and the random header according to 66 | * the given password. 67 | */ 68 | static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t FAR * pcrc_32_tab) 69 | { 70 | *(pkeys+0) = 305419896L; 71 | *(pkeys+1) = 591751049L; 72 | *(pkeys+2) = 878082192L; 73 | while (*passwd != '\0') { 74 | update_keys(pkeys,pcrc_32_tab,(int)*passwd); 75 | passwd++; 76 | } 77 | } 78 | 79 | #define zdecode(pkeys,pcrc_32_tab,c) \ 80 | (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) 81 | 82 | #define zencode(pkeys,pcrc_32_tab,c,t) \ 83 | (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) 84 | 85 | #ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED 86 | 87 | #define RAND_HEAD_LEN 12 88 | /* "last resort" source for second part of crypt seed pattern */ 89 | # ifndef ZCR_SEED2 90 | # define ZCR_SEED2 3141592654UL /* use PI as default pattern */ 91 | # endif 92 | 93 | static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting) 94 | const char *passwd; /* password string */ 95 | unsigned char *buf; /* where to write header */ 96 | int bufSize; 97 | unsigned long* pkeys; 98 | const z_crc_t FAR * pcrc_32_tab; 99 | unsigned long crcForCrypting; 100 | { 101 | int n; /* index in random header */ 102 | int t; /* temporary */ 103 | int c; /* random byte */ 104 | unsigned char header[RAND_HEAD_LEN-2]; /* random header */ 105 | static unsigned calls = 0; /* ensure different random header each time */ 106 | 107 | if (bufSize> 7) & 0xff; 122 | header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); 123 | } 124 | /* Encrypt random header (last two bytes is high word of crc) */ 125 | init_keys(passwd, pkeys, pcrc_32_tab); 126 | for (n = 0; n < RAND_HEAD_LEN-2; n++) 127 | { 128 | buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); 129 | } 130 | buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); 131 | buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); 132 | return n; 133 | } 134 | 135 | #endif 136 | -------------------------------------------------------------------------------- /lib/ioapi.h: -------------------------------------------------------------------------------- 1 | /* ioapi.h -- IO base function header for compress/uncompress .zip 2 | part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) 3 | 4 | Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) 5 | 6 | Modifications for Zip64 support 7 | Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) 8 | 9 | Modified by Sergey A. Tachenov to allow QIODevice API usage. 10 | 11 | For more info read MiniZip_info.txt 12 | 13 | Changes 14 | 15 | Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this) 16 | Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux. 17 | More if/def section may be needed to support other platforms 18 | Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows. 19 | (but you should use iowin32.c for windows instead) 20 | 21 | */ 22 | 23 | #ifndef _ZLIBIOAPI64_H 24 | #define _ZLIBIOAPI64_H 25 | 26 | #if (!defined(_WIN32)) && (!defined(WIN32)) 27 | 28 | // Linux needs this to support file operation on files larger then 4+GB 29 | // But might need better if/def to select just the platforms that needs them. 30 | 31 | #ifndef __USE_FILE_OFFSET64 32 | #define __USE_FILE_OFFSET64 33 | #endif 34 | #ifndef __USE_LARGEFILE64 35 | #define __USE_LARGEFILE64 36 | #endif 37 | #ifndef _LARGEFILE64_SOURCE 38 | #define _LARGEFILE64_SOURCE 39 | #endif 40 | #ifndef _FILE_OFFSET_BIT 41 | #define _FILE_OFFSET_BIT 64 42 | #endif 43 | #endif 44 | 45 | #include 46 | #include 47 | #include "zlib.h" 48 | 49 | #if defined(USE_FILE32API) 50 | #define fopen64 fopen 51 | #define ftello64 ftell 52 | #define fseeko64 fseek 53 | #else 54 | #ifdef _MSC_VER 55 | #define fopen64 fopen 56 | #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC))) 57 | #define ftello64 _ftelli64 58 | #define fseeko64 _fseeki64 59 | #else // old MSC 60 | #define ftello64 ftell 61 | #define fseeko64 fseek 62 | #endif 63 | #endif 64 | #endif 65 | 66 | /* 67 | #ifndef ZPOS64_T 68 | #ifdef _WIN32 69 | #define ZPOS64_T fpos_t 70 | #else 71 | #include 72 | #define ZPOS64_T uint64_t 73 | #endif 74 | #endif 75 | */ 76 | 77 | #ifdef HAVE_MINIZIP64_CONF_H 78 | #include "mz64conf.h" 79 | #endif 80 | 81 | /* a type choosen by DEFINE */ 82 | #ifdef HAVE_64BIT_INT_CUSTOM 83 | typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; 84 | #else 85 | #ifdef HAS_STDINT_H 86 | #include "stdint.h" 87 | typedef uint64_t ZPOS64_T; 88 | #else 89 | 90 | 91 | #if defined(_MSC_VER) || defined(__BORLANDC__) 92 | typedef unsigned __int64 ZPOS64_T; 93 | #else 94 | typedef unsigned long long int ZPOS64_T; 95 | #endif 96 | #endif 97 | #endif 98 | 99 | 100 | 101 | #ifdef __cplusplus 102 | extern "C" { 103 | #endif 104 | 105 | #ifndef OF 106 | #define OF _Z_OF 107 | #endif 108 | 109 | #define ZLIB_FILEFUNC_SEEK_CUR (1) 110 | #define ZLIB_FILEFUNC_SEEK_END (2) 111 | #define ZLIB_FILEFUNC_SEEK_SET (0) 112 | 113 | #define ZLIB_FILEFUNC_MODE_READ (1) 114 | #define ZLIB_FILEFUNC_MODE_WRITE (2) 115 | #define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) 116 | 117 | #define ZLIB_FILEFUNC_MODE_EXISTING (4) 118 | #define ZLIB_FILEFUNC_MODE_CREATE (8) 119 | 120 | 121 | #ifndef ZCALLBACK 122 | #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) 123 | #define ZCALLBACK CALLBACK 124 | #else 125 | #define ZCALLBACK 126 | #endif 127 | #endif 128 | 129 | 130 | 131 | 132 | typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, voidpf file, int mode)); 133 | typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); 134 | typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); 135 | typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); 136 | typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); 137 | 138 | typedef uLong (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); 139 | typedef int (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); 140 | 141 | 142 | /* here is the "old" 32 bits structure structure */ 143 | typedef struct zlib_filefunc_def_s 144 | { 145 | open_file_func zopen_file; 146 | read_file_func zread_file; 147 | write_file_func zwrite_file; 148 | tell_file_func ztell_file; 149 | seek_file_func zseek_file; 150 | close_file_func zclose_file; 151 | testerror_file_func zerror_file; 152 | voidpf opaque; 153 | } zlib_filefunc_def; 154 | 155 | typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); 156 | typedef int (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); 157 | typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, voidpf file, int mode)); 158 | 159 | typedef struct zlib_filefunc64_def_s 160 | { 161 | open64_file_func zopen64_file; 162 | read_file_func zread_file; 163 | write_file_func zwrite_file; 164 | tell64_file_func ztell64_file; 165 | seek64_file_func zseek64_file; 166 | close_file_func zclose_file; 167 | testerror_file_func zerror_file; 168 | voidpf opaque; 169 | close_file_func zfakeclose_file; // for no-auto-close flag 170 | } zlib_filefunc64_def; 171 | 172 | void fill_qiodevice64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); 173 | void fill_qiodevice_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); 174 | 175 | /* now internal definition, only for zip.c and unzip.h */ 176 | typedef struct zlib_filefunc64_32_def_s 177 | { 178 | zlib_filefunc64_def zfile_func64; 179 | open_file_func zopen32_file; 180 | tell_file_func ztell32_file; 181 | seek_file_func zseek32_file; 182 | } zlib_filefunc64_32_def; 183 | 184 | 185 | #define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) 186 | #define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) 187 | //#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) 188 | //#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) 189 | #define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) 190 | #define ZFAKECLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zfakeclose_file)) ((filefunc).zfile_func64.opaque,filestream)) 191 | #define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) 192 | 193 | voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf file,int mode)); 194 | int call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); 195 | ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); 196 | 197 | void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); 198 | 199 | #define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) 200 | #define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) 201 | #define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode))) 202 | 203 | #ifdef __cplusplus 204 | } 205 | #endif 206 | 207 | #endif 208 | -------------------------------------------------------------------------------- /lib/qioapi.cpp: -------------------------------------------------------------------------------- 1 | /* ioapi.c -- IO base function header for compress/uncompress .zip 2 | files using zlib + zip or unzip API 3 | 4 | Version 1.01e, February 12th, 2005 5 | 6 | Copyright (C) 1998-2005 Gilles Vollant 7 | 8 | Modified by Sergey A. Tachenov to integrate with Qt. 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include "zlib.h" 16 | #include "ioapi.h" 17 | #include "quazip_global.h" 18 | #include 19 | #if (QT_VERSION >= 0x050100) 20 | #define QUAZIP_QSAVEFILE_BUG_WORKAROUND 21 | #endif 22 | #ifdef QUAZIP_QSAVEFILE_BUG_WORKAROUND 23 | #include 24 | #endif 25 | 26 | /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ 27 | 28 | #ifndef SEEK_CUR 29 | #define SEEK_CUR 1 30 | #endif 31 | 32 | #ifndef SEEK_END 33 | #define SEEK_END 2 34 | #endif 35 | 36 | #ifndef SEEK_SET 37 | #define SEEK_SET 0 38 | #endif 39 | 40 | voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,voidpf file,int mode) 41 | { 42 | if (pfilefunc->zfile_func64.zopen64_file != NULL) 43 | return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,file,mode); 44 | else 45 | { 46 | return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,file,mode); 47 | } 48 | } 49 | 50 | int call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) 51 | { 52 | if (pfilefunc->zfile_func64.zseek64_file != NULL) 53 | return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); 54 | else 55 | { 56 | uLong offsetTruncated = (uLong)offset; 57 | if (offsetTruncated != offset) 58 | return -1; 59 | else 60 | return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin); 61 | } 62 | } 63 | 64 | ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) 65 | { 66 | if (pfilefunc->zfile_func64.zseek64_file != NULL) 67 | return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); 68 | else 69 | { 70 | uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream); 71 | if ((tell_uLong) == ((uLong)-1)) 72 | return (ZPOS64_T)-1; 73 | else 74 | return tell_uLong; 75 | } 76 | } 77 | 78 | /// @cond internal 79 | struct QIODevice_descriptor { 80 | // Position only used for writing to sequential devices. 81 | qint64 pos; 82 | inline QIODevice_descriptor(): 83 | pos(0) 84 | {} 85 | }; 86 | /// @endcond 87 | 88 | voidpf ZCALLBACK qiodevice_open_file_func ( 89 | voidpf opaque, 90 | voidpf file, 91 | int mode) 92 | { 93 | QIODevice_descriptor *d = reinterpret_cast(opaque); 94 | QIODevice *iodevice = reinterpret_cast(file); 95 | QIODevice::OpenMode desiredMode; 96 | if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) 97 | desiredMode = QIODevice::ReadOnly; 98 | else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) 99 | desiredMode = QIODevice::ReadWrite; 100 | else if (mode & ZLIB_FILEFUNC_MODE_CREATE) 101 | desiredMode = QIODevice::WriteOnly; 102 | if (iodevice->isOpen()) { 103 | if ((iodevice->openMode() & desiredMode) == desiredMode) { 104 | if (desiredMode != QIODevice::WriteOnly 105 | && iodevice->isSequential()) { 106 | // We can use sequential devices only for writing. 107 | delete d; 108 | return NULL; 109 | } else { 110 | if ((desiredMode & QIODevice::WriteOnly) != 0) { 111 | // open for writing, need to seek existing device 112 | if (!iodevice->isSequential()) { 113 | iodevice->seek(0); 114 | } else { 115 | d->pos = iodevice->pos(); 116 | } 117 | } 118 | } 119 | return iodevice; 120 | } else { 121 | delete d; 122 | return NULL; 123 | } 124 | } 125 | iodevice->open(desiredMode); 126 | if (iodevice->isOpen()) { 127 | if (desiredMode != QIODevice::WriteOnly && iodevice->isSequential()) { 128 | // We can use sequential devices only for writing. 129 | iodevice->close(); 130 | delete d; 131 | return NULL; 132 | } else { 133 | return iodevice; 134 | } 135 | } else { 136 | delete d; 137 | return NULL; 138 | } 139 | } 140 | 141 | 142 | uLong ZCALLBACK qiodevice_read_file_func ( 143 | voidpf opaque, 144 | voidpf stream, 145 | void* buf, 146 | uLong size) 147 | { 148 | QIODevice_descriptor *d = reinterpret_cast(opaque); 149 | QIODevice *iodevice = reinterpret_cast(stream); 150 | qint64 ret64 = iodevice->read((char*)buf,size); 151 | uLong ret; 152 | ret = (uLong) ret64; 153 | if (ret64 != -1) { 154 | d->pos += ret64; 155 | } 156 | return ret; 157 | } 158 | 159 | 160 | uLong ZCALLBACK qiodevice_write_file_func ( 161 | voidpf opaque, 162 | voidpf stream, 163 | const void* buf, 164 | uLong size) 165 | { 166 | QIODevice_descriptor *d = reinterpret_cast(opaque); 167 | QIODevice *iodevice = reinterpret_cast(stream); 168 | uLong ret; 169 | qint64 ret64 = iodevice->write((char*)buf,size); 170 | if (ret64 != -1) { 171 | d->pos += ret64; 172 | } 173 | ret = (uLong) ret64; 174 | return ret; 175 | } 176 | 177 | uLong ZCALLBACK qiodevice_tell_file_func ( 178 | voidpf opaque, 179 | voidpf stream) 180 | { 181 | QIODevice_descriptor *d = reinterpret_cast(opaque); 182 | QIODevice *iodevice = reinterpret_cast(stream); 183 | uLong ret; 184 | qint64 ret64; 185 | if (iodevice->isSequential()) { 186 | ret64 = d->pos; 187 | } else { 188 | ret64 = iodevice->pos(); 189 | } 190 | ret = static_cast(ret64); 191 | return ret; 192 | } 193 | 194 | ZPOS64_T ZCALLBACK qiodevice64_tell_file_func ( 195 | voidpf opaque, 196 | voidpf stream) 197 | { 198 | QIODevice_descriptor *d = reinterpret_cast(opaque); 199 | QIODevice *iodevice = reinterpret_cast(stream); 200 | qint64 ret; 201 | if (iodevice->isSequential()) { 202 | ret = d->pos; 203 | } else { 204 | ret = iodevice->pos(); 205 | } 206 | return static_cast(ret); 207 | } 208 | 209 | int ZCALLBACK qiodevice_seek_file_func ( 210 | voidpf /*opaque UNUSED*/, 211 | voidpf stream, 212 | uLong offset, 213 | int origin) 214 | { 215 | QIODevice *iodevice = reinterpret_cast(stream); 216 | if (iodevice->isSequential()) { 217 | if (origin == ZLIB_FILEFUNC_SEEK_END 218 | && offset == 0) { 219 | // sequential devices are always at end (needed in mdAppend) 220 | return 0; 221 | } else { 222 | qWarning("qiodevice_seek_file_func() called for sequential device"); 223 | return -1; 224 | } 225 | } 226 | uLong qiodevice_seek_result=0; 227 | int ret; 228 | switch (origin) 229 | { 230 | case ZLIB_FILEFUNC_SEEK_CUR : 231 | qiodevice_seek_result = ((QIODevice*)stream)->pos() + offset; 232 | break; 233 | case ZLIB_FILEFUNC_SEEK_END : 234 | qiodevice_seek_result = ((QIODevice*)stream)->size() - offset; 235 | break; 236 | case ZLIB_FILEFUNC_SEEK_SET : 237 | qiodevice_seek_result = offset; 238 | break; 239 | default: 240 | return -1; 241 | } 242 | ret = !iodevice->seek(qiodevice_seek_result); 243 | return ret; 244 | } 245 | 246 | int ZCALLBACK qiodevice64_seek_file_func ( 247 | voidpf /*opaque UNUSED*/, 248 | voidpf stream, 249 | ZPOS64_T offset, 250 | int origin) 251 | { 252 | QIODevice *iodevice = reinterpret_cast(stream); 253 | if (iodevice->isSequential()) { 254 | if (origin == ZLIB_FILEFUNC_SEEK_END 255 | && offset == 0) { 256 | // sequential devices are always at end (needed in mdAppend) 257 | return 0; 258 | } else { 259 | qWarning("qiodevice_seek_file_func() called for sequential device"); 260 | return -1; 261 | } 262 | } 263 | qint64 qiodevice_seek_result=0; 264 | int ret; 265 | switch (origin) 266 | { 267 | case ZLIB_FILEFUNC_SEEK_CUR : 268 | qiodevice_seek_result = ((QIODevice*)stream)->pos() + offset; 269 | break; 270 | case ZLIB_FILEFUNC_SEEK_END : 271 | qiodevice_seek_result = ((QIODevice*)stream)->size() - offset; 272 | break; 273 | case ZLIB_FILEFUNC_SEEK_SET : 274 | qiodevice_seek_result = offset; 275 | break; 276 | default: 277 | return -1; 278 | } 279 | ret = !iodevice->seek(qiodevice_seek_result); 280 | return ret; 281 | } 282 | 283 | int ZCALLBACK qiodevice_close_file_func ( 284 | voidpf opaque, 285 | voidpf stream) 286 | { 287 | QIODevice_descriptor *d = reinterpret_cast(opaque); 288 | delete d; 289 | QIODevice *device = reinterpret_cast(stream); 290 | #ifdef QUAZIP_QSAVEFILE_BUG_WORKAROUND 291 | // QSaveFile terribly breaks the is-a idiom: 292 | // it IS a QIODevice, but it is NOT compatible with it: close() is private 293 | QSaveFile *file = qobject_cast(device); 294 | if (file != NULL) { 295 | // We have to call the ugly commit() instead: 296 | return file->commit() ? 0 : -1; 297 | } 298 | #endif 299 | device->close(); 300 | return 0; 301 | } 302 | 303 | int ZCALLBACK qiodevice_fakeclose_file_func ( 304 | voidpf opaque, 305 | voidpf /*stream*/) 306 | { 307 | QIODevice_descriptor *d = reinterpret_cast(opaque); 308 | delete d; 309 | return 0; 310 | } 311 | 312 | int ZCALLBACK qiodevice_error_file_func ( 313 | voidpf /*opaque UNUSED*/, 314 | voidpf /*stream UNUSED*/) 315 | { 316 | // can't check for error due to the QIODevice API limitation 317 | return 0; 318 | } 319 | 320 | void fill_qiodevice_filefunc ( 321 | zlib_filefunc_def* pzlib_filefunc_def) 322 | { 323 | pzlib_filefunc_def->zopen_file = qiodevice_open_file_func; 324 | pzlib_filefunc_def->zread_file = qiodevice_read_file_func; 325 | pzlib_filefunc_def->zwrite_file = qiodevice_write_file_func; 326 | pzlib_filefunc_def->ztell_file = qiodevice_tell_file_func; 327 | pzlib_filefunc_def->zseek_file = qiodevice_seek_file_func; 328 | pzlib_filefunc_def->zclose_file = qiodevice_close_file_func; 329 | pzlib_filefunc_def->zerror_file = qiodevice_error_file_func; 330 | pzlib_filefunc_def->opaque = new QIODevice_descriptor; 331 | } 332 | 333 | void fill_qiodevice64_filefunc ( 334 | zlib_filefunc64_def* pzlib_filefunc_def) 335 | { 336 | // Open functions are the same for Qt. 337 | pzlib_filefunc_def->zopen64_file = qiodevice_open_file_func; 338 | pzlib_filefunc_def->zread_file = qiodevice_read_file_func; 339 | pzlib_filefunc_def->zwrite_file = qiodevice_write_file_func; 340 | pzlib_filefunc_def->ztell64_file = qiodevice64_tell_file_func; 341 | pzlib_filefunc_def->zseek64_file = qiodevice64_seek_file_func; 342 | pzlib_filefunc_def->zclose_file = qiodevice_close_file_func; 343 | pzlib_filefunc_def->zerror_file = qiodevice_error_file_func; 344 | pzlib_filefunc_def->opaque = new QIODevice_descriptor; 345 | pzlib_filefunc_def->zfakeclose_file = qiodevice_fakeclose_file_func; 346 | } 347 | 348 | void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) 349 | { 350 | p_filefunc64_32->zfile_func64.zopen64_file = NULL; 351 | p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; 352 | p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; 353 | p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; 354 | p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; 355 | p_filefunc64_32->zfile_func64.ztell64_file = NULL; 356 | p_filefunc64_32->zfile_func64.zseek64_file = NULL; 357 | p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file; 358 | p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; 359 | p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque; 360 | p_filefunc64_32->zfile_func64.zfakeclose_file = NULL; 361 | p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file; 362 | p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; 363 | } 364 | -------------------------------------------------------------------------------- /lib/quaadler32.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2010 Adam Walczak 3 | Copyright (C) 2005-2014 Sergey A. Tachenov 4 | 5 | This file is part of QuaZIP. 6 | 7 | QuaZIP is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Lesser General Public License as published by 9 | the Free Software Foundation, either version 2.1 of the License, or 10 | (at your option) any later version. 11 | 12 | QuaZIP is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License 18 | along with QuaZIP. If not, see . 19 | 20 | See COPYING file for the full LGPL text. 21 | 22 | Original ZIP package is copyrighted by Gilles Vollant and contributors, 23 | see quazip/(un)zip.h files for details. Basically it's the zlib license. 24 | */ 25 | 26 | #include "quaadler32.h" 27 | 28 | #include "zlib.h" 29 | 30 | QuaAdler32::QuaAdler32() 31 | { 32 | reset(); 33 | } 34 | 35 | quint32 QuaAdler32::calculate(const QByteArray &data) 36 | { 37 | return adler32( adler32(0L, Z_NULL, 0), (const Bytef*)data.data(), data.size() ); 38 | } 39 | 40 | void QuaAdler32::reset() 41 | { 42 | checksum = adler32(0L, Z_NULL, 0); 43 | } 44 | 45 | void QuaAdler32::update(const QByteArray &buf) 46 | { 47 | checksum = adler32( checksum, (const Bytef*)buf.data(), buf.size() ); 48 | } 49 | 50 | quint32 QuaAdler32::value() 51 | { 52 | return checksum; 53 | } 54 | -------------------------------------------------------------------------------- /lib/quaadler32.h: -------------------------------------------------------------------------------- 1 | #ifndef QUAADLER32_H 2 | #define QUAADLER32_H 3 | 4 | /* 5 | Copyright (C) 2010 Adam Walczak 6 | Copyright (C) 2005-2014 Sergey A. Tachenov 7 | 8 | This file is part of QuaZIP. 9 | 10 | QuaZIP is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU Lesser General Public License as published by 12 | the Free Software Foundation, either version 2.1 of the License, or 13 | (at your option) any later version. 14 | 15 | QuaZIP is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public License 21 | along with QuaZIP. If not, see . 22 | 23 | See COPYING file for the full LGPL text. 24 | 25 | Original ZIP package is copyrighted by Gilles Vollant and contributors, 26 | see quazip/(un)zip.h files for details. Basically it's the zlib license. 27 | */ 28 | 29 | #include 30 | 31 | #include "quachecksum32.h" 32 | 33 | /// Adler32 checksum 34 | /** \class QuaAdler32 quaadler32.h 35 | * This class wrappers the adler32 function with the QuaChecksum32 interface. 36 | * See QuaChecksum32 for more info. 37 | */ 38 | class QUAZIP_EXPORT QuaAdler32 : public QuaChecksum32 39 | { 40 | 41 | public: 42 | QuaAdler32(); 43 | 44 | quint32 calculate(const QByteArray &data); 45 | 46 | void reset(); 47 | void update(const QByteArray &buf); 48 | quint32 value(); 49 | 50 | private: 51 | quint32 checksum; 52 | }; 53 | 54 | #endif //QUAADLER32_H 55 | -------------------------------------------------------------------------------- /lib/quachecksum32.h: -------------------------------------------------------------------------------- 1 | #ifndef QUACHECKSUM32_H 2 | #define QUACHECKSUM32_H 3 | 4 | /* 5 | Copyright (C) 2005-2014 Sergey A. Tachenov 6 | 7 | This file is part of QuaZIP. 8 | 9 | QuaZIP is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU Lesser General Public License as published by 11 | the Free Software Foundation, either version 2.1 of the License, or 12 | (at your option) any later version. 13 | 14 | QuaZIP is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with QuaZIP. If not, see . 21 | 22 | See COPYING file for the full LGPL text. 23 | 24 | Original ZIP package is copyrighted by Gilles Vollant and contributors, 25 | see quazip/(un)zip.h files for details. Basically it's the zlib license. 26 | */ 27 | 28 | #include 29 | #include "quazip_global.h" 30 | 31 | /// Checksum interface. 32 | /** \class QuaChecksum32 quachecksum32.h 33 | * This is an interface for 32 bit checksums. 34 | * Classes implementing this interface can calcunate a certin 35 | * checksum in a single step: 36 | * \code 37 | * QChecksum32 *crc32 = new QuaCrc32(); 38 | * rasoult = crc32->calculate(data); 39 | * \endcode 40 | * or by streaming the data: 41 | * \code 42 | * QChecksum32 *crc32 = new QuaCrc32(); 43 | * while(!fileA.atEnd()) 44 | * crc32->update(fileA.read(bufSize)); 45 | * resoultA = crc32->value(); 46 | * crc32->reset(); 47 | * while(!fileB.atEnd()) 48 | * crc32->update(fileB.read(bufSize)); 49 | * resoultB = crc32->value(); 50 | * \endcode 51 | */ 52 | class QUAZIP_EXPORT QuaChecksum32 53 | { 54 | 55 | public: 56 | ///Calculates the checksum for data. 57 | /** \a data source data 58 | * \return data checksum 59 | * 60 | * This function has no efect on the value returned by value(). 61 | */ 62 | virtual quint32 calculate(const QByteArray &data) = 0; 63 | 64 | ///Resets the calculation on a checksun for a stream. 65 | virtual void reset() = 0; 66 | 67 | ///Updates the calculated checksum for the stream 68 | /** \a buf next portion of data from the stream 69 | */ 70 | virtual void update(const QByteArray &buf) = 0; 71 | 72 | ///Value of the checksum calculated for the stream passed throw update(). 73 | /** \return checksum 74 | */ 75 | virtual quint32 value() = 0; 76 | }; 77 | 78 | #endif //QUACHECKSUM32_H 79 | -------------------------------------------------------------------------------- /lib/quacrc32.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2005-2014 Sergey A. Tachenov 3 | 4 | This file is part of QuaZIP. 5 | 6 | QuaZIP is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | QuaZIP is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with QuaZIP. If not, see . 18 | 19 | See COPYING file for the full LGPL text. 20 | 21 | Original ZIP package is copyrighted by Gilles Vollant and contributors, 22 | see quazip/(un)zip.h files for details. Basically it's the zlib license. 23 | */ 24 | 25 | #include "quacrc32.h" 26 | 27 | #include "zlib.h" 28 | 29 | QuaCrc32::QuaCrc32() 30 | { 31 | reset(); 32 | } 33 | 34 | quint32 QuaCrc32::calculate(const QByteArray &data) 35 | { 36 | return crc32( crc32(0L, Z_NULL, 0), (const Bytef*)data.data(), data.size() ); 37 | } 38 | 39 | void QuaCrc32::reset() 40 | { 41 | checksum = crc32(0L, Z_NULL, 0); 42 | } 43 | 44 | void QuaCrc32::update(const QByteArray &buf) 45 | { 46 | checksum = crc32( checksum, (const Bytef*)buf.data(), buf.size() ); 47 | } 48 | 49 | quint32 QuaCrc32::value() 50 | { 51 | return checksum; 52 | } 53 | -------------------------------------------------------------------------------- /lib/quacrc32.h: -------------------------------------------------------------------------------- 1 | #ifndef QUACRC32_H 2 | #define QUACRC32_H 3 | 4 | /* 5 | Copyright (C) 2005-2014 Sergey A. Tachenov 6 | 7 | This file is part of QuaZIP. 8 | 9 | QuaZIP is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU Lesser General Public License as published by 11 | the Free Software Foundation, either version 2.1 of the License, or 12 | (at your option) any later version. 13 | 14 | QuaZIP is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with QuaZIP. If not, see . 21 | 22 | See COPYING file for the full LGPL text. 23 | 24 | Original ZIP package is copyrighted by Gilles Vollant and contributors, 25 | see quazip/(un)zip.h files for details. Basically it's the zlib license. 26 | */ 27 | 28 | #include "quachecksum32.h" 29 | 30 | ///CRC32 checksum 31 | /** \class QuaCrc32 quacrc32.h 32 | * This class wrappers the crc32 function with the QuaChecksum32 interface. 33 | * See QuaChecksum32 for more info. 34 | */ 35 | class QUAZIP_EXPORT QuaCrc32 : public QuaChecksum32 { 36 | 37 | public: 38 | QuaCrc32(); 39 | 40 | quint32 calculate(const QByteArray &data); 41 | 42 | void reset(); 43 | void update(const QByteArray &buf); 44 | quint32 value(); 45 | 46 | private: 47 | quint32 checksum; 48 | }; 49 | 50 | #endif //QUACRC32_H 51 | -------------------------------------------------------------------------------- /lib/quagzipfile.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2005-2014 Sergey A. Tachenov 3 | 4 | This file is part of QuaZIP. 5 | 6 | QuaZIP is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | QuaZIP is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with QuaZIP. If not, see . 18 | 19 | See COPYING file for the full LGPL text. 20 | 21 | Original ZIP package is copyrighted by Gilles Vollant and contributors, 22 | see quazip/(un)zip.h files for details. Basically it's the zlib license. 23 | */ 24 | 25 | #include 26 | 27 | #include "quagzipfile.h" 28 | 29 | /// \cond internal 30 | class QuaGzipFilePrivate { 31 | friend class QuaGzipFile; 32 | QString fileName; 33 | gzFile gzd; 34 | inline QuaGzipFilePrivate(): gzd(NULL) {} 35 | inline QuaGzipFilePrivate(const QString &fileName): 36 | fileName(fileName), gzd(NULL) {} 37 | template bool open(FileId id, 38 | QIODevice::OpenMode mode, QString &error); 39 | gzFile open(int fd, const char *modeString); 40 | gzFile open(const QString &name, const char *modeString); 41 | }; 42 | 43 | gzFile QuaGzipFilePrivate::open(const QString &name, const char *modeString) 44 | { 45 | return gzopen(QFile::encodeName(name).constData(), modeString); 46 | } 47 | 48 | gzFile QuaGzipFilePrivate::open(int fd, const char *modeString) 49 | { 50 | return gzdopen(fd, modeString); 51 | } 52 | 53 | template 54 | bool QuaGzipFilePrivate::open(FileId id, QIODevice::OpenMode mode, 55 | QString &error) 56 | { 57 | char modeString[2]; 58 | modeString[0] = modeString[1] = '\0'; 59 | if ((mode & QIODevice::Append) != 0) { 60 | error = QuaGzipFile::trUtf8("QIODevice::Append is not " 61 | "supported for GZIP"); 62 | return false; 63 | } 64 | if ((mode & QIODevice::ReadOnly) != 0 65 | && (mode & QIODevice::WriteOnly) != 0) { 66 | error = QuaGzipFile::trUtf8("Opening gzip for both reading" 67 | " and writing is not supported"); 68 | return false; 69 | } else if ((mode & QIODevice::ReadOnly) != 0) { 70 | modeString[0] = 'r'; 71 | } else if ((mode & QIODevice::WriteOnly) != 0) { 72 | modeString[0] = 'w'; 73 | } else { 74 | error = QuaGzipFile::trUtf8("You can open a gzip either for reading" 75 | " or for writing. Which is it?"); 76 | return false; 77 | } 78 | gzd = open(id, modeString); 79 | if (gzd == NULL) { 80 | error = QuaGzipFile::trUtf8("Could not gzopen() file"); 81 | return false; 82 | } 83 | return true; 84 | } 85 | /// \endcond 86 | 87 | QuaGzipFile::QuaGzipFile(): 88 | d(new QuaGzipFilePrivate()) 89 | { 90 | } 91 | 92 | QuaGzipFile::QuaGzipFile(QObject *parent): 93 | QIODevice(parent), 94 | d(new QuaGzipFilePrivate()) 95 | { 96 | } 97 | 98 | QuaGzipFile::QuaGzipFile(const QString &fileName, QObject *parent): 99 | QIODevice(parent), 100 | d(new QuaGzipFilePrivate(fileName)) 101 | { 102 | } 103 | 104 | QuaGzipFile::~QuaGzipFile() 105 | { 106 | if (isOpen()) { 107 | close(); 108 | } 109 | delete d; 110 | } 111 | 112 | void QuaGzipFile::setFileName(const QString& fileName) 113 | { 114 | d->fileName = fileName; 115 | } 116 | 117 | QString QuaGzipFile::getFileName() const 118 | { 119 | return d->fileName; 120 | } 121 | 122 | bool QuaGzipFile::isSequential() const 123 | { 124 | return true; 125 | } 126 | 127 | bool QuaGzipFile::open(QIODevice::OpenMode mode) 128 | { 129 | QString error; 130 | if (!d->open(d->fileName, mode, error)) { 131 | setErrorString(error); 132 | return false; 133 | } 134 | return QIODevice::open(mode); 135 | } 136 | 137 | bool QuaGzipFile::open(int fd, QIODevice::OpenMode mode) 138 | { 139 | QString error; 140 | if (!d->open(fd, mode, error)) { 141 | setErrorString(error); 142 | return false; 143 | } 144 | return QIODevice::open(mode); 145 | } 146 | 147 | bool QuaGzipFile::flush() 148 | { 149 | return gzflush(d->gzd, Z_SYNC_FLUSH) == Z_OK; 150 | } 151 | 152 | void QuaGzipFile::close() 153 | { 154 | QIODevice::close(); 155 | gzclose(d->gzd); 156 | } 157 | 158 | qint64 QuaGzipFile::readData(char *data, qint64 maxSize) 159 | { 160 | return gzread(d->gzd, (voidp)data, (unsigned)maxSize); 161 | } 162 | 163 | qint64 QuaGzipFile::writeData(const char *data, qint64 maxSize) 164 | { 165 | if (maxSize == 0) 166 | return 0; 167 | int written = gzwrite(d->gzd, (voidp)data, (unsigned)maxSize); 168 | if (written == 0) 169 | return -1; 170 | else 171 | return written; 172 | } 173 | -------------------------------------------------------------------------------- /lib/quagzipfile.h: -------------------------------------------------------------------------------- 1 | #ifndef QUAZIP_QUAGZIPFILE_H 2 | #define QUAZIP_QUAGZIPFILE_H 3 | 4 | /* 5 | Copyright (C) 2005-2014 Sergey A. Tachenov 6 | 7 | This file is part of QuaZIP. 8 | 9 | QuaZIP is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU Lesser General Public License as published by 11 | the Free Software Foundation, either version 2.1 of the License, or 12 | (at your option) any later version. 13 | 14 | QuaZIP is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with QuaZIP. If not, see . 21 | 22 | See COPYING file for the full LGPL text. 23 | 24 | Original ZIP package is copyrighted by Gilles Vollant and contributors, 25 | see quazip/(un)zip.h files for details. Basically it's the zlib license. 26 | */ 27 | 28 | #include 29 | #include "quazip_global.h" 30 | 31 | #include "zlib.h" 32 | 33 | class QuaGzipFilePrivate; 34 | 35 | /// GZIP file 36 | /** 37 | This class is a wrapper around GZIP file access functions in zlib. Unlike QuaZip classes, it doesn't allow reading from a GZIP file opened as QIODevice, for example, if your GZIP file is in QBuffer. It only provides QIODevice access to a GZIP file contents, but the GZIP file itself must be identified by its name on disk or by descriptor id. 38 | */ 39 | class QUAZIP_EXPORT QuaGzipFile: public QIODevice { 40 | Q_OBJECT 41 | public: 42 | /// Empty constructor. 43 | /** 44 | Must call setFileName() before trying to open. 45 | */ 46 | QuaGzipFile(); 47 | /// Empty constructor with a parent. 48 | /** 49 | Must call setFileName() before trying to open. 50 | \param parent The parent object, as per QObject logic. 51 | */ 52 | QuaGzipFile(QObject *parent); 53 | /// Constructor. 54 | /** 55 | \param fileName The name of the GZIP file. 56 | \param parent The parent object, as per QObject logic. 57 | */ 58 | QuaGzipFile(const QString &fileName, QObject *parent = NULL); 59 | /// Destructor. 60 | virtual ~QuaGzipFile(); 61 | /// Sets the name of the GZIP file to be opened. 62 | void setFileName(const QString& fileName); 63 | /// Returns the name of the GZIP file. 64 | QString getFileName() const; 65 | /// Returns true. 66 | /** 67 | Strictly speaking, zlib supports seeking for GZIP files, but it is 68 | poorly implemented, because there is no way to implement it 69 | properly. For reading, seeking backwards is very slow, and for 70 | writing, it is downright impossible. Therefore, QuaGzipFile does not 71 | support seeking at all. 72 | */ 73 | virtual bool isSequential() const; 74 | /// Opens the file. 75 | /** 76 | \param mode Can be either QIODevice::Write or QIODevice::Read. 77 | ReadWrite and Append aren't supported. 78 | */ 79 | virtual bool open(QIODevice::OpenMode mode); 80 | /// Opens the file. 81 | /** 82 | \overload 83 | \param fd The file descriptor to read/write the GZIP file from/to. 84 | \param mode Can be either QIODevice::Write or QIODevice::Read. 85 | ReadWrite and Append aren't supported. 86 | */ 87 | virtual bool open(int fd, QIODevice::OpenMode mode); 88 | /// Flushes data to file. 89 | /** 90 | The data is written using Z_SYNC_FLUSH mode. Doesn't make any sense 91 | when reading. 92 | */ 93 | virtual bool flush(); 94 | /// Closes the file. 95 | virtual void close(); 96 | protected: 97 | /// Implementation of QIODevice::readData(). 98 | virtual qint64 readData(char *data, qint64 maxSize); 99 | /// Implementation of QIODevice::writeData(). 100 | virtual qint64 writeData(const char *data, qint64 maxSize); 101 | private: 102 | // not implemented by design to disable copy 103 | QuaGzipFile(const QuaGzipFile &that); 104 | QuaGzipFile& operator=(const QuaGzipFile &that); 105 | QuaGzipFilePrivate *d; 106 | }; 107 | 108 | #endif // QUAZIP_QUAGZIPFILE_H 109 | -------------------------------------------------------------------------------- /lib/quaziodevice.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2005-2014 Sergey A. Tachenov 3 | 4 | This file is part of QuaZIP. 5 | 6 | QuaZIP is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | QuaZIP is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with QuaZIP. If not, see . 18 | 19 | See COPYING file for the full LGPL text. 20 | 21 | Original ZIP package is copyrighted by Gilles Vollant and contributors, 22 | see quazip/(un)zip.h files for details. Basically it's the zlib license. 23 | */ 24 | 25 | #include "quaziodevice.h" 26 | 27 | #define QUAZIO_INBUFSIZE 4096 28 | #define QUAZIO_OUTBUFSIZE 4096 29 | 30 | /// \cond internal 31 | class QuaZIODevicePrivate { 32 | friend class QuaZIODevice; 33 | QuaZIODevicePrivate(QIODevice *io); 34 | ~QuaZIODevicePrivate(); 35 | QIODevice *io; 36 | z_stream zins; 37 | z_stream zouts; 38 | char *inBuf; 39 | int inBufPos; 40 | int inBufSize; 41 | char *outBuf; 42 | int outBufPos; 43 | int outBufSize; 44 | bool zBufError; 45 | bool atEnd; 46 | int doFlush(QString &error); 47 | }; 48 | 49 | QuaZIODevicePrivate::QuaZIODevicePrivate(QIODevice *io): 50 | io(io), 51 | inBuf(NULL), 52 | inBufPos(0), 53 | inBufSize(0), 54 | outBuf(NULL), 55 | outBufPos(0), 56 | outBufSize(0), 57 | zBufError(false), 58 | atEnd(false) 59 | { 60 | zins.zalloc = (alloc_func) NULL; 61 | zins.zfree = (free_func) NULL; 62 | zins.opaque = NULL; 63 | zouts.zalloc = (alloc_func) NULL; 64 | zouts.zfree = (free_func) NULL; 65 | zouts.opaque = NULL; 66 | inBuf = new char[QUAZIO_INBUFSIZE]; 67 | outBuf = new char[QUAZIO_OUTBUFSIZE]; 68 | #ifdef QUAZIP_ZIODEVICE_DEBUG_OUTPUT 69 | debug.setFileName("debug.out"); 70 | debug.open(QIODevice::WriteOnly); 71 | #endif 72 | #ifdef QUAZIP_ZIODEVICE_DEBUG_INPUT 73 | indebug.setFileName("debug.in"); 74 | indebug.open(QIODevice::WriteOnly); 75 | #endif 76 | } 77 | 78 | QuaZIODevicePrivate::~QuaZIODevicePrivate() 79 | { 80 | #ifdef QUAZIP_ZIODEVICE_DEBUG_OUTPUT 81 | debug.close(); 82 | #endif 83 | #ifdef QUAZIP_ZIODEVICE_DEBUG_INPUT 84 | indebug.close(); 85 | #endif 86 | if (inBuf != NULL) 87 | delete[] inBuf; 88 | if (outBuf != NULL) 89 | delete[] outBuf; 90 | } 91 | 92 | int QuaZIODevicePrivate::doFlush(QString &error) 93 | { 94 | int flushed = 0; 95 | while (outBufPos < outBufSize) { 96 | int more = io->write(outBuf + outBufPos, outBufSize - outBufPos); 97 | if (more == -1) { 98 | error = io->errorString(); 99 | return -1; 100 | } 101 | if (more == 0) 102 | break; 103 | outBufPos += more; 104 | flushed += more; 105 | } 106 | if (outBufPos == outBufSize) { 107 | outBufPos = outBufSize = 0; 108 | } 109 | return flushed; 110 | } 111 | 112 | /// \endcond 113 | 114 | // #define QUAZIP_ZIODEVICE_DEBUG_OUTPUT 115 | // #define QUAZIP_ZIODEVICE_DEBUG_INPUT 116 | #ifdef QUAZIP_ZIODEVICE_DEBUG_OUTPUT 117 | #include 118 | static QFile debug; 119 | #endif 120 | #ifdef QUAZIP_ZIODEVICE_DEBUG_INPUT 121 | #include 122 | static QFile indebug; 123 | #endif 124 | 125 | QuaZIODevice::QuaZIODevice(QIODevice *io, QObject *parent): 126 | QIODevice(parent), 127 | d(new QuaZIODevicePrivate(io)) 128 | { 129 | connect(io, SIGNAL(readyRead()), SIGNAL(readyRead())); 130 | } 131 | 132 | QuaZIODevice::~QuaZIODevice() 133 | { 134 | if (isOpen()) 135 | close(); 136 | delete d; 137 | } 138 | 139 | QIODevice *QuaZIODevice::getIoDevice() const 140 | { 141 | return d->io; 142 | } 143 | 144 | bool QuaZIODevice::open(QIODevice::OpenMode mode) 145 | { 146 | if ((mode & QIODevice::Append) != 0) { 147 | setErrorString(trUtf8("QIODevice::Append is not supported for" 148 | " QuaZIODevice")); 149 | return false; 150 | } 151 | if ((mode & QIODevice::ReadWrite) == QIODevice::ReadWrite) { 152 | setErrorString(trUtf8("QIODevice::ReadWrite is not supported for" 153 | " QuaZIODevice")); 154 | return false; 155 | } 156 | if ((mode & QIODevice::ReadOnly) != 0) { 157 | if (inflateInit(&d->zins) != Z_OK) { 158 | setErrorString(d->zins.msg); 159 | return false; 160 | } 161 | } 162 | if ((mode & QIODevice::WriteOnly) != 0) { 163 | if (deflateInit(&d->zouts, Z_DEFAULT_COMPRESSION) != Z_OK) { 164 | setErrorString(d->zouts.msg); 165 | return false; 166 | } 167 | } 168 | return QIODevice::open(mode); 169 | } 170 | 171 | void QuaZIODevice::close() 172 | { 173 | if ((openMode() & QIODevice::ReadOnly) != 0) { 174 | if (inflateEnd(&d->zins) != Z_OK) { 175 | setErrorString(d->zins.msg); 176 | } 177 | } 178 | if ((openMode() & QIODevice::WriteOnly) != 0) { 179 | flush(); 180 | if (deflateEnd(&d->zouts) != Z_OK) { 181 | setErrorString(d->zouts.msg); 182 | } 183 | } 184 | QIODevice::close(); 185 | } 186 | 187 | qint64 QuaZIODevice::readData(char *data, qint64 maxSize) 188 | { 189 | int read = 0; 190 | while (read < maxSize) { 191 | if (d->inBufPos == d->inBufSize) { 192 | d->inBufPos = 0; 193 | d->inBufSize = d->io->read(d->inBuf, QUAZIO_INBUFSIZE); 194 | if (d->inBufSize == -1) { 195 | d->inBufSize = 0; 196 | setErrorString(d->io->errorString()); 197 | return -1; 198 | } 199 | if (d->inBufSize == 0) 200 | break; 201 | } 202 | while (read < maxSize && d->inBufPos < d->inBufSize) { 203 | d->zins.next_in = (Bytef *) (d->inBuf + d->inBufPos); 204 | d->zins.avail_in = d->inBufSize - d->inBufPos; 205 | d->zins.next_out = (Bytef *) (data + read); 206 | d->zins.avail_out = (uInt) (maxSize - read); // hope it's less than 2GB 207 | int more = 0; 208 | switch (inflate(&d->zins, Z_SYNC_FLUSH)) { 209 | case Z_OK: 210 | read = (char *) d->zins.next_out - data; 211 | d->inBufPos = (char *) d->zins.next_in - d->inBuf; 212 | break; 213 | case Z_STREAM_END: 214 | read = (char *) d->zins.next_out - data; 215 | d->inBufPos = (char *) d->zins.next_in - d->inBuf; 216 | d->atEnd = true; 217 | return read; 218 | case Z_BUF_ERROR: // this should never happen, but just in case 219 | if (!d->zBufError) { 220 | qWarning("Z_BUF_ERROR detected with %d/%d in/out, weird", 221 | d->zins.avail_in, d->zins.avail_out); 222 | d->zBufError = true; 223 | } 224 | memmove(d->inBuf, d->inBuf + d->inBufPos, d->inBufSize - d->inBufPos); 225 | d->inBufSize -= d->inBufPos; 226 | d->inBufPos = 0; 227 | more = d->io->read(d->inBuf + d->inBufSize, QUAZIO_INBUFSIZE - d->inBufSize); 228 | if (more == -1) { 229 | setErrorString(d->io->errorString()); 230 | return -1; 231 | } 232 | if (more == 0) 233 | return read; 234 | d->inBufSize += more; 235 | break; 236 | default: 237 | setErrorString(QString::fromLocal8Bit(d->zins.msg)); 238 | return -1; 239 | } 240 | } 241 | } 242 | #ifdef QUAZIP_ZIODEVICE_DEBUG_INPUT 243 | indebug.write(data, read); 244 | #endif 245 | return read; 246 | } 247 | 248 | qint64 QuaZIODevice::writeData(const char *data, qint64 maxSize) 249 | { 250 | int written = 0; 251 | QString error; 252 | if (d->doFlush(error) == -1) { 253 | setErrorString(error); 254 | return -1; 255 | } 256 | while (written < maxSize) { 257 | // there is some data waiting in the output buffer 258 | if (d->outBufPos < d->outBufSize) 259 | return written; 260 | d->zouts.next_in = (Bytef *) (data + written); 261 | d->zouts.avail_in = (uInt) (maxSize - written); // hope it's less than 2GB 262 | d->zouts.next_out = (Bytef *) d->outBuf; 263 | d->zouts.avail_out = QUAZIO_OUTBUFSIZE; 264 | switch (deflate(&d->zouts, Z_NO_FLUSH)) { 265 | case Z_OK: 266 | written = (char *) d->zouts.next_in - data; 267 | d->outBufSize = (char *) d->zouts.next_out - d->outBuf; 268 | break; 269 | default: 270 | setErrorString(QString::fromLocal8Bit(d->zouts.msg)); 271 | return -1; 272 | } 273 | if (d->doFlush(error) == -1) { 274 | setErrorString(error); 275 | return -1; 276 | } 277 | } 278 | #ifdef QUAZIP_ZIODEVICE_DEBUG_OUTPUT 279 | debug.write(data, written); 280 | #endif 281 | return written; 282 | } 283 | 284 | bool QuaZIODevice::flush() 285 | { 286 | QString error; 287 | if (d->doFlush(error) < 0) { 288 | setErrorString(error); 289 | return false; 290 | } 291 | // can't flush buffer, some data is still waiting 292 | if (d->outBufPos < d->outBufSize) 293 | return true; 294 | Bytef c = 0; 295 | d->zouts.next_in = &c; // fake input buffer 296 | d->zouts.avail_in = 0; // of zero size 297 | do { 298 | d->zouts.next_out = (Bytef *) d->outBuf; 299 | d->zouts.avail_out = QUAZIO_OUTBUFSIZE; 300 | switch (deflate(&d->zouts, Z_SYNC_FLUSH)) { 301 | case Z_OK: 302 | d->outBufSize = (char *) d->zouts.next_out - d->outBuf; 303 | if (d->doFlush(error) < 0) { 304 | setErrorString(error); 305 | return false; 306 | } 307 | if (d->outBufPos < d->outBufSize) 308 | return true; 309 | break; 310 | case Z_BUF_ERROR: // nothing to write? 311 | return true; 312 | default: 313 | setErrorString(QString::fromLocal8Bit(d->zouts.msg)); 314 | return false; 315 | } 316 | } while (d->zouts.avail_out == 0); 317 | return true; 318 | } 319 | 320 | bool QuaZIODevice::isSequential() const 321 | { 322 | return true; 323 | } 324 | 325 | bool QuaZIODevice::atEnd() const 326 | { 327 | // Here we MUST check QIODevice::bytesAvailable() because WE 328 | // might have reached the end, but QIODevice didn't-- 329 | // it could have simply pre-buffered all remaining data. 330 | return (openMode() == NotOpen) || (QIODevice::bytesAvailable() == 0 && d->atEnd); 331 | } 332 | 333 | qint64 QuaZIODevice::bytesAvailable() const 334 | { 335 | // If we haven't recevied Z_STREAM_END, it means that 336 | // we have at least one more input byte available. 337 | // Plus whatever QIODevice has buffered. 338 | return (d->atEnd ? 0 : 1) + QIODevice::bytesAvailable(); 339 | } 340 | -------------------------------------------------------------------------------- /lib/quaziodevice.h: -------------------------------------------------------------------------------- 1 | #ifndef QUAZIP_QUAZIODEVICE_H 2 | #define QUAZIP_QUAZIODEVICE_H 3 | 4 | /* 5 | Copyright (C) 2005-2014 Sergey A. Tachenov 6 | 7 | This file is part of QuaZIP. 8 | 9 | QuaZIP is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU Lesser General Public License as published by 11 | the Free Software Foundation, either version 2.1 of the License, or 12 | (at your option) any later version. 13 | 14 | QuaZIP is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with QuaZIP. If not, see . 21 | 22 | See COPYING file for the full LGPL text. 23 | 24 | Original ZIP package is copyrighted by Gilles Vollant and contributors, 25 | see quazip/(un)zip.h files for details. Basically it's the zlib license. 26 | */ 27 | 28 | #include 29 | #include "quazip_global.h" 30 | 31 | #include "zlib.h" 32 | 33 | class QuaZIODevicePrivate; 34 | 35 | /// A class to compress/decompress QIODevice. 36 | /** 37 | This class can be used to compress any data written to QIODevice or 38 | decompress it back. Compressing data sent over a QTcpSocket is a good 39 | example. 40 | */ 41 | class QUAZIP_EXPORT QuaZIODevice: public QIODevice { 42 | Q_OBJECT 43 | public: 44 | /// Constructor. 45 | /** 46 | \param io The QIODevice to read/write. 47 | \param parent The parent object, as per QObject logic. 48 | */ 49 | QuaZIODevice(QIODevice *io, QObject *parent = NULL); 50 | /// Destructor. 51 | ~QuaZIODevice(); 52 | /// Flushes data waiting to be written. 53 | /** 54 | Unfortunately, as QIODevice doesn't support flush() by itself, the 55 | only thing this method does is write the compressed data into the 56 | device using Z_SYNC_FLUSH mode. If you need the compressed data to 57 | actually be flushed from the buffer of the underlying QIODevice, you 58 | need to call its flush() method as well, providing it supports it 59 | (like QTcpSocket does). Example: 60 | \code 61 | QuaZIODevice dev(&sock); 62 | dev.open(QIODevice::Write); 63 | dev.write(yourDataGoesHere); 64 | dev.flush(); 65 | sock->flush(); // this actually sends data to network 66 | \endcode 67 | 68 | This may change in the future versions of QuaZIP by implementing an 69 | ugly hack: trying to cast the QIODevice using qobject_cast to known 70 | flush()-supporting subclasses, and calling flush if the resulting 71 | pointer is not zero. 72 | */ 73 | virtual bool flush(); 74 | /// Opens the device. 75 | /** 76 | \param mode Neither QIODevice::ReadWrite nor QIODevice::Append are 77 | not supported. 78 | */ 79 | virtual bool open(QIODevice::OpenMode mode); 80 | /// Closes this device, but not the underlying one. 81 | /** 82 | The underlying QIODevice is not closed in case you want to write 83 | something else to it. 84 | */ 85 | virtual void close(); 86 | /// Returns the underlying device. 87 | QIODevice *getIoDevice() const; 88 | /// Returns true. 89 | virtual bool isSequential() const; 90 | /// Returns true iff the end of the compressed stream is reached. 91 | virtual bool atEnd() const; 92 | /// Returns the number of the bytes buffered. 93 | virtual qint64 bytesAvailable() const; 94 | protected: 95 | /// Implementation of QIODevice::readData(). 96 | virtual qint64 readData(char *data, qint64 maxSize); 97 | /// Implementation of QIODevice::writeData(). 98 | virtual qint64 writeData(const char *data, qint64 maxSize); 99 | private: 100 | QuaZIODevicePrivate *d; 101 | }; 102 | #endif // QUAZIP_QUAZIODEVICE_H 103 | -------------------------------------------------------------------------------- /lib/quazip.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Purple-CSGO/CSGO-Toolbox-Qt/bf425be542e3173298e84675e41c75ab21ab1bed/lib/quazip.lib -------------------------------------------------------------------------------- /lib/quazip.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = lib 2 | CONFIG += qt warn_on 3 | QT -= gui 4 | 5 | # The ABI version. 6 | 7 | !win32:VERSION = 1.0.0 8 | 9 | # 1.0.0 is the first stable ABI. 10 | # The next binary incompatible change will be 2.0.0 and so on. 11 | # The existing QuaZIP policy on changing ABI requires to bump the 12 | # major version of QuaZIP itself as well. Note that there may be 13 | # other reasons for chaging the major version of QuaZIP, so 14 | # in case where there is a QuaZIP major version bump but no ABI change, 15 | # the VERSION variable will stay the same. 16 | 17 | # For example: 18 | 19 | # QuaZIP 1.0 is released after some 0.x, keeping binary compatibility. 20 | # VERSION stays 1.0.0. 21 | # Then some binary incompatible change is introduced. QuaZIP goes up to 22 | # 2.0, VERSION to 2.0.0. 23 | # And so on. 24 | 25 | 26 | # This one handles dllimport/dllexport directives. 27 | DEFINES += QUAZIP_BUILD 28 | 29 | # You'll need to define this one manually if using a build system other 30 | # than qmake or using QuaZIP sources directly in your project. 31 | CONFIG(staticlib): DEFINES += QUAZIP_STATIC 32 | 33 | # Input 34 | include(quazip.pri) 35 | 36 | 37 | CONFIG(debug, debug|release) { 38 | mac: TARGET = $$join(TARGET,,,_debug) 39 | win32: TARGET = $$join(TARGET,,,d) 40 | } 41 | 42 | unix:!symbian { 43 | headers.path=$$PREFIX/include/quazip 44 | headers.files=$$HEADERS 45 | target.path=$$PREFIX/lib/$${LIB_ARCH} 46 | INSTALLS += headers target 47 | 48 | OBJECTS_DIR=.obj 49 | MOC_DIR=.moc 50 | 51 | } 52 | 53 | win32 { 54 | headers.path=$$PREFIX/include/quazip 55 | headers.files=$$HEADERS 56 | target.path=$$PREFIX/lib 57 | INSTALLS += headers target 58 | # workaround for qdatetime.h macro bug 59 | DEFINES += NOMINMAX 60 | } 61 | 62 | 63 | symbian { 64 | 65 | # Note, on Symbian you may run into troubles with LGPL. 66 | # The point is, if your application uses some version of QuaZip, 67 | # and a newer binary compatible version of QuaZip is released, then 68 | # the users of your application must be able to relink it with the 69 | # new QuaZip version. For example, to take advantage of some QuaZip 70 | # bug fixes. 71 | 72 | # This is probably best achieved by building QuaZip as a static 73 | # library and providing linkable object files of your application, 74 | # so users can relink it. 75 | 76 | CONFIG += staticlib 77 | CONFIG += debug_and_release 78 | 79 | LIBS += -lezip 80 | 81 | #Export headers to SDK Epoc32/include directory 82 | exportheaders.sources = $$HEADERS 83 | exportheaders.path = quazip 84 | for(header, exportheaders.sources) { 85 | BLD_INF_RULES.prj_exports += "$$header $$exportheaders.path/$$basename(header)" 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /lib/quazip_global.h: -------------------------------------------------------------------------------- 1 | #ifndef QUAZIP_GLOBAL_H 2 | #define QUAZIP_GLOBAL_H 3 | 4 | /* 5 | Copyright (C) 2005-2014 Sergey A. Tachenov 6 | 7 | This file is part of QuaZIP. 8 | 9 | QuaZIP is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU Lesser General Public License as published by 11 | the Free Software Foundation, either version 2.1 of the License, or 12 | (at your option) any later version. 13 | 14 | QuaZIP is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with QuaZIP. If not, see . 21 | 22 | See COPYING file for the full LGPL text. 23 | 24 | Original ZIP package is copyrighted by Gilles Vollant and contributors, 25 | see quazip/(un)zip.h files for details. Basically it's the zlib license. 26 | */ 27 | 28 | #include 29 | 30 | /** 31 | This is automatically defined when building a static library, but when 32 | including QuaZip sources directly into a project, QUAZIP_STATIC should 33 | be defined explicitly to avoid possible troubles with unnecessary 34 | importing/exporting. 35 | */ 36 | #ifdef QUAZIP_STATIC 37 | #define QUAZIP_EXPORT 38 | #else 39 | /** 40 | * When building a DLL with MSVC, QUAZIP_BUILD must be defined. 41 | * qglobal.h takes care of defining Q_DECL_* correctly for msvc/gcc. 42 | */ 43 | #if defined(QUAZIP_BUILD) 44 | #define QUAZIP_EXPORT Q_DECL_EXPORT 45 | #else 46 | #define QUAZIP_EXPORT Q_DECL_IMPORT 47 | #endif 48 | #endif // QUAZIP_STATIC 49 | 50 | #ifdef __GNUC__ 51 | #define UNUSED __attribute__((__unused__)) 52 | #else 53 | #define UNUSED 54 | #endif 55 | 56 | #define QUAZIP_EXTRA_NTFS_MAGIC 0x000Au 57 | #define QUAZIP_EXTRA_NTFS_TIME_MAGIC 0x0001u 58 | 59 | #endif // QUAZIP_GLOBAL_H 60 | -------------------------------------------------------------------------------- /lib/quazipd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Purple-CSGO/CSGO-Toolbox-Qt/bf425be542e3173298e84675e41c75ab21ab1bed/lib/quazipd.lib -------------------------------------------------------------------------------- /lib/quazipdir.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2005-2014 Sergey A. Tachenov 3 | 4 | This file is part of QuaZIP. 5 | 6 | QuaZIP is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | QuaZIP is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with QuaZIP. If not, see . 18 | 19 | See COPYING file for the full LGPL text. 20 | 21 | Original ZIP package is copyrighted by Gilles Vollant and contributors, 22 | see quazip/(un)zip.h files for details. Basically it's the zlib license. 23 | */ 24 | 25 | #include "quazipdir.h" 26 | 27 | #include 28 | #include 29 | 30 | /// \cond internal 31 | class QuaZipDirPrivate: public QSharedData { 32 | friend class QuaZipDir; 33 | private: 34 | QuaZipDirPrivate(QuaZip *zip, const QString &dir = QString()): 35 | zip(zip), dir(dir), caseSensitivity(QuaZip::csDefault), 36 | filter(QDir::NoFilter), sorting(QDir::NoSort) {} 37 | QuaZip *zip; 38 | QString dir; 39 | QuaZip::CaseSensitivity caseSensitivity; 40 | QDir::Filters filter; 41 | QStringList nameFilters; 42 | QDir::SortFlags sorting; 43 | template 44 | bool entryInfoList(QStringList nameFilters, QDir::Filters filter, 45 | QDir::SortFlags sort, TFileInfoList &result) const; 46 | inline QString simplePath() const {return QDir::cleanPath(dir);} 47 | }; 48 | /// \endcond 49 | 50 | QuaZipDir::QuaZipDir(const QuaZipDir &that): 51 | d(that.d) 52 | { 53 | } 54 | 55 | QuaZipDir::QuaZipDir(QuaZip *zip, const QString &dir): 56 | d(new QuaZipDirPrivate(zip, dir)) 57 | { 58 | if (d->dir.startsWith('/')) 59 | d->dir = d->dir.mid(1); 60 | } 61 | 62 | QuaZipDir::~QuaZipDir() 63 | { 64 | } 65 | 66 | bool QuaZipDir::operator==(const QuaZipDir &that) 67 | { 68 | return d->zip == that.d->zip && d->dir == that.d->dir; 69 | } 70 | 71 | QuaZipDir& QuaZipDir::operator=(const QuaZipDir &that) 72 | { 73 | this->d = that.d; 74 | return *this; 75 | } 76 | 77 | QString QuaZipDir::operator[](int pos) const 78 | { 79 | return entryList().at(pos); 80 | } 81 | 82 | QuaZip::CaseSensitivity QuaZipDir::caseSensitivity() const 83 | { 84 | return d->caseSensitivity; 85 | } 86 | 87 | bool QuaZipDir::cd(const QString &directoryName) 88 | { 89 | if (directoryName == "/") { 90 | d->dir = ""; 91 | return true; 92 | } 93 | QString dirName = directoryName; 94 | if (dirName.endsWith('/')) 95 | dirName.chop(1); 96 | if (dirName.contains('/')) { 97 | QuaZipDir dir(*this); 98 | if (dirName.startsWith('/')) { 99 | #ifdef QUAZIP_QUAZIPDIR_DEBUG 100 | qDebug("QuaZipDir::cd(%s): going to /", 101 | dirName.toUtf8().constData()); 102 | #endif 103 | if (!dir.cd("/")) 104 | return false; 105 | } 106 | QStringList path = dirName.split('/', QString::SkipEmptyParts); 107 | for (QStringList::const_iterator i = path.constBegin(); 108 | i != path.end(); 109 | ++i) { 110 | const QString &step = *i; 111 | #ifdef QUAZIP_QUAZIPDIR_DEBUG 112 | qDebug("QuaZipDir::cd(%s): going to %s", 113 | dirName.toUtf8().constData(), 114 | step.toUtf8().constData()); 115 | #endif 116 | if (!dir.cd(step)) 117 | return false; 118 | } 119 | d->dir = dir.path(); 120 | return true; 121 | } else { // no '/' 122 | if (dirName == ".") { 123 | return true; 124 | } else if (dirName == "..") { 125 | if (isRoot()) { 126 | return false; 127 | } else { 128 | int slashPos = d->dir.lastIndexOf('/'); 129 | if (slashPos == -1) { 130 | d->dir = ""; 131 | } else { 132 | d->dir = d->dir.left(slashPos); 133 | } 134 | return true; 135 | } 136 | } else { // a simple subdirectory 137 | if (exists(dirName)) { 138 | if (isRoot()) 139 | d->dir = dirName; 140 | else 141 | d->dir += "/" + dirName; 142 | return true; 143 | } else { 144 | return false; 145 | } 146 | } 147 | } 148 | } 149 | 150 | bool QuaZipDir::cdUp() 151 | { 152 | return cd(".."); 153 | } 154 | 155 | uint QuaZipDir::count() const 156 | { 157 | return entryList().count(); 158 | } 159 | 160 | QString QuaZipDir::dirName() const 161 | { 162 | return QDir(d->dir).dirName(); 163 | } 164 | 165 | QuaZipFileInfo64 QuaZipDir_getFileInfo(QuaZip *zip, bool *ok, 166 | const QString &relativeName, 167 | bool isReal) 168 | { 169 | QuaZipFileInfo64 info; 170 | if (isReal) { 171 | *ok = zip->getCurrentFileInfo(&info); 172 | } else { 173 | *ok = true; 174 | info.compressedSize = 0; 175 | info.crc = 0; 176 | info.diskNumberStart = 0; 177 | info.externalAttr = 0; 178 | info.flags = 0; 179 | info.internalAttr = 0; 180 | info.method = 0; 181 | info.uncompressedSize = 0; 182 | info.versionCreated = info.versionNeeded = 0; 183 | } 184 | info.name = relativeName; 185 | return info; 186 | } 187 | 188 | static void QuaZipDir_convertInfoList(const QList &from, 189 | QList &to) 190 | { 191 | to = from; 192 | } 193 | 194 | static void QuaZipDir_convertInfoList(const QList &from, 195 | QStringList &to) 196 | { 197 | to.clear(); 198 | for (QList::const_iterator i = from.constBegin(); 199 | i != from.constEnd(); 200 | ++i) { 201 | to.append(i->name); 202 | } 203 | } 204 | 205 | static void QuaZipDir_convertInfoList(const QList &from, 206 | QList &to) 207 | { 208 | to.clear(); 209 | for (QList::const_iterator i = from.constBegin(); 210 | i != from.constEnd(); 211 | ++i) { 212 | QuaZipFileInfo info32; 213 | i->toQuaZipFileInfo(info32); 214 | to.append(info32); 215 | } 216 | } 217 | 218 | /// \cond internal 219 | /** 220 | An utility class to restore the current file. 221 | */ 222 | class QuaZipDirRestoreCurrent { 223 | public: 224 | inline QuaZipDirRestoreCurrent(QuaZip *zip): 225 | zip(zip), currentFile(zip->getCurrentFileName()) {} 226 | inline ~QuaZipDirRestoreCurrent() 227 | { 228 | zip->setCurrentFile(currentFile); 229 | } 230 | private: 231 | QuaZip *zip; 232 | QString currentFile; 233 | }; 234 | /// \endcond 235 | 236 | /// \cond internal 237 | class QuaZipDirComparator 238 | { 239 | private: 240 | QDir::SortFlags sort; 241 | static QString getExtension(const QString &name); 242 | int compareStrings(const QString &string1, const QString &string2); 243 | public: 244 | inline QuaZipDirComparator(QDir::SortFlags sort): sort(sort) {} 245 | bool operator()(const QuaZipFileInfo64 &info1, const QuaZipFileInfo64 &info2); 246 | }; 247 | 248 | QString QuaZipDirComparator::getExtension(const QString &name) 249 | { 250 | if (name.endsWith('.') || name.indexOf('.', 1) == -1) { 251 | return ""; 252 | } else { 253 | return name.mid(name.lastIndexOf('.') + 1); 254 | } 255 | 256 | } 257 | 258 | int QuaZipDirComparator::compareStrings(const QString &string1, 259 | const QString &string2) 260 | { 261 | if (sort & QDir::LocaleAware) { 262 | if (sort & QDir::IgnoreCase) { 263 | return string1.toLower().localeAwareCompare(string2.toLower()); 264 | } else { 265 | return string1.localeAwareCompare(string2); 266 | } 267 | } else { 268 | return string1.compare(string2, (sort & QDir::IgnoreCase) 269 | ? Qt::CaseInsensitive : Qt::CaseSensitive); 270 | } 271 | } 272 | 273 | bool QuaZipDirComparator::operator()(const QuaZipFileInfo64 &info1, 274 | const QuaZipFileInfo64 &info2) 275 | { 276 | QDir::SortFlags order = sort 277 | & (QDir::Name | QDir::Time | QDir::Size | QDir::Type); 278 | if ((sort & QDir::DirsFirst) == QDir::DirsFirst 279 | || (sort & QDir::DirsLast) == QDir::DirsLast) { 280 | if (info1.name.endsWith('/') && !info2.name.endsWith('/')) 281 | return (sort & QDir::DirsFirst) == QDir::DirsFirst; 282 | else if (!info1.name.endsWith('/') && info2.name.endsWith('/')) 283 | return (sort & QDir::DirsLast) == QDir::DirsLast; 284 | } 285 | bool result; 286 | int extDiff; 287 | switch (order) { 288 | case QDir::Name: 289 | result = compareStrings(info1.name, info2.name) < 0; 290 | break; 291 | case QDir::Type: 292 | extDiff = compareStrings(getExtension(info1.name), 293 | getExtension(info2.name)); 294 | if (extDiff == 0) { 295 | result = compareStrings(info1.name, info2.name) < 0; 296 | } else { 297 | result = extDiff < 0; 298 | } 299 | break; 300 | case QDir::Size: 301 | if (info1.uncompressedSize == info2.uncompressedSize) { 302 | result = compareStrings(info1.name, info2.name) < 0; 303 | } else { 304 | result = info1.uncompressedSize < info2.uncompressedSize; 305 | } 306 | break; 307 | case QDir::Time: 308 | if (info1.dateTime == info2.dateTime) { 309 | result = compareStrings(info1.name, info2.name) < 0; 310 | } else { 311 | result = info1.dateTime < info2.dateTime; 312 | } 313 | break; 314 | default: 315 | qWarning("QuaZipDirComparator(): Invalid sort mode 0x%2X", 316 | static_cast(sort)); 317 | return false; 318 | } 319 | return (sort & QDir::Reversed) ? !result : result; 320 | } 321 | 322 | template 323 | bool QuaZipDirPrivate::entryInfoList(QStringList nameFilters, 324 | QDir::Filters filter, QDir::SortFlags sort, TFileInfoList &result) const 325 | { 326 | QString basePath = simplePath(); 327 | if (!basePath.isEmpty()) 328 | basePath += "/"; 329 | int baseLength = basePath.length(); 330 | result.clear(); 331 | QuaZipDirRestoreCurrent saveCurrent(zip); 332 | if (!zip->goToFirstFile()) { 333 | return zip->getZipError() == UNZ_OK; 334 | } 335 | QDir::Filters fltr = filter; 336 | if (fltr == QDir::NoFilter) 337 | fltr = this->filter; 338 | if (fltr == QDir::NoFilter) 339 | fltr = QDir::AllEntries; 340 | QStringList nmfltr = nameFilters; 341 | if (nmfltr.isEmpty()) 342 | nmfltr = this->nameFilters; 343 | QSet dirsFound; 344 | QList list; 345 | do { 346 | QString name = zip->getCurrentFileName(); 347 | if (!name.startsWith(basePath)) 348 | continue; 349 | QString relativeName = name.mid(baseLength); 350 | if (relativeName.isEmpty()) 351 | continue; 352 | bool isDir = false; 353 | bool isReal = true; 354 | if (relativeName.contains('/')) { 355 | int indexOfSlash = relativeName.indexOf('/'); 356 | // something like "subdir/" 357 | isReal = indexOfSlash == relativeName.length() - 1; 358 | relativeName = relativeName.left(indexOfSlash + 1); 359 | if (dirsFound.contains(relativeName)) 360 | continue; 361 | isDir = true; 362 | } 363 | dirsFound.insert(relativeName); 364 | if ((fltr & QDir::Dirs) == 0 && isDir) 365 | continue; 366 | if ((fltr & QDir::Files) == 0 && !isDir) 367 | continue; 368 | if (!nmfltr.isEmpty() && !QDir::match(nmfltr, relativeName)) 369 | continue; 370 | bool ok; 371 | QuaZipFileInfo64 info = QuaZipDir_getFileInfo(zip, &ok, relativeName, 372 | isReal); 373 | if (!ok) { 374 | return false; 375 | } 376 | list.append(info); 377 | } while (zip->goToNextFile()); 378 | QDir::SortFlags srt = sort; 379 | if (srt == QDir::NoSort) 380 | srt = sorting; 381 | #ifdef QUAZIP_QUAZIPDIR_DEBUG 382 | qDebug("QuaZipDirPrivate::entryInfoList(): before sort:"); 383 | foreach (QuaZipFileInfo64 info, list) { 384 | qDebug("%s\t%s", info.name.toUtf8().constData(), 385 | info.dateTime.toString(Qt::ISODate).toUtf8().constData()); 386 | } 387 | #endif 388 | if (srt != QDir::NoSort && (srt & QDir::Unsorted) != QDir::Unsorted) { 389 | if (QuaZip::convertCaseSensitivity(caseSensitivity) 390 | == Qt::CaseInsensitive) 391 | srt |= QDir::IgnoreCase; 392 | QuaZipDirComparator lessThan(srt); 393 | qSort(list.begin(), list.end(), lessThan); 394 | } 395 | QuaZipDir_convertInfoList(list, result); 396 | return true; 397 | } 398 | 399 | /// \endcond 400 | 401 | QList QuaZipDir::entryInfoList(const QStringList &nameFilters, 402 | QDir::Filters filters, QDir::SortFlags sort) const 403 | { 404 | QList result; 405 | if (d->entryInfoList(nameFilters, filters, sort, result)) 406 | return result; 407 | else 408 | return QList(); 409 | } 410 | 411 | QList QuaZipDir::entryInfoList(QDir::Filters filters, 412 | QDir::SortFlags sort) const 413 | { 414 | return entryInfoList(QStringList(), filters, sort); 415 | } 416 | 417 | QList QuaZipDir::entryInfoList64(const QStringList &nameFilters, 418 | QDir::Filters filters, QDir::SortFlags sort) const 419 | { 420 | QList result; 421 | if (d->entryInfoList(nameFilters, filters, sort, result)) 422 | return result; 423 | else 424 | return QList(); 425 | } 426 | 427 | QList QuaZipDir::entryInfoList64(QDir::Filters filters, 428 | QDir::SortFlags sort) const 429 | { 430 | return entryInfoList64(QStringList(), filters, sort); 431 | } 432 | 433 | QStringList QuaZipDir::entryList(const QStringList &nameFilters, 434 | QDir::Filters filters, QDir::SortFlags sort) const 435 | { 436 | QStringList result; 437 | if (d->entryInfoList(nameFilters, filters, sort, result)) 438 | return result; 439 | else 440 | return QStringList(); 441 | } 442 | 443 | QStringList QuaZipDir::entryList(QDir::Filters filters, 444 | QDir::SortFlags sort) const 445 | { 446 | return entryList(QStringList(), filters, sort); 447 | } 448 | 449 | bool QuaZipDir::exists(const QString &filePath) const 450 | { 451 | if (filePath == "/" || filePath.isEmpty()) 452 | return true; 453 | QString fileName = filePath; 454 | if (fileName.endsWith('/')) 455 | fileName.chop(1); 456 | if (fileName.contains('/')) { 457 | QFileInfo fileInfo(fileName); 458 | #ifdef QUAZIP_QUAZIPDIR_DEBUG 459 | qDebug("QuaZipDir::exists(): fileName=%s, fileInfo.fileName()=%s, " 460 | "fileInfo.path()=%s", fileName.toUtf8().constData(), 461 | fileInfo.fileName().toUtf8().constData(), 462 | fileInfo.path().toUtf8().constData()); 463 | #endif 464 | QuaZipDir dir(*this); 465 | return dir.cd(fileInfo.path()) && dir.exists(fileInfo.fileName()); 466 | } else { 467 | if (fileName == "..") { 468 | return !isRoot(); 469 | } else if (fileName == ".") { 470 | return true; 471 | } else { 472 | QStringList entries = entryList(QDir::AllEntries, QDir::NoSort); 473 | #ifdef QUAZIP_QUAZIPDIR_DEBUG 474 | qDebug("QuaZipDir::exists(): looking for %s", 475 | fileName.toUtf8().constData()); 476 | for (QStringList::const_iterator i = entries.constBegin(); 477 | i != entries.constEnd(); 478 | ++i) { 479 | qDebug("QuaZipDir::exists(): entry: %s", 480 | i->toUtf8().constData()); 481 | } 482 | #endif 483 | Qt::CaseSensitivity cs = QuaZip::convertCaseSensitivity( 484 | d->caseSensitivity); 485 | if (filePath.endsWith('/')) { 486 | return entries.contains(filePath, cs); 487 | } else { 488 | return entries.contains(fileName, cs) 489 | || entries.contains(fileName + "/", cs); 490 | } 491 | } 492 | } 493 | } 494 | 495 | bool QuaZipDir::exists() const 496 | { 497 | return QuaZipDir(d->zip).exists(d->dir); 498 | } 499 | 500 | QString QuaZipDir::filePath(const QString &fileName) const 501 | { 502 | return QDir(d->dir).filePath(fileName); 503 | } 504 | 505 | QDir::Filters QuaZipDir::filter() 506 | { 507 | return d->filter; 508 | } 509 | 510 | bool QuaZipDir::isRoot() const 511 | { 512 | return d->simplePath().isEmpty(); 513 | } 514 | 515 | QStringList QuaZipDir::nameFilters() const 516 | { 517 | return d->nameFilters; 518 | } 519 | 520 | QString QuaZipDir::path() const 521 | { 522 | return d->dir; 523 | } 524 | 525 | QString QuaZipDir::relativeFilePath(const QString &fileName) const 526 | { 527 | return QDir("/" + d->dir).relativeFilePath(fileName); 528 | } 529 | 530 | void QuaZipDir::setCaseSensitivity(QuaZip::CaseSensitivity caseSensitivity) 531 | { 532 | d->caseSensitivity = caseSensitivity; 533 | } 534 | 535 | void QuaZipDir::setFilter(QDir::Filters filters) 536 | { 537 | d->filter = filters; 538 | } 539 | 540 | void QuaZipDir::setNameFilters(const QStringList &nameFilters) 541 | { 542 | d->nameFilters = nameFilters; 543 | } 544 | 545 | void QuaZipDir::setPath(const QString &path) 546 | { 547 | QString newDir = path; 548 | if (newDir == "/") { 549 | d->dir = ""; 550 | } else { 551 | if (newDir.endsWith('/')) 552 | newDir.chop(1); 553 | if (newDir.startsWith('/')) 554 | newDir = newDir.mid(1); 555 | d->dir = newDir; 556 | } 557 | } 558 | 559 | void QuaZipDir::setSorting(QDir::SortFlags sort) 560 | { 561 | d->sorting = sort; 562 | } 563 | 564 | QDir::SortFlags QuaZipDir::sorting() const 565 | { 566 | return d->sorting; 567 | } 568 | -------------------------------------------------------------------------------- /lib/quazipdir.h: -------------------------------------------------------------------------------- 1 | #ifndef QUAZIP_QUAZIPDIR_H 2 | #define QUAZIP_QUAZIPDIR_H 3 | 4 | /* 5 | Copyright (C) 2005-2014 Sergey A. Tachenov 6 | 7 | This file is part of QuaZIP. 8 | 9 | QuaZIP is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU Lesser General Public License as published by 11 | the Free Software Foundation, either version 2.1 of the License, or 12 | (at your option) any later version. 13 | 14 | QuaZIP is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with QuaZIP. If not, see . 21 | 22 | See COPYING file for the full LGPL text. 23 | 24 | Original ZIP package is copyrighted by Gilles Vollant and contributors, 25 | see quazip/(un)zip.h files for details. Basically it's the zlib license. 26 | */ 27 | 28 | class QuaZipDirPrivate; 29 | 30 | #include "quazip.h" 31 | #include "quazipfileinfo.h" 32 | #include 33 | #include 34 | #include 35 | 36 | /// Provides ZIP archive navigation. 37 | /** 38 | * This class is modelled after QDir, and is designed to provide similar 39 | * features for ZIP archives. 40 | * 41 | * The only significant difference from QDir is that the root path is not 42 | * '/', but an empty string since that's how the file paths are stored in 43 | * the archive. However, QuaZipDir understands the paths starting with 44 | * '/'. It is important in a few places: 45 | * 46 | * - In the cd() function. 47 | * - In the constructor. 48 | * - In the exists() function. 49 | * - In the relativePath() function. 50 | * 51 | * Note that since ZIP uses '/' on all platforms, the '\' separator is 52 | * not supported. 53 | */ 54 | class QUAZIP_EXPORT QuaZipDir { 55 | private: 56 | QSharedDataPointer d; 57 | public: 58 | /// The copy constructor. 59 | QuaZipDir(const QuaZipDir &that); 60 | /// Constructs a QuaZipDir instance pointing to the specified directory. 61 | /** 62 | If \a dir is not specified, points to the root of the archive. 63 | The same happens if the \a dir is "/". 64 | */ 65 | QuaZipDir(QuaZip *zip, const QString &dir = QString()); 66 | /// Destructor. 67 | ~QuaZipDir(); 68 | /// The assignment operator. 69 | bool operator==(const QuaZipDir &that); 70 | /// operator!= 71 | /** 72 | \return \c true if either this and \a that use different QuaZip 73 | instances or if they point to different directories. 74 | */ 75 | inline bool operator!=(const QuaZipDir &that) {return !operator==(that);} 76 | /// operator== 77 | /** 78 | \return \c true if both this and \a that use the same QuaZip 79 | instance and point to the same directory. 80 | */ 81 | QuaZipDir& operator=(const QuaZipDir &that); 82 | /// Returns the name of the entry at the specified position. 83 | QString operator[](int pos) const; 84 | /// Returns the current case sensitivity mode. 85 | QuaZip::CaseSensitivity caseSensitivity() const; 86 | /// Changes the 'current' directory. 87 | /** 88 | * If the path starts with '/', it is interpreted as an absolute 89 | * path from the root of the archive. Otherwise, it is interpreted 90 | * as a path relative to the current directory as was set by the 91 | * previous cd() or the constructor. 92 | * 93 | * Note that the subsequent path() call will not return a path 94 | * starting with '/' in all cases. 95 | */ 96 | bool cd(const QString &dirName); 97 | /// Goes up. 98 | bool cdUp(); 99 | /// Returns the number of entries in the directory. 100 | uint count() const; 101 | /// Returns the current directory name. 102 | /** 103 | The name doesn't include the path. 104 | */ 105 | QString dirName() const; 106 | /// Returns the list of the entries in the directory. 107 | /** 108 | \param nameFilters The list of file patterns to list, uses the same 109 | syntax as QDir. 110 | \param filters The entry type filters, only Files and Dirs are 111 | accepted. 112 | \param sort Sorting mode. 113 | */ 114 | QList entryInfoList(const QStringList &nameFilters, 115 | QDir::Filters filters = QDir::NoFilter, 116 | QDir::SortFlags sort = QDir::NoSort) const; 117 | /// Returns the list of the entries in the directory. 118 | /** 119 | \overload 120 | 121 | The same as entryInfoList(QStringList(), filters, sort). 122 | */ 123 | QList entryInfoList(QDir::Filters filters = QDir::NoFilter, 124 | QDir::SortFlags sort = QDir::NoSort) const; 125 | /// Returns the list of the entries in the directory with zip64 support. 126 | /** 127 | \param nameFilters The list of file patterns to list, uses the same 128 | syntax as QDir. 129 | \param filters The entry type filters, only Files and Dirs are 130 | accepted. 131 | \param sort Sorting mode. 132 | */ 133 | QList entryInfoList64(const QStringList &nameFilters, 134 | QDir::Filters filters = QDir::NoFilter, 135 | QDir::SortFlags sort = QDir::NoSort) const; 136 | /// Returns the list of the entries in the directory with zip64 support. 137 | /** 138 | \overload 139 | 140 | The same as entryInfoList64(QStringList(), filters, sort). 141 | */ 142 | QList entryInfoList64(QDir::Filters filters = QDir::NoFilter, 143 | QDir::SortFlags sort = QDir::NoSort) const; 144 | /// Returns the list of the entry names in the directory. 145 | /** 146 | The same as entryInfoList(nameFilters, filters, sort), but only 147 | returns entry names. 148 | */ 149 | QStringList entryList(const QStringList &nameFilters, 150 | QDir::Filters filters = QDir::NoFilter, 151 | QDir::SortFlags sort = QDir::NoSort) const; 152 | /// Returns the list of the entry names in the directory. 153 | /** 154 | \overload 155 | 156 | The same as entryList(QStringList(), filters, sort). 157 | */ 158 | QStringList entryList(QDir::Filters filters = QDir::NoFilter, 159 | QDir::SortFlags sort = QDir::NoSort) const; 160 | /// Returns \c true if the entry with the specified name exists. 161 | /** 162 | The ".." is considered to exist if the current directory 163 | is not root. The "." and "/" are considered to 164 | always exist. Paths starting with "/" are relative to 165 | the archive root, other paths are relative to the current dir. 166 | */ 167 | bool exists(const QString &fileName) const; 168 | /// Return \c true if the directory pointed by this QuaZipDir exists. 169 | bool exists() const; 170 | /// Returns the full path to the specified file. 171 | /** 172 | Doesn't check if the file actually exists. 173 | */ 174 | QString filePath(const QString &fileName) const; 175 | /// Returns the default filter. 176 | QDir::Filters filter(); 177 | /// Returns if the QuaZipDir points to the root of the archive. 178 | /** 179 | Not that the root path is the empty string, not '/'. 180 | */ 181 | bool isRoot() const; 182 | /// Return the default name filter. 183 | QStringList nameFilters() const; 184 | /// Returns the path to the current dir. 185 | /** 186 | The path never starts with '/', and the root path is an empty 187 | string. 188 | */ 189 | QString path() const; 190 | /// Returns the path to the specified file relative to the current dir. 191 | /** 192 | * This function is mostly useless, provided only for the sake of 193 | * completeness. 194 | * 195 | * @param fileName The path to the file, should start with "/" 196 | * if relative to the archive root. 197 | * @return Path relative to the current dir. 198 | */ 199 | QString relativeFilePath(const QString &fileName) const; 200 | /// Sets the default case sensitivity mode. 201 | void setCaseSensitivity(QuaZip::CaseSensitivity caseSensitivity); 202 | /// Sets the default filter. 203 | void setFilter(QDir::Filters filters); 204 | /// Sets the default name filter. 205 | void setNameFilters(const QStringList &nameFilters); 206 | /// Goes to the specified path. 207 | /** 208 | The difference from cd() is that this function never checks if the 209 | path actually exists and doesn't use relative paths, so it's 210 | possible to go to the root directory with setPath(""). 211 | 212 | Note that this function still chops the trailing and/or leading 213 | '/' and treats a single '/' as the root path (path() will still 214 | return an empty string). 215 | */ 216 | void setPath(const QString &path); 217 | /// Sets the default sorting mode. 218 | void setSorting(QDir::SortFlags sort); 219 | /// Returns the default sorting mode. 220 | QDir::SortFlags sorting() const; 221 | }; 222 | 223 | #endif // QUAZIP_QUAZIPDIR_H 224 | -------------------------------------------------------------------------------- /lib/quazipfile.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2005-2014 Sergey A. Tachenov 3 | 4 | This file is part of QuaZIP. 5 | 6 | QuaZIP is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | QuaZIP is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with QuaZIP. If not, see . 18 | 19 | See COPYING file for the full LGPL text. 20 | 21 | Original ZIP package is copyrighted by Gilles Vollant, see 22 | quazip/(un)zip.h files for details, basically it's zlib license. 23 | **/ 24 | 25 | #include "quazipfile.h" 26 | 27 | using namespace std; 28 | 29 | /// The implementation class for QuaZip. 30 | /** 31 | \internal 32 | 33 | This class contains all the private stuff for the QuaZipFile class, thus 34 | allowing to preserve binary compatibility between releases, the 35 | technique known as the Pimpl (private implementation) idiom. 36 | */ 37 | class QuaZipFilePrivate { 38 | friend class QuaZipFile; 39 | private: 40 | Q_DISABLE_COPY(QuaZipFilePrivate) 41 | /// The pointer to the associated QuaZipFile instance. 42 | QuaZipFile *q; 43 | /// The QuaZip object to work with. 44 | QuaZip *zip; 45 | /// The file name. 46 | QString fileName; 47 | /// Case sensitivity mode. 48 | QuaZip::CaseSensitivity caseSensitivity; 49 | /// Whether this file is opened in the raw mode. 50 | bool raw; 51 | /// Write position to keep track of. 52 | /** 53 | QIODevice::pos() is broken for non-seekable devices, so we need 54 | our own position. 55 | */ 56 | qint64 writePos; 57 | /// Uncompressed size to write along with a raw file. 58 | quint64 uncompressedSize; 59 | /// CRC to write along with a raw file. 60 | quint32 crc; 61 | /// Whether \ref zip points to an internal QuaZip instance. 62 | /** 63 | This is true if the archive was opened by name, rather than by 64 | supplying an existing QuaZip instance. 65 | */ 66 | bool internal; 67 | /// The last error. 68 | int zipError; 69 | /// Resets \ref zipError. 70 | inline void resetZipError() const {setZipError(UNZ_OK);} 71 | /// Sets the zip error. 72 | /** 73 | This function is marked as const although it changes one field. 74 | This allows to call it from const functions that don't change 75 | anything by themselves. 76 | */ 77 | void setZipError(int zipError) const; 78 | /// The constructor for the corresponding QuaZipFile constructor. 79 | inline QuaZipFilePrivate(QuaZipFile *q): 80 | q(q), 81 | zip(NULL), 82 | caseSensitivity(QuaZip::csDefault), 83 | raw(false), 84 | writePos(0), 85 | uncompressedSize(0), 86 | crc(0), 87 | internal(true), 88 | zipError(UNZ_OK) {} 89 | /// The constructor for the corresponding QuaZipFile constructor. 90 | inline QuaZipFilePrivate(QuaZipFile *q, const QString &zipName): 91 | q(q), 92 | caseSensitivity(QuaZip::csDefault), 93 | raw(false), 94 | writePos(0), 95 | uncompressedSize(0), 96 | crc(0), 97 | internal(true), 98 | zipError(UNZ_OK) 99 | { 100 | zip=new QuaZip(zipName); 101 | } 102 | /// The constructor for the corresponding QuaZipFile constructor. 103 | inline QuaZipFilePrivate(QuaZipFile *q, const QString &zipName, const QString &fileName, 104 | QuaZip::CaseSensitivity cs): 105 | q(q), 106 | raw(false), 107 | writePos(0), 108 | uncompressedSize(0), 109 | crc(0), 110 | internal(true), 111 | zipError(UNZ_OK) 112 | { 113 | zip=new QuaZip(zipName); 114 | this->fileName=fileName; 115 | if (this->fileName.startsWith('/')) 116 | this->fileName = this->fileName.mid(1); 117 | this->caseSensitivity=cs; 118 | } 119 | /// The constructor for the QuaZipFile constructor accepting a file name. 120 | inline QuaZipFilePrivate(QuaZipFile *q, QuaZip *zip): 121 | q(q), 122 | zip(zip), 123 | raw(false), 124 | writePos(0), 125 | uncompressedSize(0), 126 | crc(0), 127 | internal(false), 128 | zipError(UNZ_OK) {} 129 | /// The destructor. 130 | inline ~QuaZipFilePrivate() 131 | { 132 | if (internal) 133 | delete zip; 134 | } 135 | }; 136 | 137 | QuaZipFile::QuaZipFile(): 138 | p(new QuaZipFilePrivate(this)) 139 | { 140 | } 141 | 142 | QuaZipFile::QuaZipFile(QObject *parent): 143 | QIODevice(parent), 144 | p(new QuaZipFilePrivate(this)) 145 | { 146 | } 147 | 148 | QuaZipFile::QuaZipFile(const QString& zipName, QObject *parent): 149 | QIODevice(parent), 150 | p(new QuaZipFilePrivate(this, zipName)) 151 | { 152 | } 153 | 154 | QuaZipFile::QuaZipFile(const QString& zipName, const QString& fileName, 155 | QuaZip::CaseSensitivity cs, QObject *parent): 156 | QIODevice(parent), 157 | p(new QuaZipFilePrivate(this, zipName, fileName, cs)) 158 | { 159 | } 160 | 161 | QuaZipFile::QuaZipFile(QuaZip *zip, QObject *parent): 162 | QIODevice(parent), 163 | p(new QuaZipFilePrivate(this, zip)) 164 | { 165 | } 166 | 167 | QuaZipFile::~QuaZipFile() 168 | { 169 | if (isOpen()) 170 | close(); 171 | delete p; 172 | } 173 | 174 | QString QuaZipFile::getZipName() const 175 | { 176 | return p->zip==NULL ? QString() : p->zip->getZipName(); 177 | } 178 | 179 | QuaZip *QuaZipFile::getZip() const 180 | { 181 | return p->internal ? NULL : p->zip; 182 | } 183 | 184 | QString QuaZipFile::getActualFileName()const 185 | { 186 | p->setZipError(UNZ_OK); 187 | if (p->zip == NULL || (openMode() & WriteOnly)) 188 | return QString(); 189 | QString name=p->zip->getCurrentFileName(); 190 | if(name.isNull()) 191 | p->setZipError(p->zip->getZipError()); 192 | return name; 193 | } 194 | 195 | void QuaZipFile::setZipName(const QString& zipName) 196 | { 197 | if(isOpen()) { 198 | qWarning("QuaZipFile::setZipName(): file is already open - can not set ZIP name"); 199 | return; 200 | } 201 | if(p->zip!=NULL && p->internal) 202 | delete p->zip; 203 | p->zip=new QuaZip(zipName); 204 | p->internal=true; 205 | } 206 | 207 | void QuaZipFile::setZip(QuaZip *zip) 208 | { 209 | if(isOpen()) { 210 | qWarning("QuaZipFile::setZip(): file is already open - can not set ZIP"); 211 | return; 212 | } 213 | if(p->zip!=NULL && p->internal) 214 | delete p->zip; 215 | p->zip=zip; 216 | p->fileName=QString(); 217 | p->internal=false; 218 | } 219 | 220 | void QuaZipFile::setFileName(const QString& fileName, QuaZip::CaseSensitivity cs) 221 | { 222 | if(p->zip==NULL) { 223 | qWarning("QuaZipFile::setFileName(): call setZipName() first"); 224 | return; 225 | } 226 | if(!p->internal) { 227 | qWarning("QuaZipFile::setFileName(): should not be used when not using internal QuaZip"); 228 | return; 229 | } 230 | if(isOpen()) { 231 | qWarning("QuaZipFile::setFileName(): can not set file name for already opened file"); 232 | return; 233 | } 234 | p->fileName=fileName; 235 | if (p->fileName.startsWith('/')) 236 | p->fileName = p->fileName.mid(1); 237 | p->caseSensitivity=cs; 238 | } 239 | 240 | void QuaZipFilePrivate::setZipError(int zipError) const 241 | { 242 | QuaZipFilePrivate *fakeThis = const_cast(this); // non-const 243 | fakeThis->zipError=zipError; 244 | if(zipError==UNZ_OK) 245 | q->setErrorString(QString()); 246 | else 247 | q->setErrorString(QuaZipFile::tr("ZIP/UNZIP API error %1").arg(zipError)); 248 | } 249 | 250 | bool QuaZipFile::open(OpenMode mode) 251 | { 252 | return open(mode, NULL); 253 | } 254 | 255 | bool QuaZipFile::open(OpenMode mode, int *method, int *level, bool raw, const char *password) 256 | { 257 | p->resetZipError(); 258 | if(isOpen()) { 259 | qWarning("QuaZipFile::open(): already opened"); 260 | return false; 261 | } 262 | if(mode&Unbuffered) { 263 | qWarning("QuaZipFile::open(): Unbuffered mode is not supported"); 264 | return false; 265 | } 266 | if((mode&ReadOnly)&&!(mode&WriteOnly)) { 267 | if(p->internal) { 268 | if(!p->zip->open(QuaZip::mdUnzip)) { 269 | p->setZipError(p->zip->getZipError()); 270 | return false; 271 | } 272 | if(!p->zip->setCurrentFile(p->fileName, p->caseSensitivity)) { 273 | p->setZipError(p->zip->getZipError()); 274 | p->zip->close(); 275 | return false; 276 | } 277 | } else { 278 | if(p->zip==NULL) { 279 | qWarning("QuaZipFile::open(): zip is NULL"); 280 | return false; 281 | } 282 | if(p->zip->getMode()!=QuaZip::mdUnzip) { 283 | qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d", 284 | (int)mode, (int)p->zip->getMode()); 285 | return false; 286 | } 287 | if(!p->zip->hasCurrentFile()) { 288 | qWarning("QuaZipFile::open(): zip does not have current file"); 289 | return false; 290 | } 291 | } 292 | p->setZipError(unzOpenCurrentFile3(p->zip->getUnzFile(), method, level, (int)raw, password)); 293 | if(p->zipError==UNZ_OK) { 294 | setOpenMode(mode); 295 | p->raw=raw; 296 | return true; 297 | } else 298 | return false; 299 | } 300 | qWarning("QuaZipFile::open(): open mode %d not supported by this function", (int)mode); 301 | return false; 302 | } 303 | 304 | bool QuaZipFile::open(OpenMode mode, const QuaZipNewInfo& info, 305 | const char *password, quint32 crc, 306 | int method, int level, bool raw, 307 | int windowBits, int memLevel, int strategy) 308 | { 309 | zip_fileinfo info_z; 310 | p->resetZipError(); 311 | if(isOpen()) { 312 | qWarning("QuaZipFile::open(): already opened"); 313 | return false; 314 | } 315 | if((mode&WriteOnly)&&!(mode&ReadOnly)) { 316 | if(p->internal) { 317 | qWarning("QuaZipFile::open(): write mode is incompatible with internal QuaZip approach"); 318 | return false; 319 | } 320 | if(p->zip==NULL) { 321 | qWarning("QuaZipFile::open(): zip is NULL"); 322 | return false; 323 | } 324 | if(p->zip->getMode()!=QuaZip::mdCreate&&p->zip->getMode()!=QuaZip::mdAppend&&p->zip->getMode()!=QuaZip::mdAdd) { 325 | qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d", 326 | (int)mode, (int)p->zip->getMode()); 327 | return false; 328 | } 329 | info_z.tmz_date.tm_year=info.dateTime.date().year(); 330 | info_z.tmz_date.tm_mon=info.dateTime.date().month() - 1; 331 | info_z.tmz_date.tm_mday=info.dateTime.date().day(); 332 | info_z.tmz_date.tm_hour=info.dateTime.time().hour(); 333 | info_z.tmz_date.tm_min=info.dateTime.time().minute(); 334 | info_z.tmz_date.tm_sec=info.dateTime.time().second(); 335 | info_z.dosDate = 0; 336 | info_z.internal_fa=(uLong)info.internalAttr; 337 | info_z.external_fa=(uLong)info.externalAttr; 338 | if (p->zip->isDataDescriptorWritingEnabled()) 339 | zipSetFlags(p->zip->getZipFile(), ZIP_WRITE_DATA_DESCRIPTOR); 340 | else 341 | zipClearFlags(p->zip->getZipFile(), ZIP_WRITE_DATA_DESCRIPTOR); 342 | p->setZipError(zipOpenNewFileInZip3_64(p->zip->getZipFile(), 343 | p->zip->getFileNameCodec()->fromUnicode(info.name).constData(), &info_z, 344 | info.extraLocal.constData(), info.extraLocal.length(), 345 | info.extraGlobal.constData(), info.extraGlobal.length(), 346 | p->zip->getCommentCodec()->fromUnicode(info.comment).constData(), 347 | method, level, (int)raw, 348 | windowBits, memLevel, strategy, 349 | password, (uLong)crc, p->zip->isZip64Enabled())); 350 | if(p->zipError==UNZ_OK) { 351 | p->writePos=0; 352 | setOpenMode(mode); 353 | p->raw=raw; 354 | if(raw) { 355 | p->crc=crc; 356 | p->uncompressedSize=info.uncompressedSize; 357 | } 358 | return true; 359 | } else 360 | return false; 361 | } 362 | qWarning("QuaZipFile::open(): open mode %d not supported by this function", (int)mode); 363 | return false; 364 | } 365 | 366 | bool QuaZipFile::isSequential()const 367 | { 368 | return true; 369 | } 370 | 371 | qint64 QuaZipFile::pos()const 372 | { 373 | if(p->zip==NULL) { 374 | qWarning("QuaZipFile::pos(): call setZipName() or setZip() first"); 375 | return -1; 376 | } 377 | if(!isOpen()) { 378 | qWarning("QuaZipFile::pos(): file is not open"); 379 | return -1; 380 | } 381 | if(openMode()&ReadOnly) 382 | // QIODevice::pos() is broken for sequential devices, 383 | // but thankfully bytesAvailable() returns the number of 384 | // bytes buffered, so we know how far ahead we are. 385 | return unztell64(p->zip->getUnzFile()) - QIODevice::bytesAvailable(); 386 | else 387 | return p->writePos; 388 | } 389 | 390 | bool QuaZipFile::atEnd()const 391 | { 392 | if(p->zip==NULL) { 393 | qWarning("QuaZipFile::atEnd(): call setZipName() or setZip() first"); 394 | return false; 395 | } 396 | if(!isOpen()) { 397 | qWarning("QuaZipFile::atEnd(): file is not open"); 398 | return false; 399 | } 400 | if(openMode()&ReadOnly) 401 | // the same problem as with pos() 402 | return QIODevice::bytesAvailable() == 0 403 | && unzeof(p->zip->getUnzFile())==1; 404 | else 405 | return true; 406 | } 407 | 408 | qint64 QuaZipFile::size()const 409 | { 410 | if(!isOpen()) { 411 | qWarning("QuaZipFile::atEnd(): file is not open"); 412 | return -1; 413 | } 414 | if(openMode()&ReadOnly) 415 | return p->raw?csize():usize(); 416 | else 417 | return p->writePos; 418 | } 419 | 420 | qint64 QuaZipFile::csize()const 421 | { 422 | unz_file_info64 info_z; 423 | p->setZipError(UNZ_OK); 424 | if(p->zip==NULL||p->zip->getMode()!=QuaZip::mdUnzip) return -1; 425 | p->setZipError(unzGetCurrentFileInfo64(p->zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0)); 426 | if(p->zipError!=UNZ_OK) 427 | return -1; 428 | return info_z.compressed_size; 429 | } 430 | 431 | qint64 QuaZipFile::usize()const 432 | { 433 | unz_file_info64 info_z; 434 | p->setZipError(UNZ_OK); 435 | if(p->zip==NULL||p->zip->getMode()!=QuaZip::mdUnzip) return -1; 436 | p->setZipError(unzGetCurrentFileInfo64(p->zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0)); 437 | if(p->zipError!=UNZ_OK) 438 | return -1; 439 | return info_z.uncompressed_size; 440 | } 441 | 442 | bool QuaZipFile::getFileInfo(QuaZipFileInfo *info) 443 | { 444 | QuaZipFileInfo64 info64; 445 | if (getFileInfo(&info64)) { 446 | info64.toQuaZipFileInfo(*info); 447 | return true; 448 | } else { 449 | return false; 450 | } 451 | } 452 | 453 | bool QuaZipFile::getFileInfo(QuaZipFileInfo64 *info) 454 | { 455 | if(p->zip==NULL||p->zip->getMode()!=QuaZip::mdUnzip) return false; 456 | p->zip->getCurrentFileInfo(info); 457 | p->setZipError(p->zip->getZipError()); 458 | return p->zipError==UNZ_OK; 459 | } 460 | 461 | void QuaZipFile::close() 462 | { 463 | p->resetZipError(); 464 | if(p->zip==NULL||!p->zip->isOpen()) return; 465 | if(!isOpen()) { 466 | qWarning("QuaZipFile::close(): file isn't open"); 467 | return; 468 | } 469 | if(openMode()&ReadOnly) 470 | p->setZipError(unzCloseCurrentFile(p->zip->getUnzFile())); 471 | else if(openMode()&WriteOnly) 472 | if(isRaw()) p->setZipError(zipCloseFileInZipRaw64(p->zip->getZipFile(), p->uncompressedSize, p->crc)); 473 | else p->setZipError(zipCloseFileInZip(p->zip->getZipFile())); 474 | else { 475 | qWarning("Wrong open mode: %d", (int)openMode()); 476 | return; 477 | } 478 | if(p->zipError==UNZ_OK) setOpenMode(QIODevice::NotOpen); 479 | else return; 480 | if(p->internal) { 481 | p->zip->close(); 482 | p->setZipError(p->zip->getZipError()); 483 | } 484 | } 485 | 486 | qint64 QuaZipFile::readData(char *data, qint64 maxSize) 487 | { 488 | p->setZipError(UNZ_OK); 489 | qint64 bytesRead=unzReadCurrentFile(p->zip->getUnzFile(), data, (unsigned)maxSize); 490 | if (bytesRead < 0) { 491 | p->setZipError((int) bytesRead); 492 | return -1; 493 | } 494 | return bytesRead; 495 | } 496 | 497 | qint64 QuaZipFile::writeData(const char* data, qint64 maxSize) 498 | { 499 | p->setZipError(ZIP_OK); 500 | p->setZipError(zipWriteInFileInZip(p->zip->getZipFile(), data, (uint)maxSize)); 501 | if(p->zipError!=ZIP_OK) return -1; 502 | else { 503 | p->writePos+=maxSize; 504 | return maxSize; 505 | } 506 | } 507 | 508 | QString QuaZipFile::getFileName() const 509 | { 510 | return p->fileName; 511 | } 512 | 513 | QuaZip::CaseSensitivity QuaZipFile::getCaseSensitivity() const 514 | { 515 | return p->caseSensitivity; 516 | } 517 | 518 | bool QuaZipFile::isRaw() const 519 | { 520 | return p->raw; 521 | } 522 | 523 | int QuaZipFile::getZipError() const 524 | { 525 | return p->zipError; 526 | } 527 | 528 | qint64 QuaZipFile::bytesAvailable() const 529 | { 530 | return size() - pos(); 531 | } 532 | -------------------------------------------------------------------------------- /lib/quazipfileinfo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2005-2014 Sergey A. Tachenov 3 | 4 | This file is part of QuaZIP. 5 | 6 | QuaZIP is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | QuaZIP is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with QuaZIP. If not, see . 18 | 19 | See COPYING file for the full LGPL text. 20 | 21 | Original ZIP package is copyrighted by Gilles Vollant and contributors, 22 | see quazip/(un)zip.h files for details. Basically it's the zlib license. 23 | */ 24 | 25 | #include "quazipfileinfo.h" 26 | 27 | static QFile::Permissions permissionsFromExternalAttr(quint32 externalAttr) { 28 | quint32 uPerm = (externalAttr & 0xFFFF0000u) >> 16; 29 | QFile::Permissions perm = 0; 30 | if ((uPerm & 0400) != 0) 31 | perm |= QFile::ReadOwner; 32 | if ((uPerm & 0200) != 0) 33 | perm |= QFile::WriteOwner; 34 | if ((uPerm & 0100) != 0) 35 | perm |= QFile::ExeOwner; 36 | if ((uPerm & 0040) != 0) 37 | perm |= QFile::ReadGroup; 38 | if ((uPerm & 0020) != 0) 39 | perm |= QFile::WriteGroup; 40 | if ((uPerm & 0010) != 0) 41 | perm |= QFile::ExeGroup; 42 | if ((uPerm & 0004) != 0) 43 | perm |= QFile::ReadOther; 44 | if ((uPerm & 0002) != 0) 45 | perm |= QFile::WriteOther; 46 | if ((uPerm & 0001) != 0) 47 | perm |= QFile::ExeOther; 48 | return perm; 49 | 50 | } 51 | 52 | QFile::Permissions QuaZipFileInfo::getPermissions() const 53 | { 54 | return permissionsFromExternalAttr(externalAttr); 55 | } 56 | 57 | QFile::Permissions QuaZipFileInfo64::getPermissions() const 58 | { 59 | return permissionsFromExternalAttr(externalAttr); 60 | } 61 | 62 | bool QuaZipFileInfo64::toQuaZipFileInfo(QuaZipFileInfo &info) const 63 | { 64 | bool noOverflow = true; 65 | info.name = name; 66 | info.versionCreated = versionCreated; 67 | info.versionNeeded = versionNeeded; 68 | info.flags = flags; 69 | info.method = method; 70 | info.dateTime = dateTime; 71 | info.crc = crc; 72 | if (compressedSize > 0xFFFFFFFFu) { 73 | info.compressedSize = 0xFFFFFFFFu; 74 | noOverflow = false; 75 | } else { 76 | info.compressedSize = compressedSize; 77 | } 78 | if (uncompressedSize > 0xFFFFFFFFu) { 79 | info.uncompressedSize = 0xFFFFFFFFu; 80 | noOverflow = false; 81 | } else { 82 | info.uncompressedSize = uncompressedSize; 83 | } 84 | info.diskNumberStart = diskNumberStart; 85 | info.internalAttr = internalAttr; 86 | info.externalAttr = externalAttr; 87 | info.comment = comment; 88 | info.extra = extra; 89 | return noOverflow; 90 | } 91 | 92 | static QDateTime getNTFSTime(const QByteArray &extra, int position, 93 | int *fineTicks) 94 | { 95 | QDateTime dateTime; 96 | for (int i = 0; i <= extra.size() - 4; ) { 97 | unsigned type = static_cast(static_cast( 98 | extra.at(i))) 99 | | (static_cast(static_cast( 100 | extra.at(i + 1))) << 8); 101 | i += 2; 102 | unsigned length = static_cast(static_cast( 103 | extra.at(i))) 104 | | (static_cast(static_cast( 105 | extra.at(i + 1))) << 8); 106 | i += 2; 107 | if (type == QUAZIP_EXTRA_NTFS_MAGIC && length >= 32) { 108 | i += 4; // reserved 109 | while (i <= extra.size() - 4) { 110 | unsigned tag = static_cast( 111 | static_cast(extra.at(i))) 112 | | (static_cast( 113 | static_cast(extra.at(i + 1))) 114 | << 8); 115 | i += 2; 116 | int tagsize = static_cast( 117 | static_cast(extra.at(i))) 118 | | (static_cast( 119 | static_cast(extra.at(i + 1))) 120 | << 8); 121 | i += 2; 122 | if (tag == QUAZIP_EXTRA_NTFS_TIME_MAGIC 123 | && tagsize >= position + 8) { 124 | i += position; 125 | quint64 mtime = static_cast( 126 | static_cast(extra.at(i))) 127 | | (static_cast(static_cast( 128 | extra.at(i + 1))) << 8) 129 | | (static_cast(static_cast( 130 | extra.at(i + 2))) << 16) 131 | | (static_cast(static_cast( 132 | extra.at(i + 3))) << 24) 133 | | (static_cast(static_cast( 134 | extra.at(i + 4))) << 32) 135 | | (static_cast(static_cast( 136 | extra.at(i + 5))) << 40) 137 | | (static_cast(static_cast( 138 | extra.at(i + 6))) << 48) 139 | | (static_cast(static_cast( 140 | extra.at(i + 7))) << 56); 141 | // the NTFS time is measured from 1601 for whatever reason 142 | QDateTime base(QDate(1601, 1, 1), QTime(0, 0), Qt::UTC); 143 | dateTime = base.addMSecs(mtime / 10000); 144 | if (fineTicks != NULL) { 145 | *fineTicks = static_cast(mtime % 10000); 146 | } 147 | i += tagsize - position; 148 | } else { 149 | i += tagsize; 150 | } 151 | 152 | } 153 | } else { 154 | i += length; 155 | } 156 | } 157 | if (fineTicks != NULL && dateTime.isNull()) { 158 | *fineTicks = 0; 159 | } 160 | return dateTime; 161 | } 162 | 163 | QDateTime QuaZipFileInfo64::getNTFSmTime(int *fineTicks) const 164 | { 165 | return getNTFSTime(extra, 0, fineTicks); 166 | } 167 | 168 | QDateTime QuaZipFileInfo64::getNTFSaTime(int *fineTicks) const 169 | { 170 | return getNTFSTime(extra, 8, fineTicks); 171 | } 172 | 173 | QDateTime QuaZipFileInfo64::getNTFScTime(int *fineTicks) const 174 | { 175 | return getNTFSTime(extra, 16, fineTicks); 176 | } 177 | -------------------------------------------------------------------------------- /lib/quazipfileinfo.h: -------------------------------------------------------------------------------- 1 | #ifndef QUA_ZIPFILEINFO_H 2 | #define QUA_ZIPFILEINFO_H 3 | 4 | /* 5 | Copyright (C) 2005-2014 Sergey A. Tachenov 6 | 7 | This file is part of QuaZIP. 8 | 9 | QuaZIP is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU Lesser General Public License as published by 11 | the Free Software Foundation, either version 2.1 of the License, or 12 | (at your option) any later version. 13 | 14 | QuaZIP is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with QuaZIP. If not, see . 21 | 22 | See COPYING file for the full LGPL text. 23 | 24 | Original ZIP package is copyrighted by Gilles Vollant and contributors, 25 | see quazip/(un)zip.h files for details. Basically it's the zlib license. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include "quazip_global.h" 33 | 34 | /// Information about a file inside archive. 35 | /** 36 | * \deprecated Use QuaZipFileInfo64 instead. Not only it supports large files, 37 | * but also more convenience methods as well. 38 | * 39 | * Call QuaZip::getCurrentFileInfo() or QuaZipFile::getFileInfo() to 40 | * fill this structure. */ 41 | struct QUAZIP_EXPORT QuaZipFileInfo { 42 | /// File name. 43 | QString name; 44 | /// Version created by. 45 | quint16 versionCreated; 46 | /// Version needed to extract. 47 | quint16 versionNeeded; 48 | /// General purpose flags. 49 | quint16 flags; 50 | /// Compression method. 51 | quint16 method; 52 | /// Last modification date and time. 53 | QDateTime dateTime; 54 | /// CRC. 55 | quint32 crc; 56 | /// Compressed file size. 57 | quint32 compressedSize; 58 | /// Uncompressed file size. 59 | quint32 uncompressedSize; 60 | /// Disk number start. 61 | quint16 diskNumberStart; 62 | /// Internal file attributes. 63 | quint16 internalAttr; 64 | /// External file attributes. 65 | quint32 externalAttr; 66 | /// Comment. 67 | QString comment; 68 | /// Extra field. 69 | QByteArray extra; 70 | /// Get the file permissions. 71 | /** 72 | Returns the high 16 bits of external attributes converted to 73 | QFile::Permissions. 74 | */ 75 | QFile::Permissions getPermissions() const; 76 | }; 77 | 78 | /// Information about a file inside archive (with zip64 support). 79 | /** Call QuaZip::getCurrentFileInfo() or QuaZipFile::getFileInfo() to 80 | * fill this structure. */ 81 | struct QUAZIP_EXPORT QuaZipFileInfo64 { 82 | /// File name. 83 | QString name; 84 | /// Version created by. 85 | quint16 versionCreated; 86 | /// Version needed to extract. 87 | quint16 versionNeeded; 88 | /// General purpose flags. 89 | quint16 flags; 90 | /// Compression method. 91 | quint16 method; 92 | /// Last modification date and time. 93 | /** 94 | * This is the time stored in the standard ZIP header. This format only allows 95 | * to store time with 2-second precision, so the seconds will always be even 96 | * and the milliseconds will always be zero. If you need more precise 97 | * date and time, you can try to call the getNTFSmTime() function or 98 | * its siblings, provided that the archive itself contains these NTFS times. 99 | */ 100 | QDateTime dateTime; 101 | /// CRC. 102 | quint32 crc; 103 | /// Compressed file size. 104 | quint64 compressedSize; 105 | /// Uncompressed file size. 106 | quint64 uncompressedSize; 107 | /// Disk number start. 108 | quint16 diskNumberStart; 109 | /// Internal file attributes. 110 | quint16 internalAttr; 111 | /// External file attributes. 112 | quint32 externalAttr; 113 | /// Comment. 114 | QString comment; 115 | /// Extra field. 116 | QByteArray extra; 117 | /// Get the file permissions. 118 | /** 119 | Returns the high 16 bits of external attributes converted to 120 | QFile::Permissions. 121 | */ 122 | QFile::Permissions getPermissions() const; 123 | /// Converts to QuaZipFileInfo 124 | /** 125 | If any of the fields are greater than 0xFFFFFFFFu, they are set to 126 | 0xFFFFFFFFu exactly, not just truncated. This function should be mainly used 127 | for compatibility with the old code expecting QuaZipFileInfo, in the cases 128 | when it's impossible or otherwise unadvisable (due to ABI compatibility 129 | reasons, for example) to modify that old code to use QuaZipFileInfo64. 130 | 131 | \return \c true if all fields converted correctly, \c false if an overflow 132 | occured. 133 | */ 134 | bool toQuaZipFileInfo(QuaZipFileInfo &info) const; 135 | /// Returns the NTFS modification time 136 | /** 137 | * The getNTFS*Time() functions only work if there is an NTFS extra field 138 | * present. Otherwise, they all return invalid null timestamps. 139 | * @param fineTicks If not NULL, the fractional part of milliseconds returned 140 | * there, measured in 100-nanosecond ticks. Will be set to 141 | * zero if there is no NTFS extra field. 142 | * @sa dateTime 143 | * @sa getNTFSaTime() 144 | * @sa getNTFScTime() 145 | * @return The NTFS modification time, UTC 146 | */ 147 | QDateTime getNTFSmTime(int *fineTicks = NULL) const; 148 | /// Returns the NTFS access time 149 | /** 150 | * The getNTFS*Time() functions only work if there is an NTFS extra field 151 | * present. Otherwise, they all return invalid null timestamps. 152 | * @param fineTicks If not NULL, the fractional part of milliseconds returned 153 | * there, measured in 100-nanosecond ticks. Will be set to 154 | * zero if there is no NTFS extra field. 155 | * @sa dateTime 156 | * @sa getNTFSmTime() 157 | * @sa getNTFScTime() 158 | * @return The NTFS access time, UTC 159 | */ 160 | QDateTime getNTFSaTime(int *fineTicks = NULL) const; 161 | /// Returns the NTFS creation time 162 | /** 163 | * The getNTFS*Time() functions only work if there is an NTFS extra field 164 | * present. Otherwise, they all return invalid null timestamps. 165 | * @param fineTicks If not NULL, the fractional part of milliseconds returned 166 | * there, measured in 100-nanosecond ticks. Will be set to 167 | * zero if there is no NTFS extra field. 168 | * @sa dateTime 169 | * @sa getNTFSmTime() 170 | * @sa getNTFSaTime() 171 | * @return The NTFS creation time, UTC 172 | */ 173 | QDateTime getNTFScTime(int *fineTicks = NULL) const; 174 | /// Checks whether the file is encrypted. 175 | bool isEncrypted() const {return (flags & 1) != 0;} 176 | }; 177 | 178 | #endif 179 | -------------------------------------------------------------------------------- /lib/quazipnewinfo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2005-2014 Sergey A. Tachenov 3 | 4 | This file is part of QuaZIP. 5 | 6 | QuaZIP is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | QuaZIP is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with QuaZIP. If not, see . 18 | 19 | See COPYING file for the full LGPL text. 20 | 21 | Original ZIP package is copyrighted by Gilles Vollant and contributors, 22 | see quazip/(un)zip.h files for details. Basically it's the zlib license. 23 | */ 24 | 25 | #include 26 | 27 | #include "quazipnewinfo.h" 28 | 29 | #include 30 | 31 | static void QuaZipNewInfo_setPermissions(QuaZipNewInfo *info, 32 | QFile::Permissions perm, bool isDir, bool isSymLink = false) 33 | { 34 | quint32 uPerm = isDir ? 0040000 : 0100000; 35 | 36 | if ( isSymLink ) { 37 | #ifdef Q_OS_WIN 38 | uPerm = 0200000; 39 | #else 40 | uPerm = 0120000; 41 | #endif 42 | } 43 | 44 | if ((perm & QFile::ReadOwner) != 0) 45 | uPerm |= 0400; 46 | if ((perm & QFile::WriteOwner) != 0) 47 | uPerm |= 0200; 48 | if ((perm & QFile::ExeOwner) != 0) 49 | uPerm |= 0100; 50 | if ((perm & QFile::ReadGroup) != 0) 51 | uPerm |= 0040; 52 | if ((perm & QFile::WriteGroup) != 0) 53 | uPerm |= 0020; 54 | if ((perm & QFile::ExeGroup) != 0) 55 | uPerm |= 0010; 56 | if ((perm & QFile::ReadOther) != 0) 57 | uPerm |= 0004; 58 | if ((perm & QFile::WriteOther) != 0) 59 | uPerm |= 0002; 60 | if ((perm & QFile::ExeOther) != 0) 61 | uPerm |= 0001; 62 | info->externalAttr = (info->externalAttr & ~0xFFFF0000u) | (uPerm << 16); 63 | } 64 | 65 | template 66 | void QuaZipNewInfo_init(QuaZipNewInfo &self, const FileInfo &existing) 67 | { 68 | self.name = existing.name; 69 | self.dateTime = existing.dateTime; 70 | self.internalAttr = existing.internalAttr; 71 | self.externalAttr = existing.externalAttr; 72 | self.comment = existing.comment; 73 | self.extraLocal = existing.extra; 74 | self.extraGlobal = existing.extra; 75 | self.uncompressedSize = existing.uncompressedSize; 76 | } 77 | 78 | QuaZipNewInfo::QuaZipNewInfo(const QuaZipFileInfo &existing) 79 | { 80 | QuaZipNewInfo_init(*this, existing); 81 | } 82 | 83 | QuaZipNewInfo::QuaZipNewInfo(const QuaZipFileInfo64 &existing) 84 | { 85 | QuaZipNewInfo_init(*this, existing); 86 | } 87 | 88 | QuaZipNewInfo::QuaZipNewInfo(const QString& name): 89 | name(name), dateTime(QDateTime::currentDateTime()), internalAttr(0), externalAttr(0), 90 | uncompressedSize(0) 91 | { 92 | } 93 | 94 | QuaZipNewInfo::QuaZipNewInfo(const QString& name, const QString& file): 95 | name(name), internalAttr(0), externalAttr(0), uncompressedSize(0) 96 | { 97 | QFileInfo info(file); 98 | QDateTime lm = info.lastModified(); 99 | if (!info.exists()) { 100 | dateTime = QDateTime::currentDateTime(); 101 | } else { 102 | dateTime = lm; 103 | QuaZipNewInfo_setPermissions(this, info.permissions(), info.isDir(), info.isSymLink()); 104 | } 105 | } 106 | 107 | void QuaZipNewInfo::setFileDateTime(const QString& file) 108 | { 109 | QFileInfo info(file); 110 | QDateTime lm = info.lastModified(); 111 | if (info.exists()) 112 | dateTime = lm; 113 | } 114 | 115 | void QuaZipNewInfo::setFilePermissions(const QString &file) 116 | { 117 | QFileInfo info = QFileInfo(file); 118 | QFile::Permissions perm = info.permissions(); 119 | QuaZipNewInfo_setPermissions(this, perm, info.isDir(), info.isSymLink()); 120 | } 121 | 122 | void QuaZipNewInfo::setPermissions(QFile::Permissions permissions) 123 | { 124 | QuaZipNewInfo_setPermissions(this, permissions, name.endsWith('/')); 125 | } 126 | 127 | void QuaZipNewInfo::setFileNTFSTimes(const QString &fileName) 128 | { 129 | QFileInfo fi(fileName); 130 | if (!fi.exists()) { 131 | qWarning("QuaZipNewInfo::setFileNTFSTimes(): '%s' doesn't exist", 132 | fileName.toUtf8().constData()); 133 | return; 134 | } 135 | setFileNTFSmTime(fi.lastModified()); 136 | setFileNTFSaTime(fi.lastRead()); 137 | setFileNTFScTime(fi.created()); 138 | } 139 | 140 | static void setNTFSTime(QByteArray &extra, const QDateTime &time, int position, 141 | int fineTicks) { 142 | int ntfsPos = -1, timesPos = -1; 143 | unsigned ntfsLength = 0, ntfsTimesLength = 0; 144 | for (int i = 0; i <= extra.size() - 4; ) { 145 | unsigned type = static_cast(static_cast( 146 | extra.at(i))) 147 | | (static_cast(static_cast( 148 | extra.at(i + 1))) << 8); 149 | i += 2; 150 | unsigned length = static_cast(static_cast( 151 | extra.at(i))) 152 | | (static_cast(static_cast( 153 | extra.at(i + 1))) << 8); 154 | i += 2; 155 | if (type == QUAZIP_EXTRA_NTFS_MAGIC) { 156 | ntfsPos = i - 4; // the beginning of the NTFS record 157 | ntfsLength = length; 158 | if (length <= 4) { 159 | break; // no times in the NTFS record 160 | } 161 | i += 4; // reserved 162 | while (i <= extra.size() - 4) { 163 | unsigned tag = static_cast( 164 | static_cast(extra.at(i))) 165 | | (static_cast( 166 | static_cast(extra.at(i + 1))) 167 | << 8); 168 | i += 2; 169 | unsigned tagsize = static_cast( 170 | static_cast(extra.at(i))) 171 | | (static_cast( 172 | static_cast(extra.at(i + 1))) 173 | << 8); 174 | i += 2; 175 | if (tag == QUAZIP_EXTRA_NTFS_TIME_MAGIC) { 176 | timesPos = i - 4; // the beginning of the NTFS times tag 177 | ntfsTimesLength = tagsize; 178 | break; 179 | } else { 180 | i += tagsize; 181 | } 182 | } 183 | break; // I ain't going to search for yet another NTFS record! 184 | } else { 185 | i += length; 186 | } 187 | } 188 | if (ntfsPos == -1) { 189 | // No NTFS record, need to create one. 190 | ntfsPos = extra.size(); 191 | ntfsLength = 32; 192 | extra.resize(extra.size() + 4 + ntfsLength); 193 | // the NTFS record header 194 | extra[ntfsPos] = static_cast(QUAZIP_EXTRA_NTFS_MAGIC); 195 | extra[ntfsPos + 1] = static_cast(QUAZIP_EXTRA_NTFS_MAGIC >> 8); 196 | extra[ntfsPos + 2] = 32; // the 2-byte size in LittleEndian 197 | extra[ntfsPos + 3] = 0; 198 | // zero the record 199 | memset(extra.data() + ntfsPos + 4, 0, 32); 200 | timesPos = ntfsPos + 8; 201 | // now set the tag data 202 | extra[timesPos] = static_cast(QUAZIP_EXTRA_NTFS_TIME_MAGIC); 203 | extra[timesPos + 1] = static_cast(QUAZIP_EXTRA_NTFS_TIME_MAGIC 204 | >> 8); 205 | // the size: 206 | extra[timesPos + 2] = 24; 207 | extra[timesPos + 3] = 0; 208 | ntfsTimesLength = 24; 209 | } 210 | if (timesPos == -1) { 211 | // No time tag in the NTFS record, need to add one. 212 | timesPos = ntfsPos + 4 + ntfsLength; 213 | extra.resize(extra.size() + 28); 214 | // Now we need to move the rest of the field 215 | // (possibly zero bytes, but memmove() is OK with that). 216 | // 0 ......... ntfsPos .. ntfsPos + 4 ... timesPos 217 | //
218 | memmove(extra.data() + timesPos + 28, extra.data() + timesPos, 219 | extra.size() - 28 - timesPos); 220 | ntfsLength += 28; 221 | // now set the tag data 222 | extra[timesPos] = static_cast(QUAZIP_EXTRA_NTFS_TIME_MAGIC); 223 | extra[timesPos + 1] = static_cast(QUAZIP_EXTRA_NTFS_TIME_MAGIC 224 | >> 8); 225 | // the size: 226 | extra[timesPos + 2] = 24; 227 | extra[timesPos + 3] = 0; 228 | // zero the record 229 | memset(extra.data() + timesPos + 4, 0, 24); 230 | ntfsTimesLength = 24; 231 | } 232 | if (ntfsTimesLength < 24) { 233 | // Broken times field. OK, this is really unlikely, but just in case... 234 | size_t timesEnd = timesPos + 4 + ntfsTimesLength; 235 | extra.resize(extra.size() + (24 - ntfsTimesLength)); 236 | // Move it! 237 | // 0 ......... timesPos .... timesPos + 4 .. timesEnd 238 | //