mirror of
https://github.com/chylex/Nextcloud-Desktop.git
synced 2026-04-04 12:11:33 +02:00
Compare commits
15 Commits
v1.6.3-rc1
...
v1.6.4-rc2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18f1b3c5ff | ||
|
|
7dcbbb0046 | ||
|
|
cc8408be8f | ||
|
|
4902271b19 | ||
|
|
b881b6db4e | ||
|
|
421177bfaf | ||
|
|
395ae1d4ed | ||
|
|
c0bb4cd938 | ||
|
|
06bcb8f3c8 | ||
|
|
8711a3ea6c | ||
|
|
984be698b4 | ||
|
|
4566ca3127 | ||
|
|
cc1121ef00 | ||
|
|
6f9938a2b2 | ||
|
|
a650dce17f |
15
ChangeLog
15
ChangeLog
@@ -1,6 +1,19 @@
|
||||
ChangeLog
|
||||
=========
|
||||
version 1.6.3 (release 2014-09-xx)
|
||||
|
||||
version 1.6.4 (release 2014-10-xx)
|
||||
* Fix startup logic, fixes bug #1989
|
||||
* Fix raise dialog on X11
|
||||
* Win32: fix overflow when computing the size of file > 4GiB
|
||||
* Use a fixed function to get files modification time, the
|
||||
original one was broken for certain timezone issues, see
|
||||
core bug #9781 for details
|
||||
* Added some missing copyright headers
|
||||
* Avoid data corruption due to wrong error handling, bug #2280
|
||||
* Do improved request timeout handling to reduce the number of
|
||||
timed out jobs, bug #2155
|
||||
|
||||
version 1.6.3 (release 2014-09-03)
|
||||
* Fixed updater on OS X
|
||||
* Fixed memory leak in SSL button that could lead to quick memory draining
|
||||
* Fixed upload problem with files >4 GB
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
set( MIRALL_VERSION_MAJOR 1 )
|
||||
set( MIRALL_VERSION_MINOR 6 )
|
||||
set( MIRALL_VERSION_PATCH 3 )
|
||||
set( MIRALL_VERSION_PATCH 4 )
|
||||
set( MIRALL_SOVERSION 0 )
|
||||
|
||||
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||
set( MIRALL_VERSION_SUFFIX "rc1") #e.g. beta1, beta2, rc1
|
||||
set( MIRALL_VERSION_SUFFIX "rc2") #e.g. beta1, beta2, rc1
|
||||
endif( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||
|
||||
if( NOT DEFINED MIRALL_VERSION_BUILD )
|
||||
|
||||
@@ -23,6 +23,8 @@ fix_frameworks() {
|
||||
mkdir -p "${FMWK_PATH}/Versions/${QT_FMWK_VERSION}/Resources/"
|
||||
cp -avf "${QT_FMWK_PATH}/${FMWK}/Contents/Info.plist" "${FMWK_PATH}/Versions/${QT_FMWK_VERSION}/Resources"
|
||||
(cd "${FMWK_PATH}" && ln -sf "Versions/${QT_FMWK_VERSION}/Resources" "Resources")
|
||||
(cd "${FMWK_PATH}" && ln -sf "Versions/${QT_FMWK_VERSION}/${FMWK_NAME}")
|
||||
(cd "${FMWK_PATH}/Versions" && ln -sf "${QT_FMWK_VERSION}" "Current")
|
||||
perl -pi -e "s/${FMWK_NAME}_debug/${FMWK_NAME}/" "${FMWK_PATH}/Resources/Info.plist"
|
||||
done
|
||||
}
|
||||
@@ -30,6 +32,9 @@ fix_frameworks() {
|
||||
mount="/Volumes/$(basename "$src_dmg"|sed 's,-\([0-9]\)\(.*\),,')"
|
||||
test -e "$tmp_dmg" && rm -rf "$tmp_dmg"
|
||||
hdiutil convert "$src_dmg" -format UDRW -o "$tmp_dmg"
|
||||
#signing adds data, add a bit of space
|
||||
sectors=$(hdiutil resize -limits "$tmp_dmg" |grep -v cur|cut -f2)
|
||||
hdiutil resize -sectors $(($sectors+(51200))) "$tmp_dmg"
|
||||
hdiutil attach "$tmp_dmg"
|
||||
pushd "$mount"
|
||||
fix_frameworks "$mount"/*.app `qmake -query QT_INSTALL_LIBS` "$mount"/*.app/Contents/Frameworks
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# Always include srcdir and builddir in include path
|
||||
# This saves typing ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY} in
|
||||
# about every subdir
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# define system dependent compiler flags
|
||||
|
||||
include(CheckCCompilerFlag)
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
if (UNIX)
|
||||
# Suffix for Linux
|
||||
SET(LIB_SUFFIX
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# Set system vars
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# This module defines
|
||||
# INOTIFY_INCLUDE_DIR, where to find inotify.h, etc.
|
||||
# INOTIFY_FOUND, If false, do not try to use inotify.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# FIND_PACKAGE_VERSION_CHECK(NAME (DEFAULT_MSG|"Custom failure message"))
|
||||
# This function is intended to be used in FindXXX.cmake modules files.
|
||||
# It handles NAME_FIND_VERSION and NAME_VERSION variables in a Module.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
find_program(PDFLATEX_EXECUTABLE NAMES pdflatex
|
||||
HINTS
|
||||
$ENV{PDFLATEX_DIR}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# - Try to find QtKeychain
|
||||
# Once done this will define
|
||||
# QTKEYCHAIN_FOUND - System has QtKeychain
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# - Try to find QtKeychain
|
||||
# Once done this will define
|
||||
# QTKEYCHAIN_FOUND - System has QtKeychain
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
find_program(SPHINX_EXECUTABLE NAMES sphinx-build
|
||||
HINTS
|
||||
$ENV{SPHINX_DIR}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# - macro_copy_file(_src _dst)
|
||||
# Copies a file to ${_dst} only if ${_src} is different (newer) than ${_dst}
|
||||
#
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
include (MacroOptionalFindPackage)
|
||||
include (MacroLogFeature)
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# -helper macro to add a "doc" target with CMake build system.
|
||||
# and configure doxy.config.in to doxy.config
|
||||
#
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
|
||||
OUTPUT_VARIABLE GCC_VERSION)
|
||||
|
||||
@@ -240,7 +240,7 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
/* printf("Index: %I64i\n", FileIndex.QuadPart); */
|
||||
buf->inode = FileIndex.QuadPart;
|
||||
|
||||
buf->size = (fileInfo.nFileSizeHigh * (int64_t)(MAXDWORD+1)) + fileInfo.nFileSizeLow;
|
||||
buf->size = (fileInfo.nFileSizeHigh * ((int64_t)(MAXDWORD)+1)) + fileInfo.nFileSizeLow;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
|
||||
|
||||
/* Get the file time with a win32 call rather than through stat. See
|
||||
|
||||
@@ -39,6 +39,7 @@ static const char urlC[] = "url";
|
||||
static const char authTypeC[] = "authType";
|
||||
static const char userC[] = "user";
|
||||
static const char httpUserC[] = "http_user";
|
||||
static const char caCertsKeyC[] = "CaCertificates";
|
||||
|
||||
AccountManager *AccountManager::_instance = 0;
|
||||
|
||||
@@ -102,15 +103,15 @@ void Account::save()
|
||||
}
|
||||
settings->sync();
|
||||
|
||||
// ### TODO port away from MirallConfigFile
|
||||
MirallConfigFile cfg;
|
||||
// Save accepted certificates.
|
||||
settings->beginGroup(QLatin1String("General"));
|
||||
qDebug() << "Saving " << approvedCerts().count() << " unknown certs.";
|
||||
QByteArray certs;
|
||||
Q_FOREACH( const QSslCertificate& cert, approvedCerts() ) {
|
||||
certs += cert.toPem() + '\n';
|
||||
}
|
||||
if (!certs.isEmpty()) {
|
||||
cfg.setCaCerts( certs );
|
||||
settings->setValue( QLatin1String(caCertsKeyC), certs );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +177,7 @@ Account* Account::restore()
|
||||
|
||||
// now the cert, it is in the general group
|
||||
settings->beginGroup(QLatin1String("General"));
|
||||
acc->setApprovedCerts(QSslCertificate::fromData(settings->value(QLatin1String("CaCertificates")).toByteArray()));
|
||||
acc->setApprovedCerts(QSslCertificate::fromData(settings->value(caCertsKeyC).toByteArray()));
|
||||
acc->setMigrated(migratedCreds);
|
||||
return acc;
|
||||
}
|
||||
|
||||
@@ -154,8 +154,10 @@ public:
|
||||
QNetworkAccessManager* networkAccessManager();
|
||||
|
||||
QuotaInfo *quotaInfo();
|
||||
|
||||
signals:
|
||||
void stateChanged(int state);
|
||||
void propagatorNetworkActivity();
|
||||
|
||||
protected Q_SLOTS:
|
||||
void slotHandleErrors(QNetworkReply*,QList<QSslError>);
|
||||
|
||||
@@ -12,7 +12,10 @@
|
||||
*/
|
||||
|
||||
#include "filesystem.h"
|
||||
|
||||
#include "utility.h"
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QDebug>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
||||
@@ -24,11 +27,16 @@
|
||||
#include <winbase.h>
|
||||
#endif
|
||||
|
||||
|
||||
// We use some internals of csync:
|
||||
extern "C" int c_utimes(const char *, const struct timeval *);
|
||||
extern "C" void csync_win32_set_file_hidden( const char *file, bool h );
|
||||
|
||||
extern "C" {
|
||||
#include "vio/csync_vio_handle.h"
|
||||
#include "vio/csync_vio_file_stat.h"
|
||||
#include "vio/csync_vio_local.h"
|
||||
}
|
||||
|
||||
namespace Mirall {
|
||||
|
||||
bool FileSystem::fileEquals(const QString& fn1, const QString& fn2)
|
||||
@@ -69,6 +77,25 @@ void FileSystem::setFileHidden(const QString& filename, bool hidden)
|
||||
return csync_win32_set_file_hidden(filename.toUtf8().constData(), hidden);
|
||||
}
|
||||
|
||||
time_t FileSystem::getModTime(const QString &filename)
|
||||
{
|
||||
csync_vio_file_stat_t* stat = csync_vio_file_stat_new();
|
||||
qint64 result = -1;
|
||||
if (csync_vio_local_stat(filename.toUtf8().data(), stat) != -1
|
||||
&& (stat->fields & CSYNC_VIO_FILE_STAT_FIELDS_MTIME))
|
||||
{
|
||||
result = stat->mtime;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Could not get modification time for" << filename
|
||||
<< "with csync, using QFileInfo";
|
||||
result = Utility::qDateTimeToTime_t(QFileInfo(filename).lastModified());
|
||||
}
|
||||
csync_vio_file_stat_destroy(stat);
|
||||
return result;
|
||||
}
|
||||
|
||||
void FileSystem::setModTime(const QString& filename, time_t modTime)
|
||||
{
|
||||
struct timeval times[2];
|
||||
|
||||
@@ -30,6 +30,14 @@ bool fileEquals(const QString &fn1, const QString &fn2);
|
||||
/** Mark the file as hidden (only has effects on windows) */
|
||||
void setFileHidden(const QString& filename, bool hidden);
|
||||
|
||||
|
||||
/** Get the mtime for a filepath.
|
||||
*
|
||||
* Use this over QFileInfo::lastModified() to avoid timezone related bugs. See
|
||||
* owncloud/core#9781 for details.
|
||||
*/
|
||||
time_t getModTime(const QString &filename);
|
||||
|
||||
void setModTime(const QString &filename, time_t modTime);
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "mirall/clientproxy.h"
|
||||
#include "mirall/syncengine.h"
|
||||
#include "mirall/syncrunfilelog.h"
|
||||
#include "mirall/filesystem.h"
|
||||
|
||||
#include "creds/abstractcredentials.h"
|
||||
|
||||
@@ -776,7 +777,9 @@ SyncFileStatus Folder::fileStatus( const QString& fileName )
|
||||
}
|
||||
|
||||
// file was locally modified.
|
||||
if( stat == FILE_STATUS_NONE && fi.lastModified() != rec._modtime ) {
|
||||
if( stat == FILE_STATUS_NONE &&
|
||||
FileSystem::getModTime(fi.absoluteFilePath())
|
||||
!= Utility::qDateTimeToTime_t(rec._modtime) ) {
|
||||
stat = FILE_STATUS_EVAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -600,27 +600,41 @@ QString FolderMan::getBackupName( const QString& fullPathName ) const
|
||||
|
||||
bool FolderMan::startFromScratch( const QString& localFolder )
|
||||
{
|
||||
if( localFolder.isEmpty() ) return false;
|
||||
if( localFolder.isEmpty() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QFileInfo fi( localFolder );
|
||||
if( fi.exists() && fi.isDir() ) {
|
||||
QDir file = fi.dir();
|
||||
QDir parentDir( fi.dir() );
|
||||
QString folderName = fi.fileName();
|
||||
|
||||
// check if there are files in the directory.
|
||||
if( file.count() == 0 ) {
|
||||
// directory is existing, but its empty. Use it.
|
||||
// Adjust for case where localFolder ends with a /
|
||||
if ( fi.isDir() ) {
|
||||
folderName = parentDir.dirName();
|
||||
parentDir.cdUp();
|
||||
}
|
||||
|
||||
if( fi.exists() ) {
|
||||
// It exists, but is empty -> just reuse it.
|
||||
if( fi.isDir() && fi.dir().count() == 0 ) {
|
||||
qDebug() << "startFromScratch: Directory is empty!";
|
||||
return true;
|
||||
}
|
||||
QString newName = getBackupName( fi.absoluteFilePath() );
|
||||
|
||||
if( file.rename( fi.absoluteFilePath(), newName )) {
|
||||
if( file.mkdir( fi.absoluteFilePath() ) ) {
|
||||
return true;
|
||||
}
|
||||
// Make a backup of the folder/file.
|
||||
QString newName = getBackupName( parentDir.absoluteFilePath( folderName ) );
|
||||
if( !parentDir.rename( fi.absoluteFilePath(), newName ) ) {
|
||||
qDebug() << "startFromScratch: Could not rename" << fi.absoluteFilePath()
|
||||
<< "to" << newName;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
if( !parentDir.mkdir( fi.absoluteFilePath() ) ) {
|
||||
qDebug() << "startFromScratch: Could not mkdir" << fi.absoluteFilePath();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FolderMan::setDirtyProxy(bool value)
|
||||
|
||||
@@ -50,6 +50,15 @@ AbstractNetworkJob::AbstractNetworkJob(Account *account, const QString &path, QO
|
||||
_timer.setSingleShot(true);
|
||||
_timer.setInterval(10*1000); // default to 10 seconds.
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(slotTimeout()));
|
||||
|
||||
connect(this, SIGNAL(networkActivity()), SLOT(resetTimeout()));
|
||||
|
||||
// Network activity on the propagator jobs (GET/PUT) keeps all requests alive.
|
||||
// This is a workaround for OC instances which only support one
|
||||
// parallel up and download
|
||||
if (_account) {
|
||||
connect(_account, SIGNAL(propagatorNetworkActivity()), SLOT(resetTimeout()));
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractNetworkJob::setReply(QNetworkReply *reply)
|
||||
@@ -80,11 +89,6 @@ void AbstractNetworkJob::setIgnoreCredentialFailure(bool ignore)
|
||||
_ignoreCredentialFailure = ignore;
|
||||
}
|
||||
|
||||
void AbstractNetworkJob::setAccount(Account *account)
|
||||
{
|
||||
_account = account;
|
||||
}
|
||||
|
||||
void AbstractNetworkJob::setPath(const QString &path)
|
||||
{
|
||||
_path = path;
|
||||
@@ -93,6 +97,8 @@ void AbstractNetworkJob::setPath(const QString &path)
|
||||
void AbstractNetworkJob::setupConnections(QNetworkReply *reply)
|
||||
{
|
||||
connect(reply, SIGNAL(finished()), SLOT(slotFinished()));
|
||||
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), SIGNAL(networkActivity()));
|
||||
connect(reply, SIGNAL(uploadProgress(qint64,qint64)), SIGNAL(networkActivity()));
|
||||
}
|
||||
|
||||
QNetworkReply* AbstractNetworkJob::addTimer(QNetworkReply *reply)
|
||||
@@ -179,8 +185,11 @@ QString AbstractNetworkJob::responseTimestamp()
|
||||
return _responseTimestamp;
|
||||
}
|
||||
|
||||
AbstractNetworkJob::~AbstractNetworkJob() {
|
||||
_reply->deleteLater();
|
||||
AbstractNetworkJob::~AbstractNetworkJob()
|
||||
{
|
||||
if (_reply) {
|
||||
_reply->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractNetworkJob::start()
|
||||
|
||||
@@ -55,15 +55,14 @@ public:
|
||||
|
||||
virtual void start();
|
||||
|
||||
void setAccount(Account *account);
|
||||
Account* account() const { return _account; }
|
||||
|
||||
void setPath(const QString &path);
|
||||
QString path() const { return _path; }
|
||||
|
||||
void setReply(QNetworkReply *reply);
|
||||
QNetworkReply* reply() const { return _reply; }
|
||||
|
||||
|
||||
void setIgnoreCredentialFailure(bool ignore);
|
||||
bool ignoreCredentialFailure() const { return _ignoreCredentialFailure; }
|
||||
|
||||
@@ -75,6 +74,7 @@ public slots:
|
||||
void resetTimeout();
|
||||
signals:
|
||||
void networkError(QNetworkReply *reply);
|
||||
void networkActivity();
|
||||
protected:
|
||||
void setupConnections(QNetworkReply *reply);
|
||||
QNetworkReply* davRequest(const QByteArray& verb, const QString &relPath,
|
||||
|
||||
@@ -559,6 +559,13 @@ void ownCloudGui::raiseDialog( QWidget *raiseWidget )
|
||||
e.xclient.data.l[2] = 0;
|
||||
e.xclient.data.l[3] = 0l;
|
||||
e.xclient.data.l[4] = 0l;
|
||||
|
||||
Display *display = QX11Info::display();
|
||||
XSendEvent(display,
|
||||
RootWindow(display, DefaultScreen(display)),
|
||||
False, // propagate
|
||||
SubstructureRedirectMask|SubstructureNotifyMask,
|
||||
&e);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ QPixmap ownCloudTheme::wizardHeaderLogo() const
|
||||
|
||||
QString ownCloudTheme::appName() const
|
||||
{
|
||||
return QLatin1String("owncloud");
|
||||
return QLatin1String("ownCloud");
|
||||
}
|
||||
|
||||
QString ownCloudTheme::appNameGUI() const
|
||||
|
||||
@@ -73,7 +73,7 @@ void PUTFileJob::start() {
|
||||
}
|
||||
|
||||
connect(reply(), SIGNAL(uploadProgress(qint64,qint64)), this, SIGNAL(uploadProgress(qint64,qint64)));
|
||||
connect(reply(), SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(resetTimeout()));
|
||||
connect(this, SIGNAL(networkActivity()), account(), SIGNAL(propagatorNetworkActivity()));
|
||||
|
||||
AbstractNetworkJob::start();
|
||||
}
|
||||
@@ -302,8 +302,10 @@ void PropagateUploadFileQNAM::slotPutFinished()
|
||||
return;
|
||||
}
|
||||
|
||||
if (Utility::qDateTimeToTime_t(fi.lastModified()) != _item._modtime) {
|
||||
qDebug() << "The local file has changed during upload:" << _item._modtime << "!=" << Utility::qDateTimeToTime_t(fi.lastModified()) << fi.lastModified();
|
||||
const time_t new_mtime = FileSystem::getModTime(fi.absoluteFilePath());
|
||||
if (new_mtime != _item._modtime) {
|
||||
qDebug() << "The local file has changed during upload:" << _item._modtime << "!=" << new_mtime
|
||||
<< ", QFileInfo: " << Utility::qDateTimeToTime_t(fi.lastModified()) << fi.lastModified();
|
||||
_propagator->_activeJobs--;
|
||||
done(SyncFileItem::SoftError, tr("Local file changed during sync."));
|
||||
// FIXME: the legacy code was retrying for a few seconds.
|
||||
@@ -395,6 +397,12 @@ void PropagateUploadFileQNAM::abort()
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GETFileJob::start() {
|
||||
if (_resumeStart > 0) {
|
||||
_headers["Range"] = "bytes=" + QByteArray::number(_resumeStart) +'-';
|
||||
_headers["Accept-Ranges"] = "bytes";
|
||||
qDebug() << "Retry with range " << _headers["Range"];
|
||||
}
|
||||
|
||||
QNetworkRequest req;
|
||||
for(QMap<QByteArray, QByteArray>::const_iterator it = _headers.begin(); it != _headers.end(); ++it) {
|
||||
req.setRawHeader(it.key(), it.value());
|
||||
@@ -411,15 +419,22 @@ void GETFileJob::start() {
|
||||
connect(reply(), SIGNAL(metaDataChanged()), this, SLOT(slotMetaDataChanged()));
|
||||
connect(reply(), SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
|
||||
connect(reply(), SIGNAL(downloadProgress(qint64,qint64)), this, SIGNAL(downloadProgress(qint64,qint64)));
|
||||
connect(this, SIGNAL(networkActivity()), account(), SIGNAL(propagatorNetworkActivity()));
|
||||
|
||||
AbstractNetworkJob::start();
|
||||
}
|
||||
|
||||
void GETFileJob::slotMetaDataChanged()
|
||||
{
|
||||
if (reply()->error() != QNetworkReply::NoError
|
||||
|| reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() / 100 != 2) {
|
||||
// We will handle the error when the job is finished.
|
||||
int httpStatus = reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
// If the status code isn't 2xx, don't write the reply body to the file.
|
||||
// For any error: handle it when the job is finished, not here.
|
||||
if (httpStatus / 100 != 2) {
|
||||
_device->close();
|
||||
return;
|
||||
}
|
||||
if (reply()->error() != QNetworkReply::NoError) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -484,16 +499,17 @@ void GETFileJob::slotReadyRead()
|
||||
return;
|
||||
}
|
||||
|
||||
qint64 w = _device->write(buffer.constData(), r);
|
||||
if (w != r) {
|
||||
_errorString = _device->errorString();
|
||||
_errorStatus = SyncFileItem::NormalError;
|
||||
qDebug() << "Error while writing to file" << w << r << _errorString;
|
||||
reply()->abort();
|
||||
return;
|
||||
if (_device->isOpen()) {
|
||||
qint64 w = _device->write(buffer.constData(), r);
|
||||
if (w != r) {
|
||||
_errorString = _device->errorString();
|
||||
_errorStatus = SyncFileItem::NormalError;
|
||||
qDebug() << "Error while writing to file" << w << r << _errorString;
|
||||
reply()->abort();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
resetTimeout();
|
||||
}
|
||||
|
||||
void PropagateDownloadFileQNAM::start()
|
||||
@@ -558,17 +574,13 @@ void PropagateDownloadFileQNAM::start()
|
||||
/* Allow compressed content by setting the header */
|
||||
//headers["Accept-Encoding"] = "gzip";
|
||||
|
||||
if (_tmpFile.size() > 0) {
|
||||
quint64 done = _tmpFile.size();
|
||||
if (done == _item._size) {
|
||||
_startSize = _tmpFile.size();
|
||||
if (_startSize > 0) {
|
||||
if (_startSize == _item._size) {
|
||||
qDebug() << "File is already complete, no need to download";
|
||||
downloadFinished();
|
||||
return;
|
||||
}
|
||||
headers["Range"] = "bytes=" + QByteArray::number(done) +'-';
|
||||
headers["Accept-Ranges"] = "bytes";
|
||||
qDebug() << "Retry with range " << headers["Range"];
|
||||
_startSize = done;
|
||||
}
|
||||
|
||||
_job = new GETFileJob(AccountManager::instance()->account(),
|
||||
@@ -595,18 +607,33 @@ void PropagateDownloadFileQNAM::slotGetFinished()
|
||||
|
||||
QNetworkReply::NetworkError err = job->reply()->error();
|
||||
if (err != QNetworkReply::NoError) {
|
||||
if (_tmpFile.size() == 0) {
|
||||
// don't keep the temporary file if it is empty.
|
||||
_item._httpErrorCode = job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
// If we sent a 'Range' header and get 416 back, we want to retry
|
||||
// without the header.
|
||||
bool badRangeHeader = job->resumeStart() > 0 && _item._httpErrorCode == 416;
|
||||
if (badRangeHeader) {
|
||||
qDebug() << Q_FUNC_INFO << "server replied 416 to our range request, trying again without in next sync";
|
||||
}
|
||||
|
||||
// Don't keep the temporary file if it is empty or we
|
||||
// used a bad range header.
|
||||
if (_tmpFile.size() == 0 || badRangeHeader) {
|
||||
_tmpFile.close();
|
||||
_tmpFile.remove();
|
||||
_propagator->_journal->setDownloadInfo(_item._file, SyncJournalDb::DownloadInfo());
|
||||
}
|
||||
_item._httpErrorCode = job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
_propagator->_activeJobs--;
|
||||
SyncFileItem::Status status = job->errorStatus();
|
||||
if (status == SyncFileItem::NoStatus) {
|
||||
status = classifyError(err, _item._httpErrorCode);
|
||||
}
|
||||
if (badRangeHeader) {
|
||||
// Can't do this in classifyError() because 416 without a
|
||||
// Range header should result in NormalError.
|
||||
status = SyncFileItem::SoftError;
|
||||
}
|
||||
done(status, job->errorString());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -133,6 +133,8 @@ public:
|
||||
|
||||
SyncFileItem::Status errorStatus() { return _errorStatus; }
|
||||
|
||||
quint64 resumeStart() const { return _resumeStart; }
|
||||
|
||||
virtual void slotTimeout();
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user