mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2026-03-11 08:54:48 +00:00
* minizip-ng has slightly different defines and function names than the original minizip. These changes adapt the existing code to use the minizip-ng versions if necessary.
101 lines
3.6 KiB
C++
101 lines
3.6 KiB
C++
/*
|
|
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
|
|
*
|
|
* This program 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 or (at your option)
|
|
* version 3 of the License.
|
|
*
|
|
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
#include "ShareImport.h"
|
|
#include "core/Merger.h"
|
|
#include "format/KeePass2Reader.h"
|
|
#include "keeshare/KeeShare.h"
|
|
#include "keys/PasswordKey.h"
|
|
|
|
#include <QBuffer>
|
|
#include <minizip/unzip.h>
|
|
|
|
namespace
|
|
{
|
|
QByteArray readZipFile(void* uf)
|
|
{
|
|
QByteArray data;
|
|
int bytes, bytesRead = 0;
|
|
unzOpenCurrentFile(uf);
|
|
do {
|
|
data.resize(data.size() + 8192);
|
|
bytes = unzReadCurrentFile(uf, data.data() + bytesRead, 8192);
|
|
if (bytes > 0) {
|
|
bytesRead += bytes;
|
|
}
|
|
} while (bytes > 0);
|
|
unzCloseCurrentFile(uf);
|
|
data.truncate(bytesRead);
|
|
return data;
|
|
}
|
|
} // namespace
|
|
|
|
ShareObserver::Result ShareImport::containerInto(const QString& resolvedPath,
|
|
const KeeShareSettings::Reference& reference,
|
|
Group* targetGroup)
|
|
{
|
|
QByteArray dbData;
|
|
|
|
auto uf = unzOpen64(resolvedPath.toLatin1().constData());
|
|
if (uf) {
|
|
// Open zip share, extract database portion, ignore signature file
|
|
char zipFileName[256];
|
|
auto err = unzGoToFirstFile(uf);
|
|
while (err == UNZ_OK) {
|
|
unzGetCurrentFileInfo64(uf, nullptr, zipFileName, sizeof(zipFileName), nullptr, 0, nullptr, 0);
|
|
if (QString(zipFileName).compare(KeeShare::containerFileName()) == 0) {
|
|
dbData = readZipFile(uf);
|
|
}
|
|
err = unzGoToNextFile(uf);
|
|
}
|
|
unzClose(uf);
|
|
} else {
|
|
// Open KDBX file directly
|
|
QFile file(resolvedPath);
|
|
if (!file.open(QIODevice::ReadOnly)) {
|
|
qCritical("Unable to open file %s.", qPrintable(reference.path));
|
|
return {reference.path, ShareObserver::Result::Error, file.errorString()};
|
|
}
|
|
dbData = file.readAll();
|
|
file.close();
|
|
}
|
|
|
|
QBuffer buffer(&dbData);
|
|
buffer.open(QIODevice::ReadOnly);
|
|
|
|
KeePass2Reader reader;
|
|
auto key = QSharedPointer<CompositeKey>::create();
|
|
key->addKey(QSharedPointer<PasswordKey>::create(reference.password));
|
|
auto sourceDb = QSharedPointer<Database>::create();
|
|
if (!reader.readDatabase(&buffer, key, sourceDb.data())) {
|
|
qCritical("Error while parsing the database: %s", qPrintable(reader.errorString()));
|
|
return {reference.path, ShareObserver::Result::Error, reader.errorString()};
|
|
}
|
|
|
|
qDebug("Synchronize %s %s with %s",
|
|
qPrintable(reference.path),
|
|
qPrintable(targetGroup->name()),
|
|
qPrintable(sourceDb->rootGroup()->name()));
|
|
|
|
Merger merger(sourceDb->rootGroup(), targetGroup);
|
|
merger.setForcedMergeMode(Group::Synchronize);
|
|
auto changelist = merger.merge();
|
|
if (!changelist.isEmpty()) {
|
|
return {reference.path, ShareObserver::Result::Success, ShareImport::tr("Successful import")};
|
|
}
|
|
|
|
return {};
|
|
}
|