diff --git a/src/kar.cpp b/src/kar.cpp index 2d66861..e8fa625 100644 --- a/src/kar.cpp +++ b/src/kar.cpp @@ -1,206 +1,206 @@ /* This file is part of the KDE libraries Copyright (C) 2002 Laurence Anderson This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kar.h" #include "karchive_p.h" #include "loggingcategory.h" #include #include #include "kfilterdev.h" //#include "klimitediodevice_p.h" //////////////////////////////////////////////////////////////////////// /////////////////////////// KAr /////////////////////////////////////// //////////////////////////////////////////////////////////////////////// class Q_DECL_HIDDEN KAr::KArPrivate { public: KArPrivate() { } }; KAr::KAr(const QString &filename) : KArchive(filename) , d(new KArPrivate) { } KAr::KAr(QIODevice *dev) : KArchive(dev) , d(new KArPrivate) { } KAr::~KAr() { if (isOpen()) { close(); } delete d; } bool KAr::doPrepareWriting(const QString &, const QString &, const QString &, qint64, mode_t, const QDateTime &, const QDateTime &, const QDateTime &) { setErrorString(tr("Cannot write to AR file")); qCWarning(KArchiveLog) << "doPrepareWriting not implemented for KAr"; return false; } bool KAr::doFinishWriting(qint64) { setErrorString(tr("Cannot write to AR file")); qCWarning(KArchiveLog) << "doFinishWriting not implemented for KAr"; return false; } bool KAr::doWriteDir(const QString &, const QString &, const QString &, mode_t, const QDateTime &, const QDateTime &, const QDateTime &) { setErrorString(tr("Cannot write to AR file")); qCWarning(KArchiveLog) << "doWriteDir not implemented for KAr"; return false; } bool KAr::doWriteSymLink(const QString &, const QString &, const QString &, const QString &, mode_t, const QDateTime &, const QDateTime &, const QDateTime &) { setErrorString(tr("Cannot write to AR file")); qCWarning(KArchiveLog) << "doWriteSymLink not implemented for KAr"; return false; } bool KAr::openArchive(QIODevice::OpenMode mode) { // Open archive if (mode == QIODevice::WriteOnly) { return true; } if (mode != QIODevice::ReadOnly && mode != QIODevice::ReadWrite) { setErrorString(tr("Unsupported mode %1").arg(mode)); return false; } QIODevice *dev = device(); if (!dev) { return false; } QByteArray magic = dev->read(7); if (magic != "!") { setErrorString(tr("Invalid main magic")); return false; } char *ar_longnames = nullptr; while (! dev->atEnd()) { QByteArray ar_header; ar_header.resize(60); dev->seek(dev->pos() + (2 - (dev->pos() % 2)) % 2); // Ar headers are padded to byte boundary if (dev->read(ar_header.data(), 60) != 60) { // Read ar header //qCWarning(KArchiveLog) << "Couldn't read header"; delete[] ar_longnames; //return false; return true; // Probably EOF / trailing junk } if (!ar_header.endsWith("`\n")) { // Check header magic // krazy:exclude=strings setErrorString(tr("Invalid magic")); delete[] ar_longnames; return false; } QByteArray name = ar_header.mid(0, 16); // Process header const int date = ar_header.mid(16, 12).trimmed().toInt(); //const int uid = ar_header.mid( 28, 6 ).trimmed().toInt(); //const int gid = ar_header.mid( 34, 6 ).trimmed().toInt(); const int mode = ar_header.mid(40, 8).trimmed().toInt(); const qint64 size = ar_header.mid(48, 10).trimmed().toInt(); if (size < 0) { setErrorString(tr("Invalid size")); delete[] ar_longnames; return false; } bool skip_entry = false; // Deal with special entries if (name.mid(0, 1) == "/") { if (name.mid(1, 1) == "/") { // Longfilename table entry delete[] ar_longnames; ar_longnames = new char[size + 1]; ar_longnames[size] = '\0'; dev->read(ar_longnames, size); skip_entry = true; //qCDebug(KArchiveLog) << "Read in longnames entry"; } else if (name.mid(1, 1) == " ") { // Symbol table entry //qCDebug(KArchiveLog) << "Skipped symbol entry"; dev->seek(dev->pos() + size); skip_entry = true; } else { // Longfilename //qCDebug(KArchiveLog) << "Longfilename #" << name.mid(1, 15).toInt(); if (! ar_longnames) { setErrorString(tr("Invalid longfilename reference")); delete[] ar_longnames; return false; } const int ar_longnamesIndex = name.mid(1, 15).toInt(); - if (ar_longnamesIndex >= size) { + if (ar_longnamesIndex < 0 || ar_longnamesIndex >= size) { setErrorString(tr("Invalid longfilename position reference")); delete[] ar_longnames; return false; } name = &ar_longnames[ar_longnamesIndex]; name = name.left(name.indexOf("/")); } } if (skip_entry) { continue; } name = name.trimmed(); // Process filename name.replace('/', QByteArray()); //qCDebug(KArchiveLog) << "Filename: " << name << " Size: " << size; KArchiveEntry *entry = new KArchiveFile(this, QString::fromLocal8Bit(name.constData()), mode, KArchivePrivate::time_tToDateTime(date), rootDir()->user(), rootDir()->group(), /*symlink*/ QString(), dev->pos(), size); rootDir()->addEntry(entry); // Ar files don't support directories, so everything in root dev->seek(dev->pos() + size); // Skip contents } delete[] ar_longnames; return true; } bool KAr::closeArchive() { // Close the archive return true; } void KAr::virtual_hook(int id, void *data) { KArchive::virtual_hook(id, data); }