File indexing completed on 2024-04-21 03:52:34

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