2018-01-21 23:26:05 +03:00
|
|
|
#include "propagatedownloadencrypted.h"
|
|
|
|
#include "clientsideencryptionjobs.h"
|
|
|
|
|
|
|
|
Q_LOGGING_CATEGORY(lcPropagateDownloadEncrypted, "nextcloud.sync.propagator.download.encrypted", QtInfoMsg)
|
|
|
|
|
|
|
|
|
|
|
|
namespace OCC {
|
|
|
|
|
2020-06-26 10:43:06 +03:00
|
|
|
PropagateDownloadEncrypted::PropagateDownloadEncrypted(OwncloudPropagator *propagator, const QString &localParentPath, SyncFileItemPtr item, QObject *parent)
|
2020-06-24 18:58:52 +03:00
|
|
|
: QObject(parent)
|
|
|
|
, _propagator(propagator)
|
2020-06-26 10:43:06 +03:00
|
|
|
, _localParentPath(localParentPath)
|
2020-06-24 18:58:52 +03:00
|
|
|
, _item(item)
|
|
|
|
, _info(_item->_file)
|
2018-01-21 23:26:05 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-01-22 16:08:32 +03:00
|
|
|
void PropagateDownloadEncrypted::start() {
|
|
|
|
checkFolderEncryptedStatus();
|
|
|
|
}
|
|
|
|
|
2018-01-21 23:26:05 +03:00
|
|
|
void PropagateDownloadEncrypted::checkFolderEncryptedStatus()
|
|
|
|
{
|
2020-06-29 19:16:59 +03:00
|
|
|
const auto rootPath = [=]() {
|
|
|
|
const auto result = _propagator->_remoteFolder;
|
|
|
|
if (result.startsWith('/')) {
|
|
|
|
return result.mid(1);
|
|
|
|
} else {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}();
|
2020-06-30 18:20:02 +03:00
|
|
|
const auto remoteFilename = _item->_encryptedFileName.isEmpty() ? _item->_file : _item->_encryptedFileName;
|
|
|
|
const auto remotePath = QString(rootPath + remoteFilename);
|
2020-06-29 19:16:59 +03:00
|
|
|
const auto remoteParentPath = remotePath.left(remotePath.lastIndexOf('/'));
|
|
|
|
|
|
|
|
auto getEncryptedStatus = new GetFolderEncryptStatusJob(_propagator->account(), remoteParentPath, this);
|
2018-01-21 23:26:05 +03:00
|
|
|
connect(getEncryptedStatus, &GetFolderEncryptStatusJob::encryptStatusFolderReceived,
|
|
|
|
this, &PropagateDownloadEncrypted::folderStatusReceived);
|
|
|
|
|
|
|
|
connect(getEncryptedStatus, &GetFolderEncryptStatusJob::encryptStatusError,
|
|
|
|
this, &PropagateDownloadEncrypted::folderStatusError);
|
|
|
|
|
|
|
|
getEncryptedStatus->start();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PropagateDownloadEncrypted::folderStatusError(int statusCode)
|
|
|
|
{
|
|
|
|
qCDebug(lcPropagateDownloadEncrypted) << "Failed to get encrypted status of folder" << statusCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PropagateDownloadEncrypted::folderStatusReceived(const QString &folder, bool isEncrypted)
|
|
|
|
{
|
|
|
|
qCDebug(lcPropagateDownloadEncrypted) << "Get Folder is Encrypted Received" << folder << isEncrypted;
|
|
|
|
if (!isEncrypted) {
|
|
|
|
emit folderStatusNotEncrypted();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Is encrypted Now we need the folder-id
|
|
|
|
auto job = new LsColJob(_propagator->account(), folder, this);
|
|
|
|
job->setProperties({"resourcetype", "http://owncloud.org/ns:fileid"});
|
|
|
|
connect(job, &LsColJob::directoryListingSubfolders,
|
|
|
|
this, &PropagateDownloadEncrypted::checkFolderId);
|
|
|
|
connect(job, &LsColJob::finishedWithError,
|
|
|
|
this, &PropagateDownloadEncrypted::folderIdError);
|
|
|
|
job->start();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PropagateDownloadEncrypted::folderIdError()
|
|
|
|
{
|
|
|
|
qCDebug(lcPropagateDownloadEncrypted) << "Failed to get encrypted metadata of folder";
|
|
|
|
}
|
|
|
|
|
|
|
|
void PropagateDownloadEncrypted::checkFolderId(const QStringList &list)
|
|
|
|
{
|
|
|
|
auto job = qobject_cast<LsColJob*>(sender());
|
|
|
|
const QString folderId = list.first();
|
|
|
|
qCDebug(lcPropagateDownloadEncrypted) << "Received id of folder" << folderId;
|
|
|
|
|
|
|
|
const ExtraFolderInfo &folderInfo = job->_folderInfos.value(folderId);
|
|
|
|
|
|
|
|
// Now that we have the folder-id we need it's JSON metadata
|
|
|
|
auto metadataJob = new GetMetadataApiJob(_propagator->account(), folderInfo.fileId);
|
|
|
|
connect(metadataJob, &GetMetadataApiJob::jsonReceived,
|
|
|
|
this, &PropagateDownloadEncrypted::checkFolderEncryptedMetadata);
|
|
|
|
|
|
|
|
metadataJob->start();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PropagateDownloadEncrypted::checkFolderEncryptedMetadata(const QJsonDocument &json)
|
|
|
|
{
|
2018-04-04 16:08:35 +03:00
|
|
|
qCDebug(lcPropagateDownloadEncrypted) << "Metadata Received reading" <<
|
|
|
|
csync_instruction_str(_item->_instruction) << _item->_file << _item->_encryptedFileName;
|
2018-01-21 23:26:05 +03:00
|
|
|
const QString filename = _info.fileName();
|
|
|
|
auto meta = new FolderMetadata(_propagator->account(), json.toJson(QJsonDocument::Compact));
|
|
|
|
const QVector<EncryptedFile> files = meta->files();
|
2018-03-29 00:12:48 +03:00
|
|
|
|
2018-04-04 16:08:35 +03:00
|
|
|
const QString encryptedFilename = _item->_instruction == CSYNC_INSTRUCTION_NEW ?
|
|
|
|
_item->_file.section(QLatin1Char('/'), -1) :
|
|
|
|
_item->_encryptedFileName.section(QLatin1Char('/'), -1);
|
2018-01-21 23:26:05 +03:00
|
|
|
for (const EncryptedFile &file : files) {
|
2018-04-04 01:56:05 +03:00
|
|
|
if (encryptedFilename == file.encryptedFilename) {
|
2018-01-21 23:26:05 +03:00
|
|
|
_encryptedInfo = file;
|
2020-06-30 18:20:02 +03:00
|
|
|
if (_item->_encryptedFileName.isEmpty()) {
|
|
|
|
_item->_encryptedFileName = _item->_file;
|
|
|
|
}
|
2020-06-29 19:20:23 +03:00
|
|
|
if (!_localParentPath.isEmpty()) {
|
|
|
|
_item->_file = _localParentPath + QLatin1Char('/') + _encryptedInfo.originalFilename;
|
|
|
|
} else {
|
|
|
|
_item->_file = _encryptedInfo.originalFilename;
|
|
|
|
}
|
2020-06-25 13:47:32 +03:00
|
|
|
|
2018-01-21 23:26:05 +03:00
|
|
|
qCDebug(lcPropagateDownloadEncrypted) << "Found matching encrypted metadata for file, starting download";
|
|
|
|
emit folderStatusEncrypted();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-29 00:12:48 +03:00
|
|
|
emit failed();
|
|
|
|
qCCritical(lcPropagateDownloadEncrypted) << "Failed to find encrypted metadata information of remote file" << filename;
|
2018-01-21 23:26:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Fix this. Exported in the wrong place.
|
|
|
|
QString createDownloadTmpFileName(const QString &previous);
|
|
|
|
|
|
|
|
bool PropagateDownloadEncrypted::decryptFile(QFile& tmpFile)
|
|
|
|
{
|
|
|
|
const QString tmpFileName = createDownloadTmpFileName(_item->_file + QLatin1String("_dec"));
|
|
|
|
qCDebug(lcPropagateDownloadEncrypted) << "Content Checksum Computed starting decryption" << tmpFileName;
|
|
|
|
|
|
|
|
tmpFile.close();
|
2018-03-26 23:18:07 +03:00
|
|
|
QFile _tmpOutput(_propagator->getFilePath(tmpFileName), this);
|
2018-07-02 13:45:44 +03:00
|
|
|
EncryptionHelper::fileDecryption(_encryptedInfo.encryptionKey,
|
|
|
|
_encryptedInfo.initializationVector,
|
|
|
|
&tmpFile,
|
|
|
|
&_tmpOutput);
|
2018-01-21 23:26:05 +03:00
|
|
|
|
2018-03-26 23:18:07 +03:00
|
|
|
qCDebug(lcPropagateDownloadEncrypted) << "Decryption finished" << tmpFile.fileName() << _tmpOutput.fileName();
|
2018-01-21 23:26:05 +03:00
|
|
|
|
|
|
|
tmpFile.close();
|
2018-03-26 23:18:07 +03:00
|
|
|
_tmpOutput.close();
|
2018-01-21 23:26:05 +03:00
|
|
|
|
|
|
|
// we decripted the temporary into another temporary, so good bye old one
|
|
|
|
if (!tmpFile.remove()) {
|
|
|
|
qCDebug(lcPropagateDownloadEncrypted) << "Failed to remove temporary file" << tmpFile.errorString();
|
|
|
|
_errorString = tmpFile.errorString();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Let's fool the rest of the logic into thinking this was the actual download
|
2018-03-26 23:18:07 +03:00
|
|
|
tmpFile.setFileName(_tmpOutput.fileName());
|
2018-01-21 23:26:05 +03:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString PropagateDownloadEncrypted::errorString() const
|
|
|
|
{
|
|
|
|
return _errorString;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|