File indexing completed on 2024-04-28 15:18:44

0001 /*
0002  *  SPDX-FileCopyrightText: 2002-2013 David Faure <faure@kde.org>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #include "kzip.h"
0008 #include "kcompressiondevice.h"
0009 
0010 #include <QCoreApplication>
0011 #include <QDebug>
0012 #include <QFile>
0013 
0014 #include <stdio.h>
0015 
0016 void recursive_print(const KArchiveDirectory *dir, const QString &path)
0017 {
0018     const QStringList lst = dir->entries();
0019     for (const QString &it : lst) {
0020         const KArchiveEntry *entry = dir->entry(it);
0021         printf("mode=%07o %s %s \"%s%s\" size: %lld pos: %lld isdir=%d%s",
0022                entry->permissions(),
0023                entry->user().toLatin1().constData(),
0024                entry->group().toLatin1().constData(),
0025                path.toLatin1().constData(),
0026                it.toLatin1().constData(),
0027                entry->isDirectory() ? 0 : (static_cast<const KArchiveFile *>(entry))->size(),
0028                entry->isDirectory() ? 0 : (static_cast<const KArchiveFile *>(entry))->position(),
0029                entry->isDirectory(),
0030                entry->symLinkTarget().isEmpty() ? "" : QStringLiteral(" symlink: %1").arg(entry->symLinkTarget()).toLatin1().constData());
0031 
0032         //    if (!entry->isDirectory()) printf("%d", (static_cast<const KArchiveFile *>(entry))->size());
0033         printf("\n");
0034         if (entry->isDirectory()) {
0035             recursive_print(static_cast<const KArchiveDirectory *>(entry), path + it + '/');
0036         }
0037     }
0038 }
0039 
0040 void recursive_transfer(const KArchiveDirectory *dir, const QString &path, KZip *zip)
0041 {
0042     const QStringList lst = dir->entries();
0043     for (const QString &it : lst) {
0044         const KArchiveEntry *e = dir->entry(it);
0045         qDebug() << "actual file: " << e->name();
0046         if (e->isFile()) {
0047             Q_ASSERT(e && e->isFile());
0048             const KArchiveFile *f = static_cast<const KArchiveFile *>(e);
0049             printf("FILE=%s\n", qPrintable(e->name()));
0050 
0051             QByteArray arr(f->data());
0052 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0053             printf("SIZE=%lli\n", arr.size());
0054 #else
0055             printf("SIZE=%i\n", arr.size());
0056 #endif
0057             QString str(arr);
0058             printf("DATA=%s\n", qPrintable(str));
0059 
0060             if (e->symLinkTarget().isEmpty()) {
0061                 zip->writeFile(path + e->name(), arr);
0062             } else {
0063                 zip->writeSymLink(path + e->name(), e->symLinkTarget());
0064             }
0065         } else if (e->isDirectory()) {
0066             recursive_transfer(static_cast<const KArchiveDirectory *>(e), path + e->name() + '/', zip);
0067         }
0068     }
0069 }
0070 
0071 static int doList(const QString &fileName)
0072 {
0073     KZip zip(fileName);
0074     if (!zip.open(QIODevice::ReadOnly)) {
0075         qWarning() << "Could not open" << fileName << "for reading. ZIP file doesn't exist or is invalid:" << zip.errorString();
0076         return 1;
0077     }
0078     const KArchiveDirectory *dir = zip.directory();
0079     recursive_print(dir, QString());
0080     zip.close();
0081     return 0;
0082 }
0083 
0084 static int doPrintAll(const QString &fileName)
0085 {
0086     KZip zip(fileName);
0087     qDebug() << "Opening zip file";
0088     if (!zip.open(QIODevice::ReadOnly)) {
0089         qWarning() << "Could not open" << fileName << "for reading. ZIP file doesn't exist or is invalid:" << zip.errorString();
0090         return 1;
0091     }
0092     const KArchiveDirectory *dir = zip.directory();
0093     qDebug() << "Listing toplevel of zip file";
0094     const QStringList lst = dir->entries();
0095     for (const QString &it : lst) {
0096         const KArchiveEntry *e = dir->entry(it);
0097         qDebug() << "Printing" << it;
0098         if (e->isFile()) {
0099             Q_ASSERT(e && e->isFile());
0100             const KArchiveFile *f = static_cast<const KArchiveFile *>(e);
0101             const QByteArray data(f->data());
0102 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0103             printf("SIZE=%lli\n", data.size());
0104 #else
0105             printf("SIZE=%i\n", data.size());
0106 #endif
0107             QString str = QString::fromUtf8(data);
0108             printf("DATA=%s\n", qPrintable(str));
0109         }
0110     }
0111     zip.close();
0112     return 0;
0113 }
0114 
0115 static int doSave(const QString &fileName)
0116 {
0117     KZip zip(fileName);
0118     if (!zip.open(QIODevice::WriteOnly)) {
0119         qWarning() << "Could not open" << fileName << "for writing:" << zip.errorString();
0120         return 1;
0121     }
0122 
0123     const QByteArray data = "This is the data for the main file";
0124     bool writeOk = zip.writeFile(QStringLiteral("maindoc.txt"), data);
0125     if (!writeOk) {
0126         qWarning() << "Write error (main file)";
0127         return 1;
0128     }
0129     const QByteArray data2 = "This is the data for the other file";
0130     writeOk = zip.writeFile(QStringLiteral("subdir/other.txt"), data2);
0131     if (!writeOk) {
0132         qWarning() << "Write error (other file)";
0133         return 1;
0134     }
0135     // writeOk = zip.addLocalFile("David.jpg", "picture.jpg");
0136     // if (!writeOk) {
0137     //    qWarning() << "Write error (picture)";
0138     //    return 1;
0139     //}
0140     return 0;
0141 }
0142 
0143 static int doLoad(const QString &fileName)
0144 {
0145     KZip zip(fileName);
0146     if (!zip.open(QIODevice::ReadOnly)) {
0147         qWarning() << "Could not open" << fileName << "for reading. ZIP file doesn't exist or is invalid:" << zip.errorString();
0148         return 1;
0149     }
0150     const KArchiveDirectory *dir = zip.directory();
0151     const KArchiveEntry *mainEntry = dir->entry(QStringLiteral("maindoc.txt"));
0152     Q_ASSERT(mainEntry && mainEntry->isFile());
0153     const KArchiveFile *mainFile = static_cast<const KArchiveFile *>(mainEntry);
0154     qDebug() << "maindoc.txt:" << mainFile->data();
0155     return 0;
0156 }
0157 
0158 static int doPrint(const QString &fileName, const QString &entryName)
0159 {
0160     KZip zip(fileName);
0161     if (!zip.open(QIODevice::ReadOnly)) {
0162         qWarning() << "Could not open" << fileName << "for reading. ZIP file doesn't exist or is invalid:" << zip.errorString();
0163         return 1;
0164     }
0165     const KArchiveDirectory *dir = zip.directory();
0166     const KArchiveEntry *e = dir->entry(entryName);
0167     Q_ASSERT(e && e->isFile());
0168     const KArchiveFile *f = static_cast<const KArchiveFile *>(e);
0169 
0170     const QByteArray arr(f->data());
0171 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0172     printf("SIZE=%lli\n", arr.size());
0173 #else
0174     printf("SIZE=%i\n", arr.size());
0175 #endif
0176 
0177     QString str = QString::fromUtf8(arr);
0178     printf("%s", qPrintable(str));
0179     return zip.close() ? 0 : 1 /*error*/;
0180 }
0181 
0182 static int doCreate(const QString &archiveName, const QStringList &fileNames)
0183 {
0184     KZip zip(archiveName);
0185     if (!zip.open(QIODevice::WriteOnly)) {
0186         qWarning() << "Could not open" << archiveName << "for writing:" << zip.errorString();
0187         return 1;
0188     }
0189     for (const QString &fileName : fileNames) {
0190         QFile f(fileName);
0191         if (!f.open(QIODevice::ReadOnly)) {
0192             qWarning() << "Could not open" << fileName << "for reading:" << zip.errorString();
0193             return 1;
0194         }
0195         zip.writeFile(fileName, f.readAll());
0196     }
0197     return zip.close() ? 0 : 1 /*error*/;
0198 }
0199 
0200 static int doUpdate(const QString &archiveName, const QString &fileName)
0201 {
0202     KZip zip(archiveName);
0203     if (!zip.open(QIODevice::ReadWrite)) {
0204         qWarning() << "Could not open" << archiveName << "for read/write:" << zip.errorString();
0205         return 1;
0206     }
0207 
0208     QFile f(fileName);
0209     if (!f.open(QIODevice::ReadOnly)) {
0210         qWarning() << "Could not open" << fileName << "for reading:" << zip.errorString();
0211         return 1;
0212     }
0213 
0214     zip.writeFile(fileName, f.readAll());
0215     return zip.close() ? 0 : 1 /*error*/;
0216 }
0217 
0218 static int doTransfer(const QString &sourceFile, const QString &destFile)
0219 {
0220     KZip zip1(sourceFile);
0221     KZip zip2(destFile);
0222     if (!zip1.open(QIODevice::ReadOnly)) {
0223         qWarning() << "Could not open" << sourceFile << "for reading. ZIP file doesn't exist or is invalid:" << zip1.errorString();
0224         return 1;
0225     }
0226     if (!zip2.open(QIODevice::WriteOnly)) {
0227         qWarning() << "Could not open" << destFile << "for writing:" << zip2.errorString();
0228         return 1;
0229     }
0230     const KArchiveDirectory *dir1 = zip1.directory();
0231 
0232     recursive_transfer(dir1, QLatin1String(""), &zip2);
0233 
0234     zip1.close();
0235     zip2.close();
0236     return 0;
0237 }
0238 
0239 static bool save(QIODevice *device)
0240 {
0241     const QByteArray data = "This is some text that will be compressed.\n";
0242     const int written = device->write(data);
0243     if (written != data.size()) {
0244         qWarning() << "Error writing data";
0245         return 1;
0246     }
0247     // success
0248     return 0;
0249 }
0250 
0251 static int doCompress(const QString &fileName)
0252 {
0253     KCompressionDevice device(fileName, KCompressionDevice::BZip2);
0254     if (!device.open(QIODevice::WriteOnly)) {
0255         qWarning() << "Could not open" << fileName << "for writing:" << device.errorString();
0256         return 1;
0257     }
0258 
0259     return save(&device);
0260 }
0261 
0262 static bool load(QIODevice *device)
0263 {
0264     const QByteArray data = device->readAll();
0265     printf("%s", data.constData());
0266     return true;
0267 }
0268 
0269 static int doUncompress(const QString &fileName)
0270 {
0271     KCompressionDevice device(fileName, KCompressionDevice::BZip2);
0272     if (!device.open(QIODevice::ReadOnly)) {
0273         qWarning() << "Could not open" << fileName << "for reading:" << device.errorString();
0274         return 1;
0275     }
0276     return load(&device);
0277 }
0278 
0279 int main(int argc, char **argv)
0280 {
0281     if (argc < 3) {
0282         // ###### Note: please consider adding new tests to karchivetest (so that they can be automated)
0283         // rather than here (interactive)
0284         printf(
0285             "\n"
0286             " Usage :\n"
0287             " ./kziptest list /path/to/existing_file.zip       tests listing an existing zip\n"
0288             " ./kziptest print-all file.zip                    prints contents of all files.\n"
0289             " ./kziptest print file.zip filename               prints contents of one file.\n"
0290             " ./kziptest create file.zip filenames             create a new zip file with these files.\n"
0291             " ./kziptest update file.zip filename              update filename in file.zip.\n"
0292             " ./kziptest save file.zip                         save file.\n"
0293             " ./kziptest load file.zip                         load file.\n"
0294             " ./kziptest write file.bz2                        write compressed file.\n"
0295             " ./kziptest read file.bz2                         read uncompressed file.\n");
0296         return 1;
0297     }
0298     QCoreApplication app(argc, argv);
0299     QString command = argv[1];
0300     if (command == QLatin1String("list")) {
0301         return doList(QFile::decodeName(argv[2]));
0302     } else if (command == QLatin1String("print-all")) {
0303         return doPrintAll(QFile::decodeName(argv[2]));
0304     } else if (command == QLatin1String("print")) {
0305         if (argc != 4) {
0306             printf("usage: kziptest print archivename filename");
0307             return 1;
0308         }
0309         return doPrint(QFile::decodeName(argv[2]), argv[3]);
0310     } else if (command == QLatin1String("save")) {
0311         return doSave(QFile::decodeName(argv[2]));
0312     } else if (command == QLatin1String("load")) {
0313         return doLoad(QFile::decodeName(argv[2]));
0314     } else if (command == QLatin1String("write")) {
0315         return doCompress(QFile::decodeName(argv[2]));
0316     } else if (command == QLatin1String("read")) {
0317         return doUncompress(QFile::decodeName(argv[2]));
0318     } else if (command == QLatin1String("create")) {
0319         if (argc < 4) {
0320             printf("usage: kziptest create archivename filenames");
0321             return 1;
0322         }
0323         const QStringList fileNames = app.arguments().mid(3);
0324         return doCreate(QFile::decodeName(argv[2]), fileNames);
0325     } else if (command == QLatin1String("update")) {
0326         if (argc != 4) {
0327             printf("usage: kziptest update archivename filename");
0328             return 1;
0329         }
0330         return doUpdate(QFile::decodeName(argv[2]), QFile::decodeName(argv[3]));
0331     } else if (command == QLatin1String("transfer")) {
0332         if (argc != 4) {
0333             printf("usage: kziptest transfer sourcefile destfile");
0334             return 1;
0335         }
0336         return doTransfer(QFile::decodeName(argv[2]), QFile::decodeName(argv[3]));
0337     } else {
0338         printf("Unknown command\n");
0339     }
0340 }