mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
Enforce ShareObserver to resolve relative paths
ShareObserver now uses paths which are resolved relative to the referencing database.
This commit is contained in:
parent
c5a93ca215
commit
37c53f326c
@ -151,6 +151,12 @@ namespace
|
||||
return {UntrustedOnce, certificate};
|
||||
}
|
||||
|
||||
QString resolvePath(const QString& path, QSharedPointer<Database> database)
|
||||
{
|
||||
const QFileInfo info(database->filePath());
|
||||
return info.absoluteDir().absoluteFilePath(path);
|
||||
}
|
||||
|
||||
} // End Namespace
|
||||
|
||||
ShareObserver::ShareObserver(QSharedPointer<Database> db, QObject* parent)
|
||||
@ -193,18 +199,20 @@ void ShareObserver::reinitialize()
|
||||
QList<Update> updated;
|
||||
const QList<Group*> groups = m_db->rootGroup()->groupsRecursive(true);
|
||||
for (Group* group : groups) {
|
||||
Update couple{group, m_groupToReference.value(group), KeeShare::referenceOf(group)};
|
||||
const Update couple{group, m_groupToReference.value(group), KeeShare::referenceOf(group)};
|
||||
if (couple.oldReference == couple.newReference) {
|
||||
continue;
|
||||
}
|
||||
|
||||
m_groupToReference.remove(couple.group);
|
||||
m_referenceToGroup.remove(couple.oldReference);
|
||||
m_shareToGroup.remove(couple.oldReference.path);
|
||||
const auto oldResolvedPath = resolvePath(couple.oldReference.path, m_db);
|
||||
m_shareToGroup.remove(oldResolvedPath);
|
||||
if (couple.newReference.isValid()) {
|
||||
m_groupToReference[couple.group] = couple.newReference;
|
||||
m_referenceToGroup[couple.newReference] = couple.group;
|
||||
m_shareToGroup[couple.newReference.path] = couple.group;
|
||||
const auto newResolvedPath = resolvePath(couple.newReference.path, m_db);
|
||||
m_shareToGroup[newResolvedPath] = couple.group;
|
||||
}
|
||||
updated << couple;
|
||||
}
|
||||
@ -216,11 +224,13 @@ void ShareObserver::reinitialize()
|
||||
QMap<QString, QStringList> exported;
|
||||
for (const auto& update : asConst(updated)) {
|
||||
if (!update.oldReference.path.isEmpty()) {
|
||||
m_fileWatcher->removePath(update.oldReference.path);
|
||||
const auto oldResolvedPath = resolvePath(update.oldReference.path, m_db);
|
||||
m_fileWatcher->removePath(oldResolvedPath);
|
||||
}
|
||||
|
||||
if (!update.newReference.path.isEmpty() && update.newReference.type != KeeShareSettings::Inactive) {
|
||||
m_fileWatcher->addPath(update.newReference.path);
|
||||
const auto newResolvedPath = resolvePath(update.newReference.path, m_db);
|
||||
m_fileWatcher->addPath(newResolvedPath);
|
||||
}
|
||||
if (update.newReference.isExporting()) {
|
||||
exported[update.newReference.path] << update.group->name();
|
||||
@ -326,14 +336,16 @@ void ShareObserver::handleFileUpdated(const QString& path)
|
||||
notifyAbout(success, warning, error);
|
||||
}
|
||||
|
||||
ShareObserver::Result ShareObserver::importSingedContainerInto(const KeeShareSettings::Reference& reference,
|
||||
ShareObserver::Result ShareObserver::importSignedContainerInto(const QString& realPath,
|
||||
const KeeShareSettings::Reference& reference,
|
||||
Group* targetGroup)
|
||||
{
|
||||
#if !defined(WITH_XC_KEESHARE_SECURE)
|
||||
Q_UNUSED(targetGroup);
|
||||
Q_UNUSED(realPath);
|
||||
return {reference.path, Result::Warning, tr("Signed share container are not supported - import prevented")};
|
||||
#else
|
||||
QuaZip zip(reference.path);
|
||||
QuaZip zip(realPath);
|
||||
if (!zip.open(QuaZip::mdUnzip)) {
|
||||
qCritical("Unable to open file %s.", qPrintable(reference.path));
|
||||
return {reference.path, Result::Error, tr("File is not readable")};
|
||||
@ -438,14 +450,16 @@ ShareObserver::Result ShareObserver::importSingedContainerInto(const KeeShareSet
|
||||
#endif
|
||||
}
|
||||
|
||||
ShareObserver::Result ShareObserver::importUnsignedContainerInto(const KeeShareSettings::Reference& reference,
|
||||
ShareObserver::Result ShareObserver::importUnsignedContainerInto(const QString& realPath,
|
||||
const KeeShareSettings::Reference& reference,
|
||||
Group* targetGroup)
|
||||
{
|
||||
#if !defined(WITH_XC_KEESHARE_INSECURE)
|
||||
Q_UNUSED(targetGroup);
|
||||
Q_UNUSED(realPath);
|
||||
return {reference.path, Result::Warning, tr("Unsigned share container are not supported - import prevented")};
|
||||
#else
|
||||
QFile file(reference.path);
|
||||
QFile file(realPath);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
qCritical("Unable to open file %s.", qPrintable(reference.path));
|
||||
return {reference.path, Result::Error, tr("File is not readable")};
|
||||
@ -524,20 +538,21 @@ ShareObserver::Result ShareObserver::importUnsignedContainerInto(const KeeShareS
|
||||
#endif
|
||||
}
|
||||
|
||||
ShareObserver::Result ShareObserver::importContainerInto(const KeeShareSettings::Reference& reference,
|
||||
ShareObserver::Result ShareObserver::importContainerInto(const QString& realPath,
|
||||
const KeeShareSettings::Reference& reference,
|
||||
Group* targetGroup)
|
||||
{
|
||||
const QFileInfo info(reference.path);
|
||||
const QFileInfo info(realPath);
|
||||
if (!info.exists()) {
|
||||
qCritical("File %s does not exist.", qPrintable(info.absoluteFilePath()));
|
||||
return {reference.path, Result::Warning, tr("File does not exist")};
|
||||
}
|
||||
|
||||
if (isOfExportType(info, KeeShare::signedContainerFileType())) {
|
||||
return importSingedContainerInto(reference, targetGroup);
|
||||
return importSignedContainerInto(realPath, reference, targetGroup);
|
||||
}
|
||||
if (isOfExportType(info, KeeShare::unsignedContainerFileType())) {
|
||||
return importUnsignedContainerInto(reference, targetGroup);
|
||||
return importUnsignedContainerInto(realPath, reference, targetGroup);
|
||||
}
|
||||
return {reference.path, Result::Error, tr("Unknown share container type")};
|
||||
}
|
||||
@ -547,7 +562,8 @@ ShareObserver::Result ShareObserver::importFromReferenceContainer(const QString&
|
||||
if (!KeeShare::active().in) {
|
||||
return {};
|
||||
}
|
||||
auto shareGroup = m_shareToGroup.value(path);
|
||||
const auto changePath = resolvePath(path, m_db);
|
||||
auto shareGroup = m_shareToGroup.value(changePath);
|
||||
if (!shareGroup) {
|
||||
qWarning("Source for %s does not exist", qPrintable(path));
|
||||
Q_ASSERT(shareGroup);
|
||||
@ -565,7 +581,8 @@ ShareObserver::Result ShareObserver::importFromReferenceContainer(const QString&
|
||||
|
||||
Q_ASSERT(shareGroup->database() == m_db);
|
||||
Q_ASSERT(shareGroup == m_db->rootGroup()->findGroupByUuid(shareGroup->uuid()));
|
||||
return importContainerInto(reference, shareGroup);
|
||||
const auto resolvedPath = resolvePath(reference.path, m_db);
|
||||
return importContainerInto(resolvedPath, reference, shareGroup);
|
||||
}
|
||||
|
||||
void ShareObserver::resolveReferenceAttributes(Entry* targetEntry, const Database* sourceDb)
|
||||
@ -603,14 +620,14 @@ Database* ShareObserver::exportIntoContainer(const KeeShareSettings::Reference&
|
||||
|
||||
// Copy the source root as the root of the export database, memory manage the old root node
|
||||
auto* targetRoot = sourceRoot->clone(Entry::CloneNoFlags, Group::CloneNoFlags);
|
||||
const bool updateTimeinfo = targetRoot->canUpdateTimeinfo();
|
||||
auto updateTimeinfo = targetRoot->canUpdateTimeinfo();
|
||||
targetRoot->setUpdateTimeinfo(false);
|
||||
KeeShare::setReferenceTo(targetRoot, KeeShareSettings::Reference());
|
||||
targetRoot->setUpdateTimeinfo(updateTimeinfo);
|
||||
const auto sourceEntries = sourceRoot->entriesRecursive(false);
|
||||
for (const Entry* sourceEntry : sourceEntries) {
|
||||
auto* targetEntry = sourceEntry->clone(Entry::CloneIncludeHistory);
|
||||
const bool updateTimeinfo = targetEntry->canUpdateTimeinfo();
|
||||
updateTimeinfo = targetEntry->canUpdateTimeinfo();
|
||||
targetEntry->setUpdateTimeinfo(false);
|
||||
targetEntry->setGroup(targetRoot);
|
||||
targetEntry->setUpdateTimeinfo(updateTimeinfo);
|
||||
@ -647,11 +664,13 @@ QSharedPointer<Database> ShareObserver::database()
|
||||
return m_db;
|
||||
}
|
||||
|
||||
ShareObserver::Result ShareObserver::exportIntoReferenceSignedContainer(const KeeShareSettings::Reference& reference,
|
||||
ShareObserver::Result ShareObserver::exportIntoReferenceSignedContainer(const QString& realPath,
|
||||
const KeeShareSettings::Reference& reference,
|
||||
Database* targetDb)
|
||||
{
|
||||
#if !defined(WITH_XC_KEESHARE_SECURE)
|
||||
Q_UNUSED(targetDb);
|
||||
Q_UNUSED(realPath);
|
||||
return {
|
||||
reference.path, Result::Warning, tr("Overwriting signed share container is not supported - export prevented")};
|
||||
#else
|
||||
@ -667,7 +686,7 @@ ShareObserver::Result ShareObserver::exportIntoReferenceSignedContainer(const Ke
|
||||
}
|
||||
}
|
||||
const auto own = KeeShare::own();
|
||||
QuaZip zip(reference.path);
|
||||
QuaZip zip(realPath);
|
||||
zip.setFileNameCodec("UTF-8");
|
||||
const bool zipOpened = zip.open(QuaZip::mdCreate);
|
||||
if (!zipOpened) {
|
||||
@ -723,16 +742,18 @@ ShareObserver::Result ShareObserver::exportIntoReferenceSignedContainer(const Ke
|
||||
#endif
|
||||
}
|
||||
|
||||
ShareObserver::Result ShareObserver::exportIntoReferenceUnsignedContainer(const KeeShareSettings::Reference& reference,
|
||||
ShareObserver::Result ShareObserver::exportIntoReferenceUnsignedContainer(const QString& realPath,
|
||||
const KeeShareSettings::Reference& reference,
|
||||
Database* targetDb)
|
||||
{
|
||||
#if !defined(WITH_XC_KEESHARE_INSECURE)
|
||||
Q_UNUSED(targetDb);
|
||||
Q_UNUSED(realPath);
|
||||
return {reference.path,
|
||||
Result::Warning,
|
||||
tr("Overwriting unsigned share container is not supported - export prevented")};
|
||||
#else
|
||||
QFile file(reference.path);
|
||||
QFile file(realPath);
|
||||
const bool fileOpened = file.open(QIODevice::WriteOnly);
|
||||
if (!fileOpened) {
|
||||
::qWarning("Opening export file failed");
|
||||
@ -771,12 +792,12 @@ QList<ShareObserver::Result> ShareObserver::exportIntoReferenceContainers()
|
||||
for (auto it = references.cbegin(); it != references.cend(); ++it) {
|
||||
if (it.value().count() != 1) {
|
||||
const auto path = it.value().first().config.path;
|
||||
QStringList groups;
|
||||
QStringList groupnames;
|
||||
for (const auto& reference : it.value()) {
|
||||
groups << reference.group->name();
|
||||
groupnames << reference.group->name();
|
||||
}
|
||||
results << Result{
|
||||
path, Result::Error, tr("Conflicting export target path %1 in %2").arg(path, groups.join(", "))};
|
||||
path, Result::Error, tr("Conflicting export target path %1 in %2").arg(path, groupnames.join(", "))};
|
||||
}
|
||||
}
|
||||
if (!results.isEmpty()) {
|
||||
@ -786,16 +807,17 @@ QList<ShareObserver::Result> ShareObserver::exportIntoReferenceContainers()
|
||||
|
||||
for (auto it = references.cbegin(); it != references.cend(); ++it) {
|
||||
const auto& reference = it.value().first();
|
||||
m_fileWatcher->ignoreFileChanges(reference.config.path);
|
||||
const QString resolvedPath = resolvePath(reference.config.path, m_db);
|
||||
m_fileWatcher->ignoreFileChanges(resolvedPath);
|
||||
QScopedPointer<Database> targetDb(exportIntoContainer(reference.config, reference.group));
|
||||
QFileInfo info(reference.config.path);
|
||||
QFileInfo info(resolvedPath);
|
||||
if (isOfExportType(info, KeeShare::signedContainerFileType())) {
|
||||
results << exportIntoReferenceSignedContainer(reference.config, targetDb.data());
|
||||
results << exportIntoReferenceSignedContainer(resolvedPath, reference.config, targetDb.data());
|
||||
m_fileWatcher->observeFileChanges(true);
|
||||
continue;
|
||||
}
|
||||
if (isOfExportType(info, KeeShare::unsignedContainerFileType())) {
|
||||
results << exportIntoReferenceUnsignedContainer(reference.config, targetDb.data());
|
||||
results << exportIntoReferenceUnsignedContainer(resolvedPath, reference.config, targetDb.data());
|
||||
m_fileWatcher->observeFileChanges(true);
|
||||
continue;
|
||||
}
|
||||
|
@ -79,12 +79,20 @@ private:
|
||||
static void resolveReferenceAttributes(Entry* targetEntry, const Database* sourceDb);
|
||||
|
||||
static Database* exportIntoContainer(const KeeShareSettings::Reference& reference, const Group* sourceRoot);
|
||||
static Result exportIntoReferenceUnsignedContainer(const KeeShareSettings::Reference& reference,
|
||||
static Result exportIntoReferenceUnsignedContainer(const QString& realPath,
|
||||
const KeeShareSettings::Reference& reference,
|
||||
Database* targetDb);
|
||||
static Result exportIntoReferenceSignedContainer(const KeeShareSettings::Reference& reference, Database* targetDb);
|
||||
static Result importSingedContainerInto(const KeeShareSettings::Reference& reference, Group* targetGroup);
|
||||
static Result importUnsignedContainerInto(const KeeShareSettings::Reference& reference, Group* targetGroup);
|
||||
static Result importContainerInto(const KeeShareSettings::Reference& reference, Group* targetGroup);
|
||||
static Result exportIntoReferenceSignedContainer(const QString& realPath,
|
||||
const KeeShareSettings::Reference& reference,
|
||||
Database* targetDb);
|
||||
static Result importSignedContainerInto(const QString& realPath,
|
||||
const KeeShareSettings::Reference& reference,
|
||||
Group* targetGroup);
|
||||
static Result importUnsignedContainerInto(const QString& realPath,
|
||||
const KeeShareSettings::Reference& reference,
|
||||
Group* targetGroup);
|
||||
static Result
|
||||
importContainerInto(const QString& realPath, const KeeShareSettings::Reference& reference, Group* targetGroup);
|
||||
static Result importDatabaseInto();
|
||||
|
||||
Result importFromReferenceContainer(const QString& path);
|
||||
|
Loading…
Reference in New Issue
Block a user