File indexing completed on 2025-01-26 04:24:52

0001 /*
0002 Copyright (C) 2010 Roberto Pompermaier
0003 Copyright (C) 2005-2014 Sergey A. Tachenov
0004 
0005 This file is part of QuaZIP.
0006 
0007 QuaZIP is free software: you can redistribute it and/or modify
0008 it under the terms of the GNU Lesser General Public License as published by
0009 the Free Software Foundation, either version 2.1 of the License, or
0010 (at your option) any later version.
0011 
0012 QuaZIP is distributed in the hope that it will be useful,
0013 but WITHOUT ANY WARRANTY; without even the implied warranty of
0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0015 GNU Lesser General Public License for more details.
0016 
0017 You should have received a copy of the GNU Lesser General Public License
0018 along with QuaZIP.  If not, see <http://www.gnu.org/licenses/>.
0019 
0020 See COPYING file for the full LGPL text.
0021 
0022 Original ZIP package is copyrighted by Gilles Vollant and contributors,
0023 see quazip/(un)zip.h files for details. Basically it's the zlib license.
0024 */
0025 
0026 #include "JlCompress.h"
0027 #include <QDebug>
0028 
0029 static bool copyData(QIODevice &inFile, QIODevice &outFile)
0030 {
0031     while (!inFile.atEnd()) {
0032         char buf[4096];
0033         qint64 readLen = inFile.read(buf, 4096);
0034         if (readLen <= 0)
0035             return false;
0036         if (outFile.write(buf, readLen) != readLen)
0037             return false;
0038     }
0039     return true;
0040 }
0041 
0042 bool JlCompress::compressFile(QuaZip* zip, QString fileName, QString fileDest) {
0043     // zip: oggetto dove aggiungere il file
0044     // fileName: nome del file reale
0045     // fileDest: nome del file all'interno del file compresso
0046 
0047     // Controllo l'apertura dello zip
0048     if (!zip) return false;
0049     if (zip->getMode()!=QuaZip::mdCreate &&
0050         zip->getMode()!=QuaZip::mdAppend &&
0051         zip->getMode()!=QuaZip::mdAdd) return false;
0052 
0053     // Apro il file originale
0054     QFile inFile;
0055     inFile.setFileName(fileName);
0056     if(!inFile.open(QIODevice::ReadOnly)) return false;
0057 
0058     // Apro il file risulato
0059     QuaZipFile outFile(zip);
0060     if(!outFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileDest, inFile.fileName()))) return false;
0061 
0062     // Copio i dati
0063     if (!copyData(inFile, outFile) || outFile.getZipError()!=UNZ_OK) {
0064         return false;
0065     }
0066 
0067     // Chiudo i file
0068     outFile.close();
0069     if (outFile.getZipError()!=UNZ_OK) return false;
0070     inFile.close();
0071 
0072     return true;
0073 }
0074 
0075 bool JlCompress::compressSubDir(QuaZip* zip, QString dir, QString origDir, bool recursive, QDir::Filters filters) {
0076     // zip: oggetto dove aggiungere il file
0077     // dir: cartella reale corrente
0078     // origDir: cartella reale originale
0079     // (path(dir)-path(origDir)) = path interno all'oggetto zip
0080 
0081     // Controllo l'apertura dello zip
0082     if (!zip) return false;
0083     if (zip->getMode()!=QuaZip::mdCreate &&
0084         zip->getMode()!=QuaZip::mdAppend &&
0085         zip->getMode()!=QuaZip::mdAdd) return false;
0086 
0087     // Controllo la cartella
0088     QDir directory(dir);
0089     if (!directory.exists()) return false;
0090 
0091     QDir origDirectory(origDir);
0092     if (dir != origDir) {
0093         QuaZipFile dirZipFile(zip);
0094         if (!dirZipFile.open(QIODevice::WriteOnly,
0095             QuaZipNewInfo(origDirectory.relativeFilePath(dir) + "/", dir), 0, 0, 0)) {
0096                 return false;
0097         }
0098         dirZipFile.close();
0099     }
0100 
0101 
0102     // Se comprimo anche le sotto cartelle
0103     if (recursive) {
0104         // Per ogni sotto cartella
0105         QFileInfoList files = directory.entryInfoList(QDir::AllDirs|QDir::NoDotAndDotDot|filters);
0106         Q_FOREACH (QFileInfo file, files) {
0107             // Comprimo la sotto cartella
0108             if(!compressSubDir(zip,file.absoluteFilePath(),origDir,recursive,filters)) return false;
0109         }
0110     }
0111 
0112     // Per ogni file nella cartella
0113     QFileInfoList files = directory.entryInfoList(QDir::Files|filters);
0114     Q_FOREACH (QFileInfo file, files) {
0115         // Se non e un file o e il file compresso che sto creando
0116         if(!file.isFile()||file.absoluteFilePath()==zip->getZipName()) continue;
0117 
0118         // Creo il nome relativo da usare all'interno del file compresso
0119         QString filename = origDirectory.relativeFilePath(file.absoluteFilePath());
0120 
0121         // Comprimo il file
0122         if (!compressFile(zip,file.absoluteFilePath(),filename)) return false;
0123     }
0124 
0125     return true;
0126 }
0127 
0128 bool JlCompress::extractFile(QuaZip* zip, QString fileName, QString fileDest) {
0129     // zip: oggetto dove aggiungere il file
0130     // filename: nome del file reale
0131     // fileincompress: nome del file all'interno del file compresso
0132 
0133     // Controllo l'apertura dello zip
0134     if (!zip) return false;
0135     if (zip->getMode()!=QuaZip::mdUnzip) return false;
0136 
0137     // Apro il file compresso
0138     if (!fileName.isEmpty())
0139         zip->setCurrentFile(fileName);
0140     QuaZipFile inFile(zip);
0141     if(!inFile.open(QIODevice::ReadOnly) || inFile.getZipError()!=UNZ_OK) return false;
0142 
0143     // Controllo esistenza cartella file risultato
0144     QDir curDir;
0145     if (fileDest.endsWith('/')) {
0146         if (!curDir.mkpath(fileDest)) {
0147             return false;
0148         }
0149     } else {
0150         if (!curDir.mkpath(QFileInfo(fileDest).absolutePath())) {
0151             return false;
0152         }
0153     }
0154 
0155     QuaZipFileInfo64 info;
0156     if (!zip->getCurrentFileInfo(&info))
0157         return false;
0158 
0159     QFile::Permissions srcPerm = info.getPermissions();
0160     if (fileDest.endsWith('/') && QFileInfo(fileDest).isDir()) {
0161         if (srcPerm != 0) {
0162             QFile(fileDest).setPermissions(srcPerm);
0163         }
0164         return true;
0165     }
0166 
0167     // Apro il file risultato
0168     QFile outFile;
0169     outFile.setFileName(fileDest);
0170     if(!outFile.open(QIODevice::WriteOnly)) return false;
0171 
0172     // Copio i dati
0173     if (!copyData(inFile, outFile) || inFile.getZipError()!=UNZ_OK) {
0174         outFile.close();
0175         removeFile(QStringList(fileDest));
0176         return false;
0177     }
0178     outFile.close();
0179 
0180     // Chiudo i file
0181     inFile.close();
0182     if (inFile.getZipError()!=UNZ_OK) {
0183         removeFile(QStringList(fileDest));
0184         return false;
0185     }
0186 
0187     if (srcPerm != 0) {
0188         outFile.setPermissions(srcPerm);
0189     }
0190     return true;
0191 }
0192 
0193 bool JlCompress::removeFile(QStringList listFile) {
0194     bool ret = true;
0195     // Per ogni file
0196     for (int i=0; i<listFile.count(); i++) {
0197         // Lo elimino
0198         ret = ret && QFile::remove(listFile.at(i));
0199     }
0200     return ret;
0201 }
0202 
0203 bool JlCompress::compressFile(QString fileCompressed, QString file) {
0204     // Creo lo zip
0205     QuaZip zip(fileCompressed);
0206     QDir().mkpath(QFileInfo(fileCompressed).absolutePath());
0207     if(!zip.open(QuaZip::mdCreate)) {
0208         QFile::remove(fileCompressed);
0209         return false;
0210     }
0211 
0212     // Aggiungo il file
0213     if (!compressFile(&zip,file,QFileInfo(file).fileName())) {
0214         QFile::remove(fileCompressed);
0215         return false;
0216     }
0217 
0218     // Chiudo il file zip
0219     zip.close();
0220     if(zip.getZipError()!=0) {
0221         QFile::remove(fileCompressed);
0222         return false;
0223     }
0224 
0225     return true;
0226 }
0227 
0228 bool JlCompress::compressFiles(QString fileCompressed, QStringList files) {
0229     // Creo lo zip
0230     QuaZip zip(fileCompressed);
0231     QDir().mkpath(QFileInfo(fileCompressed).absolutePath());
0232     if(!zip.open(QuaZip::mdCreate)) {
0233         QFile::remove(fileCompressed);
0234         return false;
0235     }
0236 
0237     // Comprimo i file
0238     QFileInfo info;
0239     Q_FOREACH (QString file, files) {
0240         info.setFile(file);
0241         if (!info.exists() || !compressFile(&zip,file,info.fileName())) {
0242             QFile::remove(fileCompressed);
0243             return false;
0244         }
0245     }
0246 
0247     // Chiudo il file zip
0248     zip.close();
0249     if(zip.getZipError()!=0) {
0250         QFile::remove(fileCompressed);
0251         return false;
0252     }
0253 
0254     return true;
0255 }
0256 
0257 bool JlCompress::compressDir(QString fileCompressed, QString dir, bool recursive) {
0258     return compressDir(fileCompressed, dir, recursive, 0);
0259 }
0260 
0261 bool JlCompress::compressDir(QString fileCompressed, QString dir,
0262                              bool recursive, QDir::Filters filters)
0263 {
0264     // Creo lo zip
0265     QuaZip zip(fileCompressed);
0266     QDir().mkpath(QFileInfo(fileCompressed).absolutePath());
0267     if(!zip.open(QuaZip::mdCreate)) {
0268         QFile::remove(fileCompressed);
0269         return false;
0270     }
0271 
0272     // Aggiungo i file e le sotto cartelle
0273     if (!compressSubDir(&zip,dir,dir,recursive, filters)) {
0274         QFile::remove(fileCompressed);
0275         return false;
0276     }
0277 
0278     // Chiudo il file zip
0279     zip.close();
0280     if(zip.getZipError()!=0) {
0281         QFile::remove(fileCompressed);
0282         return false;
0283     }
0284 
0285     return true;
0286 }
0287 
0288 QString JlCompress::extractFile(QString fileCompressed, QString fileName, QString fileDest) {
0289     // Apro lo zip
0290     QuaZip zip(fileCompressed);
0291     return extractFile(zip, fileName, fileDest);
0292 }
0293 
0294 QString JlCompress::extractFile(QuaZip &zip, QString fileName, QString fileDest)
0295 {
0296     if(!zip.open(QuaZip::mdUnzip)) {
0297         return QString();
0298     }
0299 
0300     // Estraggo il file
0301     if (fileDest.isEmpty())
0302         fileDest = fileName;
0303     if (!extractFile(&zip,fileName,fileDest)) {
0304         return QString();
0305     }
0306 
0307     // Chiudo il file zip
0308     zip.close();
0309     if(zip.getZipError()!=0) {
0310         removeFile(QStringList(fileDest));
0311         return QString();
0312     }
0313     return QFileInfo(fileDest).absoluteFilePath();
0314 }
0315 
0316 QStringList JlCompress::extractFiles(QString fileCompressed, QStringList files, QString dir) {
0317     // Creo lo zip
0318     QuaZip zip(fileCompressed);
0319     return extractFiles(zip, files, dir);
0320 }
0321 
0322 QStringList JlCompress::extractFiles(QuaZip &zip, const QStringList &files, const QString &dir)
0323 {
0324     if(!zip.open(QuaZip::mdUnzip)) {
0325         return QStringList();
0326     }
0327 
0328     // Estraggo i file
0329     QStringList extracted;
0330     for (int i=0; i<files.count(); i++) {
0331         QString absPath = QDir(dir).absoluteFilePath(files.at(i));
0332         if (!extractFile(&zip, files.at(i), absPath)) {
0333             removeFile(extracted);
0334             return QStringList();
0335         }
0336         extracted.append(absPath);
0337     }
0338 
0339     // Chiudo il file zip
0340     zip.close();
0341     if(zip.getZipError()!=0) {
0342         removeFile(extracted);
0343         return QStringList();
0344     }
0345 
0346     return extracted;
0347 }
0348 
0349 QStringList JlCompress::extractDir(QString fileCompressed, QString dir) {
0350     // Apro lo zip
0351     QuaZip zip(fileCompressed);
0352     return extractDir(zip, dir);
0353 }
0354 
0355 QStringList JlCompress::extractDir(QuaZip &zip, const QString &dir)
0356 {
0357     if(!zip.open(QuaZip::mdUnzip)) {
0358         return QStringList();
0359     }
0360 
0361     QDir directory(dir);
0362     QStringList extracted;
0363     if (!zip.goToFirstFile()) {
0364         return QStringList();
0365     }
0366     do {
0367         QString name = zip.getCurrentFileName();
0368         QString absFilePath = directory.absoluteFilePath(name);
0369         if (!extractFile(&zip, "", absFilePath)) {
0370             removeFile(extracted);
0371             return QStringList();
0372         }
0373         extracted.append(absFilePath);
0374     } while (zip.goToNextFile());
0375 
0376     // Chiudo il file zip
0377     zip.close();
0378     if(zip.getZipError()!=0) {
0379         removeFile(extracted);
0380         return QStringList();
0381     }
0382 
0383     return extracted;
0384 }
0385 
0386 QStringList JlCompress::getFileList(QString fileCompressed) {
0387     // Apro lo zip
0388     QuaZip* zip = new QuaZip(QFileInfo(fileCompressed).absoluteFilePath());
0389     return getFileList(zip);
0390 }
0391 
0392 QStringList JlCompress::getFileList(QuaZip *zip)
0393 {
0394     if(!zip->open(QuaZip::mdUnzip)) {
0395         delete zip;
0396         return QStringList();
0397     }
0398 
0399     // Estraggo i nomi dei file
0400     QStringList lst;
0401     QuaZipFileInfo64 info;
0402     for(bool more=zip->goToFirstFile(); more; more=zip->goToNextFile()) {
0403       if(!zip->getCurrentFileInfo(&info)) {
0404           delete zip;
0405           return QStringList();
0406       }
0407       lst << info.name;
0408       //info.name.toLocal8Bit().constData()
0409     }
0410 
0411     // Chiudo il file zip
0412     zip->close();
0413     if(zip->getZipError()!=0) {
0414         delete zip;
0415         return QStringList();
0416     }
0417     delete zip;
0418     return lst;
0419 }
0420 
0421 QStringList JlCompress::extractDir(QIODevice *ioDevice, QString dir)
0422 {
0423     QuaZip zip(ioDevice);
0424     return extractDir(zip, dir);
0425 }
0426 
0427 QStringList JlCompress::getFileList(QIODevice *ioDevice)
0428 {
0429     QuaZip *zip = new QuaZip(ioDevice);
0430     return getFileList(zip);
0431 }
0432 
0433 QString JlCompress::extractFile(QIODevice *ioDevice, QString fileName, QString fileDest)
0434 {
0435     QuaZip zip(ioDevice);
0436     return extractFile(zip, fileName, fileDest);
0437 }
0438 
0439 QStringList JlCompress::extractFiles(QIODevice *ioDevice, QStringList files, QString dir)
0440 {
0441     QuaZip zip(ioDevice);
0442     return extractFiles(zip, files, dir);
0443 }