Skip to content

Commit b6211ff

Browse files
authored
Merge pull request #7201 from nextcloud/backport/7193/stable-3.14
[stable-3.14] Bugfix/fix upload locked files
2 parents c5bf4a4 + 15c90c2 commit b6211ff

12 files changed

+43
-13
lines changed

src/common/syncjournaldb.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ Q_LOGGING_CATEGORY(lcDb, "nextcloud.sync.database", QtInfoMsg)
4949
#define GET_FILE_RECORD_QUERY \
5050
"SELECT path, inode, modtime, type, md5, fileid, remotePerm, filesize," \
5151
" ignoredChildrenRemote, contentchecksumtype.name || ':' || contentChecksum, e2eMangledName, isE2eEncrypted, " \
52-
" lock, lockOwnerDisplayName, lockOwnerId, lockType, lockOwnerEditor, lockTime, lockTimeout, isShared, lastShareStateFetchedTimestmap, sharedByMe" \
52+
" lock, lockOwnerDisplayName, lockOwnerId, lockType, lockOwnerEditor, lockTime, lockTimeout, lockToken, isShared, lastShareStateFetchedTimestmap, sharedByMe" \
5353
" FROM metadata" \
5454
" LEFT JOIN checksumtype as contentchecksumtype ON metadata.contentChecksumTypeId == contentchecksumtype.id"
5555

@@ -74,9 +74,10 @@ static void fillFileRecordFromGetQuery(SyncJournalFileRecord &rec, SqlQuery &que
7474
rec._lockstate._lockEditorApp = query.stringValue(16);
7575
rec._lockstate._lockTime = query.int64Value(17);
7676
rec._lockstate._lockTimeout = query.int64Value(18);
77-
rec._isShared = query.intValue(19) > 0;
78-
rec._lastShareStateFetchedTimestamp = query.int64Value(20);
79-
rec._sharedByMe = query.intValue(21) > 0;
77+
rec._lockstate._lockToken = query.stringValue(19);
78+
rec._isShared = query.intValue(20) > 0;
79+
rec._lastShareStateFetchedTimestamp = query.int64Value(21);
80+
rec._sharedByMe = query.intValue(22) > 0;
8081
}
8182

8283
static QByteArray defaultJournalMode(const QString &dbPath)
@@ -826,6 +827,7 @@ bool SyncJournalDb::updateMetadataTableStructure()
826827
addColumn(QStringLiteral("lockOwnerEditor"), QStringLiteral("TEXT"));
827828
addColumn(QStringLiteral("lockTime"), QStringLiteral("INTEGER"));
828829
addColumn(QStringLiteral("lockTimeout"), QStringLiteral("INTEGER"));
830+
addColumn(QStringLiteral("lockToken"), QStringLiteral("TEXT"));
829831

