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};
}
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;
}

View File

@ -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);