Enforce ShareObserver to resolve relative paths

ShareObserver now uses paths which are resolved relative to the referencing database.
This commit is contained in:
Christian Kieschnick 2019-04-18 11:58:01 +02:00 committed by Jonathan White
parent c5a93ca215
commit 37c53f326c
2 changed files with 63 additions and 33 deletions

View File

@ -151,6 +151,12 @@ namespace
return {UntrustedOnce, certificate}; return {UntrustedOnce, certificate};
} }
QString resolvePath(const QString& path, QSharedPointer<Database> database)
{
const QFileInfo info(database->filePath());
return info.absoluteDir().absoluteFilePath(path);
}
} // End Namespace } // End Namespace
ShareObserver::ShareObserver(QSharedPointer<Database> db, QObject* parent) ShareObserver::ShareObserver(QSharedPointer<Database> db, QObject* parent)
@ -193,18 +199,20 @@ void ShareObserver::reinitialize()
QList<Update> updated; QList<Update> updated;
const QList<Group*> groups = m_db->rootGroup()->groupsRecursive(true); const QList<Group*> groups = m_db->rootGroup()->groupsRecursive(true);
for (Group* group : groups) { 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) { if (couple.oldReference == couple.newReference) {
continue; continue;
} }
m_groupToReference.remove(couple.group); m_groupToReference.remove(couple.group);
m_referenceToGroup.remove(couple.oldReference); 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()) { if (couple.newReference.isValid()) {
m_groupToReference[couple.group] = couple.newReference; m_groupToReference[couple.group] = couple.newReference;
m_referenceToGroup[couple.newReference] = couple.group; 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; updated << couple;
} }
@ -216,11 +224,13 @@ void ShareObserver::reinitialize()
QMap<QString, QStringList> exported; QMap<QString, QStringList> exported;
for (const auto& update : asConst(updated)) { for (const auto& update : asConst(updated)) {
if (!update.oldReference.path.isEmpty()) { 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) { 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()) { if (update.newReference.isExporting()) {
exported[update.newReference.path] << update.group->name(); exported[update.newReference.path] << update.group->name();
@ -326,14 +336,16 @@ void ShareObserver::handleFileUpdated(const QString& path)
notifyAbout(success, warning, error); 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) Group* targetGroup)
{ {
#if !defined(WITH_XC_KEESHARE_SECURE) #if !defined(WITH_XC_KEESHARE_SECURE)
Q_UNUSED(targetGroup); Q_UNUSED(targetGroup);
Q_UNUSED(realPath);
return {reference.path, Result::Warning, tr("Signed share container are not supported - import prevented")}; return {reference.path, Result::Warning, tr("Signed share container are not supported - import prevented")};
#else #else
QuaZip zip(reference.path); QuaZip zip(realPath);
if (!zip.open(QuaZip::mdUnzip)) { if (!zip.open(QuaZip::mdUnzip)) {
qCritical("Unable to open file %s.", qPrintable(reference.path)); qCritical("Unable to open file %s.", qPrintable(reference.path));
return {reference.path, Result::Error, tr("File is not readable")}; return {reference.path, Result::Error, tr("File is not readable")};
@ -438,14 +450,16 @@ ShareObserver::Result ShareObserver::importSingedContainerInto(const KeeShareSet
#endif #endif
} }
ShareObserver::Result ShareObserver::importUnsignedContainerInto(const KeeShareSettings::Reference& reference, ShareObserver::Result ShareObserver::importUnsignedContainerInto(const QString& realPath,
const KeeShareSettings::Reference& reference,
Group* targetGroup) Group* targetGroup)
{ {
#if !defined(WITH_XC_KEESHARE_INSECURE) #if !defined(WITH_XC_KEESHARE_INSECURE)
Q_UNUSED(targetGroup); Q_UNUSED(targetGroup);
Q_UNUSED(realPath);
return {reference.path, Result::Warning, tr("Unsigned share container are not supported - import prevented")}; return {reference.path, Result::Warning, tr("Unsigned share container are not supported - import prevented")};
#else #else
QFile file(reference.path); QFile file(realPath);
if (!file.open(QIODevice::ReadOnly)) { if (!file.open(QIODevice::ReadOnly)) {
qCritical("Unable to open file %s.", qPrintable(reference.path)); qCritical("Unable to open file %s.", qPrintable(reference.path));
return {reference.path, Result::Error, tr("File is not readable")}; return {reference.path, Result::Error, tr("File is not readable")};
@ -524,20 +538,21 @@ ShareObserver::Result ShareObserver::importUnsignedContainerInto(const KeeShareS
#endif #endif
} }
ShareObserver::Result ShareObserver::importContainerInto(const KeeShareSettings::Reference& reference, ShareObserver::Result ShareObserver::importContainerInto(const QString& realPath,
const KeeShareSettings::Reference& reference,
Group* targetGroup) Group* targetGroup)
{ {
const QFileInfo info(reference.path); const QFileInfo info(realPath);
if (!info.exists()) { if (!info.exists()) {
qCritical("File %s does not exist.", qPrintable(info.absoluteFilePath())); qCritical("File %s does not exist.", qPrintable(info.absoluteFilePath()));
return {reference.path, Result::Warning, tr("File does not exist")}; return {reference.path, Result::Warning, tr("File does not exist")};
} }
if (isOfExportType(info, KeeShare::signedContainerFileType())) { if (isOfExportType(info, KeeShare::signedContainerFileType())) {
return importSingedContainerInto(reference, targetGroup); return importSignedContainerInto(realPath, reference, targetGroup);
} }
if (isOfExportType(info, KeeShare::unsignedContainerFileType())) { if (isOfExportType(info, KeeShare::unsignedContainerFileType())) {
return importUnsignedContainerInto(reference, targetGroup); return importUnsignedContainerInto(realPath, reference, targetGroup);
} }
return {reference.path, Result::Error, tr("Unknown share container type")}; return {reference.path, Result::Error, tr("Unknown share container type")};
} }
@ -547,7 +562,8 @@ ShareObserver::Result ShareObserver::importFromReferenceContainer(const QString&
if (!KeeShare::active().in) { if (!KeeShare::active().in) {
return {}; return {};
} }
auto shareGroup = m_shareToGroup.value(path); const auto changePath = resolvePath(path, m_db);
auto shareGroup = m_shareToGroup.value(changePath);
if (!shareGroup) { if (!shareGroup) {
qWarning("Source for %s does not exist", qPrintable(path)); qWarning("Source for %s does not exist", qPrintable(path));
Q_ASSERT(shareGroup); Q_ASSERT(shareGroup);
@ -565,7 +581,8 @@ ShareObserver::Result ShareObserver::importFromReferenceContainer(const QString&
Q_ASSERT(shareGroup->database() == m_db); Q_ASSERT(shareGroup->database() == m_db);
Q_ASSERT(shareGroup == m_db->rootGroup()->findGroupByUuid(shareGroup->uuid())); 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) 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 // 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); auto* targetRoot = sourceRoot->clone(Entry::CloneNoFlags, Group::CloneNoFlags);
const bool updateTimeinfo = targetRoot->canUpdateTimeinfo(); auto updateTimeinfo = targetRoot->canUpdateTimeinfo();
targetRoot->setUpdateTimeinfo(false); targetRoot->setUpdateTimeinfo(false);
KeeShare::setReferenceTo(targetRoot, KeeShareSettings::Reference()); KeeShare::setReferenceTo(targetRoot, KeeShareSettings::Reference());
targetRoot->setUpdateTimeinfo(updateTimeinfo); targetRoot->setUpdateTimeinfo(updateTimeinfo);
const auto sourceEntries = sourceRoot->entriesRecursive(false); const auto sourceEntries = sourceRoot->entriesRecursive(false);
for (const Entry* sourceEntry : sourceEntries) { for (const Entry* sourceEntry : sourceEntries) {
auto* targetEntry = sourceEntry->clone(Entry::CloneIncludeHistory); auto* targetEntry = sourceEntry->clone(Entry::CloneIncludeHistory);
const bool updateTimeinfo = targetEntry->canUpdateTimeinfo(); updateTimeinfo = targetEntry->canUpdateTimeinfo();
targetEntry->setUpdateTimeinfo(false); targetEntry->setUpdateTimeinfo(false);
targetEntry->setGroup(targetRoot); targetEntry->setGroup(targetRoot);
targetEntry->setUpdateTimeinfo(updateTimeinfo); targetEntry->setUpdateTimeinfo(updateTimeinfo);
@ -647,11 +664,13 @@ QSharedPointer<Database> ShareObserver::database()
return m_db; return m_db;
} }
ShareObserver::Result ShareObserver::exportIntoReferenceSignedContainer(const KeeShareSettings::Reference& reference, ShareObserver::Result ShareObserver::exportIntoReferenceSignedContainer(const QString& realPath,
const KeeShareSettings::Reference& reference,
Database* targetDb) Database* targetDb)
{ {
#if !defined(WITH_XC_KEESHARE_SECURE) #if !defined(WITH_XC_KEESHARE_SECURE)
Q_UNUSED(targetDb); Q_UNUSED(targetDb);
Q_UNUSED(realPath);
return { return {
reference.path, Result::Warning, tr("Overwriting signed share container is not supported - export prevented")}; reference.path, Result::Warning, tr("Overwriting signed share container is not supported - export prevented")};
#else #else
@ -667,7 +686,7 @@ ShareObserver::Result ShareObserver::exportIntoReferenceSignedContainer(const Ke
} }
} }
const auto own = KeeShare::own(); const auto own = KeeShare::own();
QuaZip zip(reference.path); QuaZip zip(realPath);
zip.setFileNameCodec("UTF-8"); zip.setFileNameCodec("UTF-8");
const bool zipOpened = zip.open(QuaZip::mdCreate); const bool zipOpened = zip.open(QuaZip::mdCreate);
if (!zipOpened) { if (!zipOpened) {
@ -723,16 +742,18 @@ ShareObserver::Result ShareObserver::exportIntoReferenceSignedContainer(const Ke
#endif #endif
} }
ShareObserver::Result ShareObserver::exportIntoReferenceUnsignedContainer(const KeeShareSettings::Reference& reference, ShareObserver::Result ShareObserver::exportIntoReferenceUnsignedContainer(const QString& realPath,
const KeeShareSettings::Reference& reference,
Database* targetDb) Database* targetDb)
{ {
#if !defined(WITH_XC_KEESHARE_INSECURE) #if !defined(WITH_XC_KEESHARE_INSECURE)
Q_UNUSED(targetDb); Q_UNUSED(targetDb);
Q_UNUSED(realPath);
return {reference.path, return {reference.path,
Result::Warning, Result::Warning,
tr("Overwriting unsigned share container is not supported - export prevented")}; tr("Overwriting unsigned share container is not supported - export prevented")};
#else #else
QFile file(reference.path); QFile file(realPath);
const bool fileOpened = file.open(QIODevice::WriteOnly); const bool fileOpened = file.open(QIODevice::WriteOnly);
if (!fileOpened) { if (!fileOpened) {
::qWarning("Opening export file failed"); ::qWarning("Opening export file failed");
@ -771,12 +792,12 @@ QList<ShareObserver::Result> ShareObserver::exportIntoReferenceContainers()
for (auto it = references.cbegin(); it != references.cend(); ++it) { for (auto it = references.cbegin(); it != references.cend(); ++it) {
if (it.value().count() != 1) { if (it.value().count() != 1) {
const auto path = it.value().first().config.path; const auto path = it.value().first().config.path;
QStringList groups; QStringList groupnames;
for (const auto& reference : it.value()) { for (const auto& reference : it.value()) {
groups << reference.group->name(); groupnames << reference.group->name();
} }
results << Result{ 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()) { if (!results.isEmpty()) {
@ -786,16 +807,17 @@ QList<ShareObserver::Result> ShareObserver::exportIntoReferenceContainers()
for (auto it = references.cbegin(); it != references.cend(); ++it) { for (auto it = references.cbegin(); it != references.cend(); ++it) {
const auto& reference = it.value().first(); 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)); QScopedPointer<Database> targetDb(exportIntoContainer(reference.config, reference.group));
QFileInfo info(reference.config.path); QFileInfo info(resolvedPath);
if (isOfExportType(info, KeeShare::signedContainerFileType())) { if (isOfExportType(info, KeeShare::signedContainerFileType())) {
results << exportIntoReferenceSignedContainer(reference.config, targetDb.data()); results << exportIntoReferenceSignedContainer(resolvedPath, reference.config, targetDb.data());
m_fileWatcher->observeFileChanges(true); m_fileWatcher->observeFileChanges(true);
continue; continue;
} }
if (isOfExportType(info, KeeShare::unsignedContainerFileType())) { if (isOfExportType(info, KeeShare::unsignedContainerFileType())) {
results << exportIntoReferenceUnsignedContainer(reference.config, targetDb.data()); results << exportIntoReferenceUnsignedContainer(resolvedPath, reference.config, targetDb.data());
m_fileWatcher->observeFileChanges(true); m_fileWatcher->observeFileChanges(true);
continue; continue;
} }

View File

@ -79,12 +79,20 @@ private:
static void resolveReferenceAttributes(Entry* targetEntry, const Database* sourceDb); static void resolveReferenceAttributes(Entry* targetEntry, const Database* sourceDb);
static Database* exportIntoContainer(const KeeShareSettings::Reference& reference, const Group* sourceRoot); 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); Database* targetDb);
static Result exportIntoReferenceSignedContainer(const KeeShareSettings::Reference& reference, Database* targetDb); static Result exportIntoReferenceSignedContainer(const QString& realPath,
static Result importSingedContainerInto(const KeeShareSettings::Reference& reference, Group* targetGroup); const KeeShareSettings::Reference& reference,
static Result importUnsignedContainerInto(const KeeShareSettings::Reference& reference, Group* targetGroup); Database* targetDb);
static Result importContainerInto(const KeeShareSettings::Reference& reference, Group* targetGroup); 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(); static Result importDatabaseInto();
Result importFromReferenceContainer(const QString& path); Result importFromReferenceContainer(const QString& path);