1
0
mirror of https://github.com/chylex/Nextcloud-Desktop.git synced 2026-04-03 09:11:33 +02:00

Compare commits

...

16 Commits

Author SHA1 Message Date
Klaas Freitag
c4a9e524e6 Set version to 1.6.4 final. 2014-10-22 11:33:26 +02:00
Daniel Molkentin
1ad23e6ab0 NSIS: Fix copying of qtbase translations 2014-10-17 16:44:16 +02:00
Daniel Molkentin
f1dbba9e5a Second part of #1661
- QT_INSTALL_TRANSLATIONS was not defined in Qt5
- Some languages have been split up in multiple qm's. We only need qtbase for now
2014-10-15 17:10:41 +02:00
Daniel Molkentin
8d7408bb0c Correct lookup logic for Qt translations
Fixes #1661
2014-10-15 09:33:56 +02:00
Klaas Freitag
18f1b3c5ff Bumped version to 1.6.4 rc2 2014-10-10 11:53:13 +02:00
Daniel Molkentin
7dcbbb0046 Make sign_dmg.sh script fix frameworks correctly, resize disk image 2014-10-09 18:39:16 +02:00
Klaas Freitag
cc8408be8f Bumped version to 1.6.4rc1 2014-10-09 15:03:27 +02:00
Klaas Freitag
4902271b19 Updated Changelog for 1.6.4 2014-10-09 15:02:40 +02:00
Christian Kamm
b881b6db4e NetworkJobs: Propagator jobs keep others from expiring. #2155
In some owncloud server setups multiple concurrent connections for the
same session are not supported: owncloud/core#11153

This causes issues with multiple uploads and downloads. A usual symptom
is the quota job failing and the sync aborting.

This workaround lets activity on the propagator's GET and PUT jobs
reset the timeout of all network jobs. That way, queries like the quota
job would not time out while a large up/download is in progress.

(cherry picked from commit 2eec85a97c)
2014-10-09 11:29:12 +02:00
Christian Kamm
421177bfaf Download: Don't store message body if status != 2xx #2280
(cherry picked from commit 705cd571a5)
2014-10-09 11:23:39 +02:00
Christian Kamm
395ae1d4ed GET: Retry if bad range header used. #2280
* If a 416 is returned and we used a Range header, try again
  from scratch.
* The direct URL logic was also inconsistent for resumed downloads:
  it sent the Range header but didn't check the returned
  Content-Range header correctly. Now resuming is disabled for
  direct URL downloads.

(cherry picked from commit 48d3c75745)
2014-10-09 11:21:29 +02:00
Jürgen Weigert
c0bb4cd938 Fixed https://github.com/owncloud/mirall/issues/1699
Added missing copyright headers.
2014-09-18 12:32:57 +02:00
Christian Kamm
06bcb8f3c8 Propagator: Use csync to get the modification time.
See owncloud/core#9781

(cherry picked from commit 2630a73a1c)

Conflict: Move modtime comparison from socketapi.cpp to folder.cpp.
2014-09-17 07:33:19 +02:00
Olivier Goffart
8711a3ea6c csync_vio_local on windows: fix overflow when computing the size of file > 4GiB
MAXDWORD is 0xFFFFFFFF, so if we add one, it overflows and is 0.
We need to cast it to 64 bits before
2014-09-10 12:12:07 +02:00
Daniel Molkentin
984be698b4 raiseDialog: Actually send the XEvent
Amendment to 25c274a0bd
2014-09-05 22:21:05 +02:00
Christian Kamm
4566ca3127 FolderMan: Fix startFromScratch logic. #1989 2014-09-05 10:13:00 +02:00
31 changed files with 239 additions and 56 deletions

View File

@@ -1,5 +1,18 @@
ChangeLog
=========
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

View File

@@ -1,6 +1,6 @@
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 )

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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")

View File

@@ -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.

View File

@@ -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.

View File

@@ -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}

View File

@@ -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

View File

@@ -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

View File

