Skip to content

Commit

Permalink
Add server capabilities for checksums owncloud#4638
Browse files Browse the repository at this point in the history
* Add checksums/supportedTypes and checksums/preferredUploadType
  capabilities. The default is that no checksum types are supported.

* Remove the transmissionChecksum config option. Servers must now
  use the capabilities to indicate that they are fine with the
  client sending checksums.

Note: This intentionally breaks brandings that overrode
Theme::transmissionChecksum. The override must be removed and the
server's capabilities must be adjusted to include the new values.
  • Loading branch information
ckamm committed Apr 15, 2016
1 parent a4f606c commit ea40e31
Show file tree
Hide file tree
Showing 11 changed files with 46 additions and 70 deletions.
20 changes: 5 additions & 15 deletions src/libsync/capabilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,28 +81,18 @@ bool Capabilities::isValid() const
return !_capabilities.isEmpty();
}

QList<QByteArray> Capabilities::supportedChecksumTypesAdvertised() const
{
return QList<QByteArray>();
}

QList<QByteArray> Capabilities::supportedChecksumTypes() const
{
auto list = supportedChecksumTypesAdvertised();
QByteArray cfgType = ConfigFile().transmissionChecksum().toLatin1();
if (!cfgType.isEmpty()) {
list.prepend(cfgType);
QList<QByteArray> list;
foreach (const auto & t, _capabilities["checksums"].toMap()["supportedTypes"].toList()) {
list.push_back(t.toByteArray());
}
return list;
}

QByteArray Capabilities::preferredChecksumType() const
QByteArray Capabilities::preferredUploadChecksumType() const
{
auto list = supportedChecksumTypes();
if (list.isEmpty()) {
return QByteArray();
}
return list.first();
return _capabilities["checksums"].toMap()["preferredUploadType"].toByteArray();
}

}
26 changes: 20 additions & 6 deletions src/libsync/capabilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,28 @@ class OWNCLOUDSYNC_EXPORT Capabilities {
/// returns true if the capabilities are loaded already.
bool isValid() const;

/// Returns the checksum types the server explicitly advertises
QList<QByteArray> supportedChecksumTypesAdvertised() const;

/// Like supportedChecksumTypesRaw(), but includes the type from the config
/**
* Returns the checksum types the server understands.
*
* When the client uses one of these checksumming algorithms in
* the OC-Checksum header of a file upload, the server will use
* it to validate that data was transmitted correctly.
*
* Path: checksums/supportedTypes
* Default: []
* Possible entries: "Adler32", "MD5", "SHA1"
*/
QList<QByteArray> supportedChecksumTypes() const;

/// Returns the checksum type that should be used for new uploads.
QByteArray preferredChecksumType() const;
/**
* The checksum algorithm that the server recommends for file uploads.
* This is just a preference, any algorithm listed in supportedTypes may be used.
*
* Path: checksums/preferredUploadType
* Default: empty, meaning "no preference"
* Possible values: empty or any of the supportedTypes
*/
QByteArray preferredUploadChecksumType() const;

private:
QVariantMap _capabilities;
Expand Down
7 changes: 4 additions & 3 deletions src/libsync/checksums.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "syncfileitem.h"
#include "propagatorjobs.h"
#include "account.h"
#include "configfile.h"

#include <qtconcurrentrun.h>

Expand Down Expand Up @@ -108,10 +109,10 @@ bool uploadChecksumEnabled()
return enabled;
}

bool downloadChecksumEnabled()
bool downloadChecksumValidationEnabled()
{
static bool enabled = qgetenv("OWNCLOUD_DISABLE_CHECKSUM_DOWNLOAD").isEmpty();
return enabled;
static bool disabledByConfig = ConfigFile().disableDownloadChecksumValidation();
return !disabledByConfig;
}

QByteArray contentChecksumType()
Expand Down
4 changes: 2 additions & 2 deletions src/libsync/checksums.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ bool parseChecksumHeader(const QByteArray& header, QByteArray* type, QByteArray*
/// Checks OWNCLOUD_DISABLE_CHECKSUM_UPLOAD
bool uploadChecksumEnabled();

/// Checks OWNCLOUD_DISABLE_CHECKSUM_DOWNLOAD
bool downloadChecksumEnabled();
/// Checks disableDownloadChecksumValidation from the config file
bool downloadChecksumValidationEnabled();

/// Checks OWNCLOUD_CONTENT_CHECKSUM_TYPE (default: SHA1)
QByteArray contentChecksumType();
Expand Down
15 changes: 6 additions & 9 deletions src/libsync/configfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ static const char updateCheckIntervalC[] = "updateCheckInterval";
static const char geometryC[] = "geometry";
static const char timeoutC[] = "timeout";
static const char chunkSizeC[] = "chunkSize";
static const char transmissionChecksumC[] = "transmissionChecksum";
static const char disableDownloadChecksumValidationC[] = "disableDownloadChecksumValidation";

static const char proxyHostC[] = "Proxy/host";
static const char proxyTypeC[] = "Proxy/type";
Expand Down Expand Up @@ -129,18 +129,15 @@ quint64 ConfigFile::chunkSize() const
return settings.value(QLatin1String(chunkSizeC), 10*1000*1000).toLongLong(); // default to 10 MB
}

QString ConfigFile::transmissionChecksum() const
bool ConfigFile::disableDownloadChecksumValidation() const
{
QSettings settings(configFile(), QSettings::IniFormat);

QString checksum = settings.value(QLatin1String(transmissionChecksumC), QString()).toString();

if( checksum.isEmpty() ) {
// if the config file setting is empty, maybe the Branding requires it.
checksum = Theme::instance()->transmissionChecksum();
QVariant value = settings.value(QLatin1String(disableDownloadChecksumValidationC));
if (!value.isValid()) {
return false;
}

return checksum;
return value.toBool();
}

void ConfigFile::setOptionalDesktopNotifications(bool show)
Expand Down
12 changes: 7 additions & 5 deletions src/libsync/configfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,13 @@ class OWNCLOUDSYNC_EXPORT ConfigFile
int timeout() const;
quint64 chunkSize() const;

// send a checksum as a header along with the transmission or not.
// possible values:
// empty: no checksum calculated or expected.
// or "Adler32", "MD5", "SHA1"
QString transmissionChecksum() const;
/** Whether to disable download checksum validation.
*
* By default (false) received checksums will be validated. This flag
* can disable checksum validation and is intended for debugging purposes
* only.
*/
bool disableDownloadChecksumValidation() const;

void saveGeometry(QWidget *w);
void restoreGeometry(QWidget *w);
Expand Down
15 changes: 0 additions & 15 deletions src/libsync/owncloudpropagator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,21 +299,6 @@ void OwncloudPropagator::start(const SyncFileItemVector& items)
{
Q_ASSERT(std::is_sorted(items.begin(), items.end()));

/* Check and log the transmission checksum type */
ConfigFile cfg;
const QString checksumType = cfg.transmissionChecksum();

/* if the checksum type is empty, it is not sent. No error */
if( !checksumType.isEmpty() ) {
if( checksumType == checkSumAdlerC ||
checksumType == checkSumMD5C ||
checksumType == checkSumSHA1C ) {
qDebug() << "Client sends transmission checksum type" << checksumType;
} else {
qWarning() << "Unknown transmission checksum type from config" << checksumType;
}
}

/* This builds all the jobs needed for the propagation.
* Each directory is a PropagateDirectory job, which contains the files in it.
* In order to do that we loop over the items. (which are sorted by destination)
Expand Down
2 changes: 1 addition & 1 deletion src/libsync/propagatedownload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ void PropagateDownloadFileQNAM::slotGetFinished()
connect(validator, SIGNAL(validationFailed(QString)),
SLOT(slotChecksumFail(QString)));
auto checksumHeader = job->reply()->rawHeader(checkSumHeaderC);
if (!downloadChecksumEnabled()) {
if (!downloadChecksumValidationEnabled()) {
checksumHeader.clear();
}
validator->start(_tmpFile.fileName(), checksumHeader);
Expand Down
2 changes: 1 addition & 1 deletion src/libsync/propagateupload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ void PropagateUploadFileQNAM::slotComputeTransmissionChecksum(const QByteArray&
// Compute the transmission checksum.
auto computeChecksum = new ComputeChecksum(this);
if (uploadChecksumEnabled()) {
computeChecksum->setChecksumType(_propagator->account()->capabilities().preferredChecksumType());
computeChecksum->setChecksumType(_propagator->account()->capabilities().preferredUploadChecksumType());
} else {
computeChecksum->setChecksumType(QByteArray());
}
Expand Down
5 changes: 0 additions & 5 deletions src/libsync/theme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,6 @@ QString Theme::updateCheckUrl() const
return QLatin1String("https://updates.owncloud.com/client/");
}

QString Theme::transmissionChecksum() const
{
return QString::null; // No transmission by default.
}

qint64 Theme::newBigFolderSizeLimit() const
{
// Default to 500MB
Expand Down
8 changes: 0 additions & 8 deletions src/libsync/theme.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,6 @@ class OWNCLOUDSYNC_EXPORT Theme : public QObject
* to nothing selected
*/
virtual bool wizardSelectiveSyncDefaultNothing() const;
/**
* @brief Add an additional checksum header to PUT requests and compare them
* if they come with GET requests.
* This value sets the checksum type (SHA1, MD5 or Adler32) or is left empty
* if no checksumming is wanted. In that case it can still be overwritten in
* the client config file.
*/
virtual QString transmissionChecksum() const;

/**
* Default option for the newBigFolderSizeLimit.
Expand Down

0 comments on commit ea40e31

Please sign in to comment.