diff --git a/src/libsync/discoveryphase.cpp b/src/libsync/discoveryphase.cpp index f88b1a1db..6e95e0dbe 100644 --- a/src/libsync/discoveryphase.cpp +++ b/src/libsync/discoveryphase.cpp @@ -300,10 +300,8 @@ void DiscoverySingleDirectoryJob::abort() } } -static std::unique_ptr propertyMapToFileStat(const QMap &map) +static void propertyMapToFileStat(const QMap &map, csync_file_stat_t *file_stat) { - std::unique_ptr file_stat(new csync_file_stat_t); - for (auto it = map.constBegin(); it != map.constEnd(); ++it) { QString property = it.key(); QString value = it.value(); @@ -316,10 +314,13 @@ static std::unique_ptr propertyMapToFileStat(const QMapmodtime = oc_httpdate_parse(value.toUtf8()); } else if (property == "getcontentlength") { + // See #4573, sometimes negative size values are returned bool ok = false; qlonglong ll = value.toLongLong(&ok); if (ok && ll >= 0) { file_stat->size = ll; + } else { + file_stat->size = 0; } } else if (property == "getetag") { file_stat->etag = Utility::normalizeEtag(value.toUtf8()); @@ -346,7 +347,6 @@ static std::unique_ptr propertyMapToFileStat(const QMap &map) @@ -374,12 +374,26 @@ void DiscoverySingleDirectoryJob::directoryListingIteratedSlot(QString file, con file = file.remove(0, 1); } - - std::unique_ptr file_stat(propertyMapToFileStat(map)); + std::unique_ptr file_stat(new csync_file_stat_t); file_stat->path = file.toUtf8(); - if (file_stat->etag.isEmpty()) { - qCCritical(lcDiscovery) << "etag of" << file_stat->path << "is" << file_stat->etag << "This must not happen."; + file_stat->size = -1; + file_stat->modtime = -1; + propertyMapToFileStat(map, file_stat.get()); + if (file_stat->type == ItemTypeDirectory) + file_stat->size = 0; + if (file_stat->type == ItemTypeSkip + || file_stat->size == -1 + || file_stat->modtime == -1 + || file_stat->remotePerm.isNull() + || file_stat->etag.isEmpty() + || file_stat->file_id.isEmpty()) { + _error = tr("The server file discovery reply is missing data."); + qCWarning(lcDiscovery) + << "Missing properties:" << file << file_stat->type << file_stat->size + << file_stat->modtime << file_stat->remotePerm.toString() + << file_stat->etag << file_stat->file_id; } + if (_isExternalStorage && file_stat->remotePerm.hasPermission(RemotePermissions::IsMounted)) { /* All the entries in a external storage have 'M' in their permission. However, for all purposes in the desktop client, we only need to know about the mount points. @@ -414,6 +428,10 @@ void DiscoverySingleDirectoryJob::lsJobFinishedWithoutErrorSlot() emit finishedWithError(ERRNO_WRONG_CONTENT, QLatin1String("Server error: PROPFIND reply is not XML formatted!")); deleteLater(); return; + } else if (!_error.isEmpty()) { + emit finishedWithError(ERRNO_ERROR_STRING, _error); + deleteLater(); + return; } emit etag(_firstEtag); emit etagConcatenation(_etagConcatenation); diff --git a/src/libsync/discoveryphase.h b/src/libsync/discoveryphase.h index b5e743d33..238f1e822 100644 --- a/src/libsync/discoveryphase.h +++ b/src/libsync/discoveryphase.h @@ -91,6 +91,8 @@ private: bool _isRootPath; // If this directory is an external storage (The first item has 'M' in its permission) bool _isExternalStorage; + // If set, the discovery will finish with an error + QString _error; QPointer _lsColJob; public: