diff options
Diffstat (limited to 'src/libsync')
-rw-r--r-- | src/libsync/account.h | 2 | ||||
-rw-r--r-- | src/libsync/configfile.cpp | 13 | ||||
-rw-r--r-- | src/libsync/configfile.h | 3 | ||||
-rw-r--r-- | src/libsync/logger.cpp | 104 | ||||
-rw-r--r-- | src/libsync/logger.h | 21 | ||||
-rw-r--r-- | src/libsync/networkjobs.cpp | 2 | ||||
-rw-r--r-- | src/libsync/owncloudpropagator.cpp | 8 | ||||
-rw-r--r-- | src/libsync/owncloudpropagator.h | 2 | ||||
-rw-r--r-- | src/libsync/owncloudtheme.cpp | 66 | ||||
-rw-r--r-- | src/libsync/owncloudtheme.h | 12 | ||||
-rw-r--r-- | src/libsync/propagateupload.cpp | 10 | ||||
-rw-r--r-- | src/libsync/propagateupload.h | 2 | ||||
-rw-r--r-- | src/libsync/propagateuploadng.cpp | 19 | ||||
-rw-r--r-- | src/libsync/propagateuploadv1.cpp | 19 | ||||
-rw-r--r-- | src/libsync/syncengine.cpp | 6 | ||||
-rw-r--r-- | src/libsync/syncengine.h | 4 | ||||
-rw-r--r-- | src/libsync/syncfileitem.h | 5 | ||||
-rw-r--r-- | src/libsync/theme.cpp | 47 | ||||
-rw-r--r-- | src/libsync/theme.h | 15 |
19 files changed, 209 insertions, 151 deletions
diff --git a/src/libsync/account.h b/src/libsync/account.h index 025dca907..a7879f4d0 100644 --- a/src/libsync/account.h +++ b/src/libsync/account.h @@ -218,7 +218,7 @@ public: /** Detects a specific bug in older server versions */ bool rootEtagChangesNotOnlySubFolderEtags(); - /** True when the server supports HTTP2 */ + /** True when the server connection is using HTTP2 */ bool isHttp2Supported() { return _http2Supported; } void setHttp2Supported(bool value) { _http2Supported = value; } diff --git a/src/libsync/configfile.cpp b/src/libsync/configfile.cpp index 82c2bc5f3..d0dadbf0f 100644 --- a/src/libsync/configfile.cpp +++ b/src/libsync/configfile.cpp @@ -64,6 +64,7 @@ static const char chunkSizeC[] = "chunkSize"; static const char minChunkSizeC[] = "minChunkSize"; static const char maxChunkSizeC[] = "maxChunkSize"; static const char targetChunkUploadDurationC[] = "targetChunkUploadDuration"; +static const char automaticLogDirC[] = "logToTemporaryLogDir"; static const char showExperimentalOptionsC[] = "showExperimentalOptions"; static const char proxyHostC[] = "Proxy/host"; @@ -737,6 +738,18 @@ void ConfigFile::setCrashReporter(bool enabled) settings.setValue(QLatin1String(crashReporterC), enabled); } +bool ConfigFile::automaticLogDir() const +{ + QSettings settings(configFile(), QSettings::IniFormat); + return settings.value(QLatin1String(automaticLogDirC), false).toBool(); +} + +void ConfigFile::setAutomaticLogDir(bool enabled) +{ + QSettings settings(configFile(), QSettings::IniFormat); + settings.setValue(QLatin1String(automaticLogDirC), enabled); +} + bool ConfigFile::showExperimentalOptions() const { QSettings settings(configFile(), QSettings::IniFormat); diff --git a/src/libsync/configfile.h b/src/libsync/configfile.h index 8877bb6dc..99aa6d5f1 100644 --- a/src/libsync/configfile.h +++ b/src/libsync/configfile.h @@ -89,6 +89,9 @@ public: bool crashReporter() const; void setCrashReporter(bool enabled); + bool automaticLogDir() const; + void setAutomaticLogDir(bool enabled); + // Whether experimental UI options should be shown bool showExperimentalOptions() const; diff --git a/src/libsync/logger.cpp b/src/libsync/logger.cpp index cfba000ed..7033bd851 100644 --- a/src/libsync/logger.cpp +++ b/src/libsync/logger.cpp @@ -14,11 +14,15 @@ #include "logger.h" +#include "config.h" + #include <QDir> #include <QStringList> #include <QThread> #include <qmetaobject.h> +#include <zlib.h> + namespace OCC { static void mirallLogCatcher(QtMsgType type, const QMessageLogContext &ctx, const QString &message) @@ -95,10 +99,15 @@ void Logger::log(Log log) */ bool Logger::isNoop() const { - QMutexLocker lock(const_cast<QMutex *>(&_mutex)); + QMutexLocker lock(&_mutex); return !_logstream && !_logWindowActivated; } +bool Logger::isLoggingToFile() const +{ + QMutexLocker lock(&_mutex); + return _logstream; +} void Logger::doLog(const QString &msg) { @@ -181,34 +190,99 @@ void Logger::setLogDebug(bool debug) _logDebug = debug; } +QString Logger::temporaryFolderLogDirPath() const +{ + QString dirName = APPLICATION_SHORTNAME + QString("-logdir"); + return QDir::temp().filePath(dirName); +} + +void Logger::setupTemporaryFolderLogDir() +{ + auto dir = temporaryFolderLogDirPath(); + if (!QDir().mkpath(dir)) + return; + setLogDebug(true); + setLogExpire(4 /*hours*/); + setLogDir(dir); + _temporaryFolderLogDir = true; +} + +void Logger::disableTemporaryFolderLogDir() +{ + if (!_temporaryFolderLogDir) + return; + + enterNextLogFile(); + setLogDir(QString()); + setLogDebug(false); + setLogFile(QString()); + _temporaryFolderLogDir = false; +} + +static bool compressLog(const QString &originalName, const QString &targetName) +{ + QFile original(originalName); + if (!original.open(QIODevice::ReadOnly)) + return false; + auto compressed = gzopen(targetName.toUtf8(), "wb"); + if (!compressed) { + return false; + } + + while (!original.atEnd()) { + auto data = original.read(1024 * 1024); + auto written = gzwrite(compressed, data.data(), data.size()); + if (written != data.size()) { + gzclose(compressed); + return false; + } + } + gzclose(compressed); + return true; +} + void Logger::enterNextLogFile() { if (!_logDirectory.isEmpty()) { + QDir dir(_logDirectory); if (!dir.exists()) { dir.mkpath("."); } - // Find out what is the file with the highest number if any - QStringList files = dir.entryList(QStringList("owncloud.log.*"), + // Tentative new log name, will be adjusted if one like this already exists + QDateTime now = QDateTime::currentDateTime(); + QString newLogName = now.toString("yyyyMMdd_HHmm") + "_owncloud.log"; + + // Expire old log files and deal with conflicts + QStringList files = dir.entryList(QStringList("*owncloud.log.*"), QDir::Files); - QRegExp rx("owncloud.log.(\\d+)"); - uint maxNumber = 0; - QDateTime now = QDateTime::currentDateTimeUtc(); + QRegExp rx(R"(.*owncloud\.log\.(\d+).*)"); + int maxNumber = -1; foreach (const QString &s, files) { - if (rx.exactMatch(s)) { - maxNumber = qMax(maxNumber, rx.cap(1).toUInt()); - if (_logExpire > 0) { - QFileInfo fileInfo = dir.absoluteFilePath(s); - if (fileInfo.lastModified().addSecs(60 * 60 * _logExpire) < now) { - dir.remove(s); - } + if (_logExpire > 0) { + QFileInfo fileInfo(dir.absoluteFilePath(s)); + if (fileInfo.lastModified().addSecs(60 * 60 * _logExpire) < now) { + dir.remove(s); } } + if (s.startsWith(newLogName) && rx.exactMatch(s)) { + maxNumber = qMax(maxNumber, rx.cap(1).toInt()); + } } + newLogName.append("." + QString::number(maxNumber + 1)); - QString filename = _logDirectory + "/owncloud.log." + QString::number(maxNumber + 1); - setLogFile(filename); + auto previousLog = _logFile.fileName(); + setLogFile(dir.filePath(newLogName)); + + if (!previousLog.isEmpty()) { + QString compressedName = previousLog + ".gz"; + if (compressLog(previousLog, compressedName)) { + QFile::remove(previousLog); + } else { + QFile::remove(compressedName); + } + } } } diff --git a/src/libsync/logger.h b/src/libsync/logger.h index 9d6ef6b26..7ae278e49 100644 --- a/src/libsync/logger.h +++ b/src/libsync/logger.h @@ -43,6 +43,8 @@ class OWNCLOUDSYNC_EXPORT Logger : public QObject Q_OBJECT public: bool isNoop() const; + bool isLoggingToFile() const; + void log(Log log); void doLog(const QString &log); @@ -65,6 +67,22 @@ public: bool logDebug() const { return _logDebug; } void setLogDebug(bool debug); + /** Returns where the automatic logdir would be */ + QString temporaryFolderLogDirPath() const; + + /** Sets up default dir log setup. + * + * logdir: a temporary folder + * logexpire: 4 hours + * logdebug: true + * + * Used in conjunction with ConfigFile::automaticLogDir + */ + void setupTemporaryFolderLogDir(); + + /** For switching off via logwindow */ + void disableTemporaryFolderLogDir(); + signals: void logWindowLog(const QString &); @@ -86,8 +104,9 @@ private: int _logExpire; bool _logDebug; QScopedPointer<QTextStream> _logstream; - QMutex _mutex; + mutable QMutex _mutex; QString _logDirectory; + bool _temporaryFolderLogDir = false; }; } // namespace OCC diff --git a/src/libsync/networkjobs.cpp b/src/libsync/networkjobs.cpp index a3881cd48..44fdc4553 100644 --- a/src/libsync/networkjobs.cpp +++ b/src/libsync/networkjobs.cpp @@ -879,6 +879,8 @@ void DetermineAuthTypeJob::start() get->setFollowRedirects(false); } #else + Q_UNUSED(this) + Q_UNUSED(get) Q_UNUSED(target) #endif }); diff --git a/src/libsync/owncloudpropagator.cpp b/src/libsync/owncloudpropagator.cpp index dafaec99c..3cd8ab0be 100644 --- a/src/libsync/owncloudpropagator.cpp +++ b/src/libsync/owncloudpropagator.cpp @@ -517,8 +517,7 @@ bool OwncloudPropagator::localFileNameClash(const QString &relFile) re = false; qCWarning(lcPropagator) << "No valid fileinfo"; } else { - // Need to normalize to composited form because of - // https://bugreports.qt-project.org/browse/QTBUG-39622 + // Need to normalize to composited form because of QTBUG-39622/QTBUG-55896 const QString cName = fileInfo.canonicalFilePath().normalized(QString::NormalizationForm_C); bool equal = (file == cName); re = (!equal && !cName.endsWith(relFile, Qt::CaseSensitive)); @@ -840,10 +839,13 @@ void PropagatorCompositeJob::slotSubJobFinished(SyncFileItem::Status status) ASSERT(i >= 0); _runningJobs.remove(i); + // Any sub job error will cause the whole composite to fail. This is important + // for knowing whether to update the etag in PropagateDirectory, for example. if (status == SyncFileItem::FatalError || status == SyncFileItem::NormalError || status == SyncFileItem::SoftError - || status == SyncFileItem::DetailError) { + || status == SyncFileItem::DetailError + || status == SyncFileItem::BlacklistedError) { _hasError = status; } diff --git a/src/libsync/owncloudpropagator.h b/src/libsync/owncloudpropagator.h index c272a06d2..b4bc470d2 100644 --- a/src/libsync/owncloudpropagator.h +++ b/src/libsync/owncloudpropagator.h @@ -156,7 +156,7 @@ class PropagateItemJob : public PropagatorJob { Q_OBJECT protected: - void done(SyncFileItem::Status status, const QString &errorString = QString()); + virtual void done(SyncFileItem::Status status, const QString &errorString = QString()); /* * set a custom restore job message that is used if the restore job succeeded. diff --git a/src/libsync/owncloudtheme.cpp b/src/libsync/owncloudtheme.cpp index 873257c19..1e142b962 100644 --- a/src/libsync/owncloudtheme.cpp +++ b/src/libsync/owncloudtheme.cpp @@ -19,8 +19,6 @@ #ifndef TOKEN_AUTH_ONLY #include <QPixmap> #include <QIcon> -#include <QStyle> -#include <QApplication> #endif #include <QCoreApplication> @@ -35,63 +33,13 @@ ownCloudTheme::ownCloudTheme() { } -QString ownCloudTheme::configFileName() const -{ - return QLatin1String("owncloud.cfg"); -} - -QString ownCloudTheme::about() const -{ - QString devString; - devString = tr("<p>Version %2. For more information visit <a href=\"%3\">https://%4</a></p>" - "<p>For known issues and help, please visit: <a href=\"https://central.owncloud.org/c/desktop-client\">https://central.owncloud.org</a></p>" - "<p><small>By Klaas Freitag, Daniel Molkentin, Olivier Goffart, Markus Götz, " - " Jan-Christoph Borchardt, and others.</small></p>" - "<p>Copyright ownCloud GmbH</p>" - "<p>Licensed under the GNU General Public License (GPL) Version 2.0<br/>" - "ownCloud and the ownCloud Logo are registered trademarks of ownCloud GmbH " - "in the United States, other countries, or both.</p>") - .arg(Utility::escape(MIRALL_VERSION_STRING), - Utility::escape("https://" MIRALL_STRINGIFY(APPLICATION_DOMAIN)), - Utility::escape(MIRALL_STRINGIFY(APPLICATION_DOMAIN))); - - devString += gitSHA1(); - return devString; -} - #ifndef TOKEN_AUTH_ONLY -QIcon ownCloudTheme::trayFolderIcon(const QString &) const -{ - QPixmap fallback = qApp->style()->standardPixmap(QStyle::SP_FileDialogNewFolder); - return QIcon::fromTheme("folder", fallback); -} - -QIcon ownCloudTheme::applicationIcon() const -{ - return themeIcon(QLatin1String("owncloud-icon")); -} - - -QVariant ownCloudTheme::customMedia(Theme::CustomMediaType type) +QVariant ownCloudTheme::customMedia(CustomMediaType) { - if (type == Theme::oCSetupTop) { - // return QCoreApplication::translate("ownCloudTheme", - // "If you don't have an ownCloud server yet, " - // "see <a href=\"https://owncloud.com\">owncloud.com</a> for more info.", - // "Top text in setup wizard. Keep short!"); - return QVariant(); - } else { - return QVariant(); - } + return QVariant(); } - #endif -QString ownCloudTheme::helpUrl() const -{ - return QString::fromLatin1("https://doc.owncloud.org/desktop/%1.%2/").arg(MIRALL_VERSION_MAJOR).arg(MIRALL_VERSION_MINOR); -} - #ifndef TOKEN_AUTH_ONLY QColor ownCloudTheme::wizardHeaderBackgroundColor() const { @@ -109,14 +57,4 @@ QPixmap ownCloudTheme::wizardHeaderLogo() const } #endif - -QString ownCloudTheme::appName() const -{ - return QLatin1String("ownCloud"); -} - -QString ownCloudTheme::appNameGUI() const -{ - return QLatin1String("ownCloud"); -} } diff --git a/src/libsync/owncloudtheme.h b/src/libsync/owncloudtheme.h index 327c96e5f..99143fe93 100644 --- a/src/libsync/owncloudtheme.h +++ b/src/libsync/owncloudtheme.h @@ -28,18 +28,6 @@ class ownCloudTheme : public Theme Q_OBJECT public: ownCloudTheme(); - - QString configFileName() const Q_DECL_OVERRIDE; - QString about() const Q_DECL_OVERRIDE; - -#ifndef TOKEN_AUTH_ONLY - QIcon trayFolderIcon(const QString &) const Q_DECL_OVERRIDE; - QIcon applicationIcon() const Q_DECL_OVERRIDE; -#endif - QString appName() const Q_DECL_OVERRIDE; - QString appNameGUI() const Q_DECL_OVERRIDE; - - QString helpUrl() const Q_DECL_OVERRIDE; #ifndef TOKEN_AUTH_ONLY QVariant customMedia(CustomMediaType type) Q_DECL_OVERRIDE; diff --git a/src/libsync/propagateupload.cpp b/src/libsync/propagateupload.cpp index 4579139ce..155eed8cc 100644 --- a/src/libsync/propagateupload.cpp +++ b/src/libsync/propagateupload.cpp @@ -471,7 +471,6 @@ void PropagateUploadFileCommon::slotPollFinished() propagator()->_activeJobList.removeOne(this); if (job->_item->_status != SyncFileItem::Success) { - _finished = true; done(job->_item->_status, job->_item->_errorString); return; } @@ -479,6 +478,12 @@ void PropagateUploadFileCommon::slotPollFinished() finalize(); } +void PropagateUploadFileCommon::done(SyncFileItem::Status status, const QString &errorString) +{ + _finished = true; + PropagateItemJob::done(status, errorString); +} + void PropagateUploadFileCommon::checkResettingErrors() { if (_item->_httpErrorCode == 412 @@ -561,7 +566,6 @@ void PropagateUploadFileCommon::abort(PropagatorJob::AbortType abortType) // This function is used whenever there is an error occuring and jobs might be in progress void PropagateUploadFileCommon::abortWithError(SyncFileItem::Status status, const QString &error) { - _finished = true; abort(AbortType::Synchronous); done(status, error); } @@ -610,8 +614,6 @@ QMap<QByteArray, QByteArray> PropagateUploadFileCommon::headers() void PropagateUploadFileCommon::finalize() { - _finished = true; - // Update the quota, if known auto quotaIt = propagator()->_folderQuota.find(QFileInfo(_item->_file).path()); if (quotaIt != propagator()->_folderQuota.end()) diff --git a/src/libsync/propagateupload.h b/src/libsync/propagateupload.h index fbbbc14f1..c7e8b4854 100644 --- a/src/libsync/propagateupload.h +++ b/src/libsync/propagateupload.h @@ -257,6 +257,8 @@ private slots: void slotPollFinished(); protected: + void done(SyncFileItem::Status status, const QString &errorString = QString()) override; + /** * Prepares the abort e.g. connects proper signals and slots * to the subjobs to abort asynchronously diff --git a/src/libsync/propagateuploadng.cpp b/src/libsync/propagateuploadng.cpp index a679887a5..13dfe513b 100644 --- a/src/libsync/propagateuploadng.cpp +++ b/src/libsync/propagateuploadng.cpp @@ -83,7 +83,7 @@ void PropagateUploadFileNG::doStartUpload() propagator()->_activeJobList.append(this); const SyncJournalDb::UploadInfo progressInfo = propagator()->_journal->getUploadInfo(_item->_file); - if (progressInfo._valid && progressInfo._modtime == _item->_modtime) { + if (progressInfo._valid && progressInfo.isChunked() && progressInfo._modtime == _item->_modtime) { _transferId = progressInfo._transferid; auto url = chunkUrl(); auto job = new LsColJob(propagator()->account(), url, this); @@ -98,7 +98,7 @@ void PropagateUploadFileNG::doStartUpload() this, &PropagateUploadFileNG::slotPropfindIterate); job->start(); return; - } else if (progressInfo._valid) { + } else if (progressInfo._valid && progressInfo.isChunked()) { // The upload info is stale. remove the stale chunks on the server _transferId = progressInfo._transferid; // Fire and forget. Any error will be ignored. @@ -143,6 +143,12 @@ void PropagateUploadFileNG::slotPropfindFinished() qCCritical(lcPropagateUpload) << "Inconsistency while resuming " << _item->_file << ": the size on the server (" << _sent << ") is bigger than the size of the file (" << _item->_size << ")"; + + // Wipe the old chunking data. + // Fire and forget. Any error will be ignored. + (new DeleteJob(propagator()->account(), chunkUrl(), this))->start(); + + propagator()->_activeJobList.append(this); startNewUpload(); return; } @@ -274,6 +280,7 @@ void PropagateUploadFileNG::startNextChunk() if (_currentChunkSize == 0) { Q_ASSERT(_jobs.isEmpty()); // There should be no running job anymore _finished = true; + // Finish with a MOVE QString destination = QDir::cleanPath(propagator()->account()->url().path() + QLatin1Char('/') + propagator()->account()->davPath() + propagator()->_remoteFolder + _item->_file); @@ -389,12 +396,12 @@ void PropagateUploadFileNG::slotPutFinished() << propagator()->_chunkSize << "bytes"; } - bool finished = _sent == _item->_size; + _finished = _sent == _item->_size; // Check if the file still exists const QString fullFilePath(propagator()->getFilePath(_item->_file)); if (!FileSystem::fileExists(fullFilePath)) { - if (!finished) { + if (!_finished) { abortWithError(SyncFileItem::SoftError, tr("The local file was removed during sync.")); return; } else { @@ -405,13 +412,13 @@ void PropagateUploadFileNG::slotPutFinished() // Check whether the file changed since discovery. if (!FileSystem::verifyFileUnchanged(fullFilePath, _item->_size, _item->_modtime)) { propagator()->_anotherSyncNeeded = true; - if (!finished) { + if (!_finished) { abortWithError(SyncFileItem::SoftError, tr("Local file changed during sync.")); return; } } - if (!finished) { + if (!_finished) { // Deletes an existing blacklist entry on successful chunk upload if (_item->_hasBlacklistEntry) { propagator()->_journal->wipeErrorBlacklistEntry(_item->_file); diff --git a/src/libsync/propagateuploadv1.cpp b/src/libsync/propagateuploadv1.cpp index 062b17634..8bd9489f5 100644 --- a/src/libsync/propagateuploadv1.cpp +++ b/src/libsync/propagateuploadv1.cpp @@ -43,7 +43,7 @@ void PropagateUploadFileV1::doStartUpload() const SyncJournalDb::UploadInfo progressInfo = propagator()->_journal->getUploadInfo(_item->_file); - if (progressInfo._valid && progressInfo._modtime == _item->_modtime + if (progressInfo._valid && progressInfo.isChunked() && progressInfo._modtime == _item->_modtime && (progressInfo._contentChecksum == _item->_checksumHeader || progressInfo._contentChecksum.isEmpty() || _item->_checksumHeader.isEmpty())) { _startChunk = progressInfo._chunk; _transferId = progressInfo._transferid; @@ -55,7 +55,7 @@ void PropagateUploadFileV1::doStartUpload() SyncJournalDb::UploadInfo pi; pi._valid = true; pi._chunk = 0; - pi._transferid = _transferId; + pi._transferid = 0; // We set a null transfer id because it is not chunked. pi._modtime = _item->_modtime; pi._errorCount = 0; pi._contentChecksum = _item->_checksumHeader; @@ -206,12 +206,12 @@ void PropagateUploadFileV1::slotPutFinished() // The server needs some time to process the request and provide us with a poll URL if (_item->_httpErrorCode == 202) { - _finished = true; QString path = QString::fromUtf8(job->reply()->rawHeader("OC-Finish-Poll")); if (path.isEmpty()) { done(SyncFileItem::NormalError, tr("Poll URL missing")); return; } + _finished = true; startPollJob(path); return; } @@ -226,12 +226,12 @@ void PropagateUploadFileV1::slotPutFinished() // yet, the upload can be stopped and an error can be displayed, because // the server hasn't registered the new file yet. QByteArray etag = getEtagFromReply(job->reply()); - bool finished = etag.length() > 0; + _finished = etag.length() > 0; // Check if the file still exists const QString fullFilePath(propagator()->getFilePath(_item->_file)); if (!FileSystem::fileExists(fullFilePath)) { - if (!finished) { + if (!_finished) { abortWithError(SyncFileItem::SoftError, tr("The local file was removed during sync.")); return; } else { @@ -242,7 +242,7 @@ void PropagateUploadFileV1::slotPutFinished() // Check whether the file changed since discovery. if (!FileSystem::verifyFileUnchanged(fullFilePath, _item->_size, _item->_modtime)) { propagator()->_anotherSyncNeeded = true; - if (!finished) { + if (!_finished) { abortWithError(SyncFileItem::SoftError, tr("Local file changed during sync.")); // FIXME: the legacy code was retrying for a few seconds. // and also checking that after the last chunk, and removed the file in case of INSTRUCTION_NEW @@ -250,14 +250,13 @@ void PropagateUploadFileV1::slotPutFinished() } } - if (!finished) { + if (!_finished) { // Proceed to next chunk. if (_currentChunk >= _chunkCount) { if (!_jobs.empty()) { // just wait for the other job to finish. return; } - _finished = true; done(SyncFileItem::NormalError, tr("The server did not acknowledge the last chunk. (No e-tag was present)")); return; } @@ -287,9 +286,8 @@ void PropagateUploadFileV1::slotPutFinished() startNextChunk(); return; } - // the following code only happens after all chunks were uploaded. - _finished = true; + // the file id should only be empty for new files up- or downloaded QByteArray fid = job->reply()->rawHeader("OC-FileID"); if (!fid.isEmpty()) { @@ -309,6 +307,7 @@ void PropagateUploadFileV1::slotPutFinished() qCWarning(lcPropagateUpload) << "Server does not support X-OC-MTime" << job->reply()->rawHeader("X-OC-MTime"); // Well, the mtime was not set done(SyncFileItem::SoftError, "Server does not support X-OC-MTime"); + return; } finalize(); diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp index 0f9907ca4..64481ca60 100644 --- a/src/libsync/syncengine.cpp +++ b/src/libsync/syncengine.cpp @@ -303,6 +303,8 @@ void SyncEngine::deleteStaleUploadInfos(const SyncFileItemVector &syncItems) // Delete the stales chunk on the server. if (account()->capabilities().chunkingNg()) { foreach (uint transferId, ids) { + if (!transferId) + continue; // Was not a chunked upload QUrl url = Utility::concatUrlPath(account()->url(), QLatin1String("remote.php/dav/uploads/") + account()->davUser() + QLatin1Char('/') + QString::number(transferId)); (new DeleteJob(account(), url, this))->start(); } @@ -1630,10 +1632,10 @@ AccountPtr SyncEngine::account() const return _account; } -void SyncEngine::setLocalDiscoveryOptions(LocalDiscoveryStyle style, std::set<QByteArray> dirs) +void SyncEngine::setLocalDiscoveryOptions(LocalDiscoveryStyle style, std::set<QByteArray> paths) { _localDiscoveryStyle = style; - _localDiscoveryPaths = std::move(dirs); + _localDiscoveryPaths = std::move(paths); } bool SyncEngine::shouldDiscoverLocally(const QByteArray &path) const diff --git a/src/libsync/syncengine.h b/src/libsync/syncengine.h index f43e2f26b..e00034f4d 100644 --- a/src/libsync/syncengine.h +++ b/src/libsync/syncengine.h @@ -104,7 +104,7 @@ public: /** * Control whether local discovery should read from filesystem or db. * - * If style is DatabaseAndFilesystem, dirs a set of file paths relative to + * If style is DatabaseAndFilesystem, paths a set of file paths relative to * the synced folder. All the parent directories of these paths will not * be read from the db and scanned on the filesystem. * @@ -112,7 +112,7 @@ public: * revert afterwards. Use _lastLocalDiscoveryStyle to discover the last * sync's style. */ - void setLocalDiscoveryOptions(LocalDiscoveryStyle style, std::set<QByteArray> dirs = {}); + void setLocalDiscoveryOptions(LocalDiscoveryStyle style, std::set<QByteArray> paths = {}); /** * Returns whether the given folder-relative path should be locally discovered diff --git a/src/libsync/syncfileitem.h b/src/libsync/syncfileitem.h index 4272bf9e5..88421c39d 100644 --- a/src/libsync/syncfileitem.h +++ b/src/libsync/syncfileitem.h @@ -75,10 +75,9 @@ public: /** For files whose errors were blacklisted * * If an file is blacklisted due to an error it isn't even reattempted. These - * errors should appear in the issues tab, but not on the account settings and - * should not cause the sync run to fail. + * errors should appear in the issues tab but should be silent otherwise. * - * A DetailError that doesn't cause sync failure. + * A SoftError caused by blacklisting. */ BlacklistedError }; diff --git a/src/libsync/theme.cpp b/src/libsync/theme.cpp index e9e389fd6..da6e28344 100644 --- a/src/libsync/theme.cpp +++ b/src/libsync/theme.cpp @@ -20,6 +20,8 @@ #include <QtCore> #ifndef TOKEN_AUTH_ONLY #include <QtGui> +#include <QStyle> +#include <QApplication> #endif #include <QSslSocket> @@ -105,12 +107,16 @@ QString Theme::version() const return MIRALL_VERSION_STRING; } +QString Theme::configFileName() const +{ + return QStringLiteral(APPLICATION_EXECUTABLE ".cfg"); +} + #ifndef TOKEN_AUTH_ONLY -QIcon Theme::trayFolderIcon(const QString &backend) const +QIcon Theme::applicationIcon() const { - Q_UNUSED(backend) - return applicationIcon(); + return themeIcon(QStringLiteral(APPLICATION_ICON_NAME "-icon")); } /* @@ -217,6 +223,11 @@ QString Theme::defaultServerFolder() const return QLatin1String("/"); } +QString Theme::helpUrl() const +{ + return QString::fromLatin1("https://doc.owncloud.org/desktop/%1.%2/").arg(MIRALL_VERSION_MAJOR).arg(MIRALL_VERSION_MINOR); +} + QString Theme::overrideServerUrl() const { return QString(); @@ -311,21 +322,21 @@ QString Theme::gitSHA1() const QString Theme::about() const { - QString re; - re = tr("<p>Version %1. For more information please visit <a href='%2'>%3</a>.</p>") - .arg(MIRALL_VERSION_STRING) - .arg("http://" MIRALL_STRINGIFY(APPLICATION_DOMAIN)) - .arg(MIRALL_STRINGIFY(APPLICATION_DOMAIN)); - - re += tr("<p>Copyright ownCloud GmbH</p>"); - re += tr("<p>Distributed by %1 and licensed under the GNU General Public License (GPL) Version 2.0.<br/>" - "%2 and the %2 logo are registered trademarks of %1 in the " - "United States, other countries, or both.</p>") - .arg(APPLICATION_VENDOR) - .arg(APPLICATION_NAME); - - re += gitSHA1(); - return re; + QString devString; + devString = tr("<p>Version %2. For more information visit <a href=\"%3\">https://%4</a></p>" + "<p>For known issues and help, please visit: <a href=\"https://central.owncloud.org/c/desktop-client\">https://central.owncloud.org</a></p>" + "<p><small>By Klaas Freitag, Daniel Molkentin, Olivier Goffart, Markus Götz, " + " Jan-Christoph Borchardt, and others.</small></p>" + "<p>Copyright ownCloud GmbH</p>" + "<p>Licensed under the GNU General Public License (GPL) Version 2.0<br/>" + "ownCloud and the ownCloud Logo are registered trademarks of ownCloud GmbH " + "in the United States, other countries, or both.</p>") + .arg(Utility::escape(MIRALL_VERSION_STRING), + Utility::escape("https://" MIRALL_STRINGIFY(APPLICATION_DOMAIN)), + Utility::escape(MIRALL_STRINGIFY(APPLICATION_DOMAIN))); + + devString += gitSHA1(); + return devString; } #ifndef TOKEN_AUTH_ONLY diff --git a/src/libsync/theme.h b/src/libsync/theme.h index c2cd4922f..90ddd7ef1 100644 --- a/src/libsync/theme.h +++ b/src/libsync/theme.h @@ -84,24 +84,19 @@ public: * @brief configFileName * @return the name of the config file. */ - virtual QString configFileName() const = 0; + virtual QString configFileName() const; #ifndef TOKEN_AUTH_ONLY static QString hidpiFileName(const QString &fileName, QPaintDevice *dev = 0); /** - * the icon that is shown in the tray context menu left of the folder name - */ - virtual QIcon trayFolderIcon(const QString &) const; - - /** * get an sync state icon */ virtual QIcon syncStateIcon(SyncResult::Status, bool sysTray = false, bool sysTrayMenuVisible = false) const; virtual QIcon folderDisabledIcon() const; virtual QIcon folderOfflineIcon(bool sysTray = false, bool sysTrayMenuVisible = false) const; - virtual QIcon applicationIcon() const = 0; + virtual QIcon applicationIcon() const; #endif virtual QString statusHeaderText(SyncResult::Status) const; @@ -118,9 +113,11 @@ public: virtual bool multiAccount() const; /** - * URL to help file + * URL to documentation. + * This is opened in the browser when the "Help" action is selected from the tray menu. + * (If it is an empty stringn the action is removed from the menu. Defaults to ownCloud's help) */ - virtual QString helpUrl() const { return QString(); } + virtual QString helpUrl() const; /** * Setting a value here will pre-define the server url. |