mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-17 19:34:13 +02:00
2bd19e04be
A .qetz that does not open as it is -- a picture's file missing (as the title-change fault wrote them), a folio file missing, a row deleted from project.sqlite by hand (issue #1458), a damaged database -- was refused whole, and nothing in QElectroTech could get anything back. QetContainer::recover() reads what it can and says what it left out: an entry that cannot be unpacked, a missing folio file or picture, a symbol or wire that does not match the database, and, when the database cannot be read at all, the information it held (the wires go too, as it holds their ends). join(), restore() and QetZip::fromBytes() take an optional list for this; given none they refuse as before. `qelectrotech --recover damaged.qetz out.qet` writes what was read to a .qet and lists what was left out. Measured on industrial (50 folios, 618 symbols, 671 wires): a wire row deleted -> 670 wires, the rest whole; a folio file missing -> 49 folios; a database page overwritten -> every folio and symbol drawn, no wires and no symbol information. A zip cut short (no central directory) still cannot be read. Tests: recoverLeavesOutOnlyTheDamage (nothing, folio file, wire row, database page), recoverMissingPicture, recoverNotAZipRefused; they fail with the database side kept strict. The strict cases pass unchanged. ctest 106/106. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
58 lines
2.0 KiB
C++
58 lines
2.0 KiB
C++
/*
|
|
Copyright 2006-2026 The QElectroTech Team
|
|
This file is part of QElectroTech.
|
|
|
|
QElectroTech is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
QElectroTech 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
#ifndef QETZIP_H
|
|
#define QETZIP_H
|
|
|
|
#include <QByteArray>
|
|
#include <QList>
|
|
#include <QString>
|
|
#include <QStringList>
|
|
|
|
/**
|
|
@brief The QetZip namespace
|
|
Reads and writes the zip file a .qetz project is stored in: plain ZIP,
|
|
Deflate, as ODF and OOXML documents are, so any unzip tool opens it.
|
|
A whole archive is read into, or written from, memory -- projects are
|
|
megabytes, not gigabytes -- and written through QSaveFile, so a failed
|
|
save leaves the previous file as it was.
|
|
|
|
Every entry is dated 1 Jan 1980 00:00, not the time of saving: saving
|
|
the same project twice gives the same bytes.
|
|
*/
|
|
namespace QetZip
|
|
{
|
|
struct Entry
|
|
{
|
|
QString name; ///< path inside the archive, '/'-separated
|
|
QByteArray data;
|
|
bool compress = true; ///< false: stored (pictures, the mimetype entry)
|
|
};
|
|
|
|
/// Largest archive read(): uncompressed total and entry count
|
|
constexpr qint64 MaxUncompressedSize = qint64(2) * 1024 * 1024 * 1024;
|
|
constexpr int MaxEntries = 100000;
|
|
|
|
bool write(const QString &path, const QList<Entry> &entries, QString *error = nullptr);
|
|
QByteArray toBytes(const QList<Entry> &entries, QString *error = nullptr);
|
|
bool read(const QString &path, QList<Entry> *entries, QString *error = nullptr);
|
|
bool fromBytes(const QByteArray &zip, QList<Entry> *entries, QString *error = nullptr,
|
|
QStringList *skipped = nullptr);
|
|
}
|
|
|
|
#endif // QETZIP_H
|