830832
SqlQuery query(_db);
831833
query.prepare("CREATE INDEX IF NOT EXISTS caseconflicts_basePath ON caseconflicts(basePath);");
@@ -987,8 +989,8 @@ Result<void, QString> SyncJournalDb::setFileRecord(const SyncJournalFileRecord &
987989
const auto query = _queryManager.get(PreparedSqlQueryManager::SetFileRecordQuery, QByteArrayLiteral("INSERT OR REPLACE INTO metadata "
988990
"(phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize, ignoredChildrenRemote, "
989991
"contentChecksum, contentChecksumTypeId, e2eMangledName, isE2eEncrypted, lock, lockType, lockOwnerDisplayName, lockOwnerId, "
990-
"lockOwnerEditor, lockTime, lockTimeout, isShared, lastShareStateFetchedTimestmap, sharedByMe) "
991-
"VALUES (?1 , ?2, ?3 , ?4 , ?5 , ?6 , ?7, ?8 , ?9 , ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20, ?21, ?22, ?23, ?24, ?25, ?26, ?27, ?28);"),
992+
"lockOwnerEditor, lockTime, lockTimeout, lockToken, isShared, lastShareStateFetchedTimestmap, sharedByMe) "
993+
"VALUES (?1 , ?2, ?3 , ?4 , ?5 , ?6 , ?7, ?8 , ?9 , ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20, ?21, ?22, ?23, ?24, ?25, ?26, ?27, ?28, ?29);"),
992994
_db);
993995
if (!query) {
994996
qCDebug(lcDb) << "database error:" << query->error();
@@ -1020,9 +1022,10 @@ Result<void, QString> SyncJournalDb::setFileRecord(const SyncJournalFileRecord &
10201022
query->bindValue(23, record._lockstate._lockEditorApp);
10211023
query->bindValue(24, record._lockstate._lockTime);
10221024
query->bindValue(25, record._lockstate._lockTimeout);
1023-
query->bindValue(26, record._isShared);
1024-
query->bindValue(27, record._lastShareStateFetchedTimestamp);
1025-
query->bindValue(28, record._sharedByMe);
1025+
query->bindValue(26, record._lockstate._lockToken);
1026+
query->bindValue(27, record._isShared);
1027+
query->bindValue(28, record._lastShareStateFetchedTimestamp);
1028+
query->bindValue(29, record._sharedByMe);
10261029

10271030
if (!query->exec()) {
10281031
qCDebug(lcDb) << "database error:" << query->error();
@@ -1616,7 +1619,7 @@ bool SyncJournalDb::updateLocalMetadata(const QString &filename,
16161619
const auto query = _queryManager.get(PreparedSqlQueryManager::SetFileRecordLocalMetadataQuery, QByteArrayLiteral("UPDATE metadata"
16171620
" SET inode=?2, modtime=?3, filesize=?4, lock=?5, lockType=?6,"
16181621
" lockOwnerDisplayName=?7, lockOwnerId=?8, lockOwnerEditor = ?9,"
1619-
" lockTime=?10, lockTimeout=?11"
1622+
" lockTime=?10, lockTimeout=?11, lockToken=?12"
16201623
" WHERE phash == ?1;"),
16211624
_db);
16221625
if (!query) {
@@ -1635,6 +1638,7 @@ bool SyncJournalDb::updateLocalMetadata(const QString &filename,
16351638
query->bindValue(9, lockInfo._lockEditorApp);
16361639
query->bindValue(10, lockInfo._lockTime);
16371640
query->bindValue(11, lockInfo._lockTimeout);
1641+
query->bindValue(12, lockInfo._lockToken);
16381642
if (!query->exec()) {
16391643
qCDebug(lcDb) << "database error:" << query->error();
16401644
return false;

src/common/syncjournalfilerecord.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ struct SyncJournalFileLockInfo {
3939
QString _lockEditorApp;
4040
qint64 _lockTime = 0;
4141
qint64 _lockTimeout = 0;
42+
QString _lockToken;
4243
};
4344

4445
/**

src/libsync/discovery.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,7 @@ void ProcessDirectoryJob::processFileAnalyzeRemoteInfo(const SyncFileItemPtr &it
712712
item->_lockEditorApp = serverEntry.lockEditorApp;
713713
item->_lockTime = serverEntry.lockTime;
714714
item->_lockTimeout = serverEntry.lockTimeout;
715+
item->_lockToken = serverEntry.lockToken;
715716

716717
qCDebug(lcDisco()) << "item lock for:" << item->_file
717718
<< item->_locked
@@ -720,7 +721,8 @@ void ProcessDirectoryJob::processFileAnalyzeRemoteInfo(const SyncFileItemPtr &it
720721
<< item->_lockOwnerType
721722
<< item->_lockEditorApp
722723
<< item->_lockTime
723-
<< item->_lockTimeout;
724+
<< item->_lockTimeout
725+
<< item->_lockToken;
724726

725727
// Check for missing server data
726728
{

src/libsync/discoveryphase.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,8 @@ void DiscoverySingleDirectoryJob::start()
415415
<< "http://nextcloud.org/ns:lock-owner-type"
416416
<< "http://nextcloud.org/ns:lock-owner-editor"
417417
<< "http://nextcloud.org/ns:lock-time"
418-
<< "http://nextcloud.org/ns:lock-timeout";
418+
<< "http://nextcloud.org/ns:lock-timeout"
419+
<< "http://nextcloud.org/ns:lock-token";
419420
}
420421
props << "http://nextcloud.org/ns:is-mount-root";
421422

@@ -547,7 +548,9 @@ static void propertyMapToRemoteInfo(const QMap<QString, QString> &map, RemotePer
547548
result.lockTimeout = 0;
548549
}
549550
}
550-
551+
if (property == "lock-token") {
552+
result.lockToken = value;
553+
}
551554
}
552555

553556
if (result.isDirectory && map.contains("size")) {

src/libsync/discoveryphase.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ struct RemoteInfo
8686
QString lockEditorApp;
8787
qint64 lockTime = 0;
8888
qint64 lockTimeout = 0;
89+
QString lockToken;
8990
};
9091

9192
struct LocalInfo

src/libsync/lockfilejobs.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ void LockFileJob::setFileRecordLocked(SyncJournalFileRecord &record) const
115115
record._lockstate._lockEditorApp = _editorName;
116116
record._lockstate._lockTime = _lockTime;
117117
record._lockstate._lockTimeout = _lockTimeout;
118+
record._lockstate._lockToken = _lockToken;
118119
if (!_etag.isEmpty()) {
119120
record._etag = _etag;
120121
}
@@ -129,6 +130,7 @@ void LockFileJob::resetState()
129130
_userId.clear();
130131
_lockTime = 0;
131132
_lockTimeout = 0;
133+
_lockToken.clear();
132134
}
133135

134136
SyncJournalFileRecord LockFileJob::handleReply()
@@ -241,6 +243,8 @@ void LockFileJob::decodeStartElement(const QString &name,
241243
_editorName = reader.readElementText();
242244
} else if (name == QStringLiteral("getetag")) {
243245
_etag = reader.readElementText().toUtf8();
246+
} else if (name == QStringLiteral("lock-token")) {
247+
_lockToken = reader.readElementText();
244248
}
245249
}
246250

src/libsync/lockfilejobs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class OWNCLOUDSYNC_EXPORT LockFileJob : public AbstractNetworkJob
5959
QByteArray _etag;
6060
qint64 _lockTime = 0;
6161
qint64 _lockTimeout = 0;
62+
QString _lockToken;
6263
QString _remoteSyncPathWithTrailingSlash;
6364
QString _localSyncPath;
6465
};

src/libsync/propagateuploadng.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,9 @@ void PropagateUploadFileNG::finishUpload()
328328

329329
const auto fileSize = _fileToUpload._size;
330330
headers[QByteArrayLiteral("OC-Total-Length")] = QByteArray::number(fileSize);
331+
if (_item->_locked == SyncFileItem::LockStatus::LockedItem) {
332+
headers[QByteArrayLiteral("If")] = (QLatin1String("<") + propagator()->account()->davUrl().toString() + _fileToUpload._file + "> (<opaquelocktoken:" + _item->_lockToken.toUtf8() + ">)").toUtf8();
333+
}
331334

332335
const auto job = new MoveJob(propagator()->account(), Utility::concatUrlPath(chunkUploadFolderUrl(), "/.file"), destination, headers, this);
333336
_jobs.append(job);

src/libsync/propagateuploadv1.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ void PropagateUploadFileV1::startNextChunk()
102102

103103
QString path = _fileToUpload._file;
104104

105+
if (_item->_locked == SyncFileItem::LockStatus::LockedItem) {
106+
headers[QByteArrayLiteral("If")] = (QLatin1String("<") + propagator()->account()->davUrl().toString() + _fileToUpload._file + "> (<opaquelocktoken:" + _item->_lockToken.toUtf8() + ">)").toUtf8();
107+
}
108+
105109
qint64 chunkStart = 0;
106110
qint64 currentChunkSize = fileSize;
107111
bool isFinalChunk = false;

src/libsync/syncengine.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ void OCC::SyncEngine::slotItemDiscovered(const OCC::SyncFileItemPtr &item)
440440
lockInfo._lockOwnerType = static_cast<qint64>(item->_lockOwnerType);
441441
lockInfo._lockOwnerDisplayName = item->_lockOwnerDisplayName;
442442
lockInfo._lockEditorApp = item->_lockOwnerDisplayName;
443+
lockInfo._lockToken = item->_lockToken;
443444

444445
if (!_journal->updateLocalMetadata(item->_file, item->_modtime, item->_size, item->_inode, lockInfo)) {
445446
qCWarning(lcEngine) << "Could not update local metadata for file" << item->_file;

0 commit comments

Comments
 (0)