Skip to content

Commit

Permalink
Enforce ShareObserver to resolve relative paths
Browse files Browse the repository at this point in the history
ShareObserver now uses paths which are resolved relative to the referencing database.
  • Loading branch information
Christian Kieschnick authored and droidmonkey committed Jun 20, 2019
1 parent c5a93ca commit 37c53f3
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 33 deletions.
78 changes: 50 additions & 28 deletions src/keeshare/ShareObserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}
Expand All @@ -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();
Expand Down Expand Up @@ -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")};
Expand Down Expand Up @@ -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")};
Expand Down Expand Up @@ -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")};
}
Expand All @@ -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);
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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) {
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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()) {
Expand All @@ -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;
}
Expand Down
18 changes: 13 additions & 5 deletions src/keeshare/ShareObserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,20 @@ private slots:
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);
Expand Down

0 comments on commit 37c53f3

Please sign in to comment.