Files
qelectrotech-source-mirror/sources/container/qetzip.h
T
ispyisail 2bd19e04be Add recovering what can be read of a damaged .qetz (--recover)
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>
2026-10-16 10:15:37 +13:00

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