@@ -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}

View File

@@ -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}
#

View File

@@ -378,6 +378,7 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
; Make sure only to copy qt, not qt_help, etc
File "${MING_SHARE}\qt5\translations\qt_??.qm"
File "${MING_SHARE}\qt5\translations\qt_??_??.qm"
File "${MING_SHARE}\qt5\translations\qtbase_*.qm"
File "${MING_SHARE}\qt5\translations\qtkeychain_*.qm"
SetOutPath "$INSTDIR\platforms"

View File

@@ -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)

View File

@@ -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
#

View File

@@ -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)

View File

@@ -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

View File

@@ -390,7 +390,6 @@ set(ownCloud ${ownCloud_old})
if (WITH_DBUS)
set(ADDITIONAL_APP_MODULES DBus)
endif(WITH_DBUS)
if(NOT BUILD_OWNCLOUD_OSX_BUNDLE AND NOT BUILD_LIBRARIES_ONLY)
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
@@ -427,8 +426,15 @@ elseif(NOT BUILD_LIBRARIES_ONLY)
set (QM_DIR ${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/Translations)
install(FILES ${mirall_I18N} DESTINATION ${QM_DIR})
get_target_property(_qmake Qt5::qmake LOCATION)
execute_process(COMMAND ${_qmake} -query QT_INSTALL_TRANSLATIONS
OUTPUT_VARIABLE QT_TRANSLATIONS_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
file(GLOB qt_I18N ${QT_TRANSLATIONS_DIR}/qt_??.qm ${QT_TRANSLATIONS_DIR}/qt_??_??.qm)
install(FILES ${qt_I18N} DESTINATION ${QM_DIR})
file(GLOB qtbase_I18N ${QT_TRANSLATIONS_DIR}/qtbase_??.qm ${QT_TRANSLATIONS_DIR}/qt_??_??.qm)
install(FILES ${qtbase_I18N} DESTINATION ${QM_DIR})
file(GLOB qtkeychain_I18N ${QT_TRANSLATIONS_DIR}/qtkeychain*.qm)
install(FILES ${qtkeychain_I18N} DESTINATION ${QM_DIR})
endif()

View File

@@ -154,8 +154,10 @@ public:
QNetworkAccessManager* networkAccessManager();
QuotaInfo *quotaInfo();
signals:
void stateChanged(int state);
void propagatorNetworkActivity();
protected Q_SLOTS:
void slotHandleErrors(QNetworkReply*,QList<QSslError>);

View File

@@ -532,12 +532,15 @@ void Application::setupTranslations()
setProperty("ui_lang", lang);
const QString qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
const QString qtTrFile = QLatin1String("qt_") + lang;
if (qtTranslator->load(qtTrFile, qtTrPath)) {
qtTranslator->load(qtTrFile, trPath);
const QString qtBaseTrFile = QLatin1String("qtbase_") + lang;
if (!qtTranslator->load(qtTrFile, qtTrPath)) {
if (!qtTranslator->load(qtTrFile, trPath)) {
qtTranslator->load(qtBaseTrFile, trPath);
}
}
const QString qtkeychainFile = QLatin1String("qt_") + lang;
if (!qtkeychainTranslator->load(qtkeychainFile, qtTrPath)) {
qtkeychainTranslator->load(qtkeychainFile, trPath);
const QString qtkeychainTrFile = QLatin1String("qtkeychain_") + lang;
if (!qtkeychainTranslator->load(qtkeychainTrFile, qtTrPath)) {
qtkeychainTranslator->load(qtkeychainTrFile, trPath);
}
if (!translator->isEmpty())
installTranslator(translator);

View File

@@ -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];

View File

@@ -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);
/**

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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()

View File

@@ -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,

View File

@@ -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
}

View File

@@ -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;
}

View File

@@ -133,6 +133,8 @@ public:
SyncFileItem::Status errorStatus() { return _errorStatus; }
quint64 resumeStart() const { return _resumeStart; }
virtual void slotTimeout();