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

Compare commits

...

41 Commits

Author SHA1 Message Date
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
Christian Kamm
cc1121ef00 Account: Fix cert save/restore from settings. #2160 2014-09-04 15:24:46 +02:00
Markus Goetz
6f9938a2b2 ownCloudTheme: Fix casing in appName()
Without this fix, the section in the config file uses the wrong name,
leading to re-configuration of the client needed.
2014-09-03 16:07:05 +02:00
Daniel Molkentin
a650dce17f 1.6.3 final 2014-09-03 15:03:23 +02:00
Daniel Molkentin
7ddd3a36c7 Update ChangeLog 2014-09-02 16:41:41 +02:00
Markus Goetz
c46f1aba89 Sparkle: Keep permissions from bundle
(cherry picked from commit 0be4b59cff)
2014-09-02 16:38:45 +02:00
Daniel Molkentin
2ab19b23d7 Make Settings Window close on Ctrl+W
Fixes #2141
2014-09-02 13:58:55 +02:00
Daniel Molkentin
d770f9cc1a Account Migrator: Switch to string comparison for URLs.
QUrl does not normalize trailing slashes, so there is no benefit
of using QUrl here.
2014-08-31 19:50:20 +02:00
Daniel Molkentin
9d3b09159e Edit ChangeLog 2014-08-31 19:13:57 +02:00
Klaas Freitag
819cb74cc3 Changelog bumped for 1.6.3 2014-08-30 19:07:59 +02:00
Klaas Freitag
2407469104 Bump version to 1.6.3 beta1. 2014-08-30 18:18:53 +02:00
Klaas Freitag
c1faff513e Merge remote-tracking branch 'origin/reuse_oc_config' into 1.6 2014-08-29 20:07:27 +02:00
Daniel Molkentin
e5b4438d5c X11: Bring Settings window to front when launched
(cherry picked from commit 25c274a0bd)

Conflicts:
	src/mirall/owncloudgui.cpp
2014-08-28 18:14:27 +02:00
Olivier Goffart
7ec43e9f36 uploading: make sure to cast to uint64 to avoid integer overflow
(cherry picked from commit 302499b483)
2014-08-26 16:36:35 +02:00
Olivier Goffart
c4dabe7ed2 SSLButton: fix memleak
(cherry picked from commit 9b88c7d3c1)
2014-08-26 16:36:35 +02:00
Daniel Molkentin
6b4f11f4aa Fix backporting glitch the broke compilation 2014-08-14 16:36:03 +02:00
Daniel Molkentin
1edf3dd503 Always handle 401 requests, except for network jobs
It is not enough to only implement it for the QNAM returned
by the ShibbolethCredentials, because we sometimes need it
when we have no valid credentials set (and are using dummy
credentials in the course).  The main use case is the
Webview opened by Shibboleth for FBA.

But as a side-effect, we can use it to handle auth requests
from the updater and other places.

(cherry picked from commit 1544606bf0)

Conflicts:
	src/CMakeLists.txt
	src/creds/shibbolethcredentials.h
2014-08-13 15:04:31 +02:00
Markus Goetz
1daf9bc80b Tests: Give a more random name to test directories 2014-08-12 16:25:04 +02:00
Markus Goetz
b7a91a6998 Fix compile and adapt code to be similar to 1.7/master 2014-08-12 15:24:42 +02:00
Markus Goetz
69dffc8882 OS X: Finally(?) fix stay-on-top behaviour of settings dialog
Fixes #1795

Conflicts:
	.gitmodules
	src/mirall/owncloudgui.cpp
2014-08-12 14:54:59 +02:00
Klaas Freitag
e17243bc1f AccountMigrator: Read path from QDir::fromNativeSeperators(), add debug. 2014-06-25 11:38:08 +02:00
Klaas Freitag
0e45dd7a3d AccountMigrator: Do not inherit from QObject as it is not needed yet.
As requested by Danimos review.
2014-06-25 11:38:08 +02:00
Klaas Freitag
65f313f1b4 Account: Added missing include statement. 2014-06-25 11:38:08 +02:00
Klaas Freitag
da4958c716 Account: Read settings from ownCloud config if no branded exists.
If there is not yet a config for a branded client, but one for the
"normal" client targetting the same URL, it will be migrated.
2014-06-25 11:38:08 +02:00
Klaas Freitag
653b8494f5 FolderMan: Migrate folderlist if no folder definitions can be found
and the account indicates that it was migrated. In that case,
read the folder definitions from the ownCloud config directory.
2014-06-25 11:38:08 +02:00
Klaas Freitag
6ed6f84f6e Account: Add a wasMigrated flag.
If an account in a branded client was migrated from a former ownCloud
configuration, the method wasMigrated() will return true.
2014-06-25 11:38:08 +02:00
Klaas Freitag
ff0ba56bc3 ownCloud Theme: Implement appName() and appNameGUI(). 2014-06-25 11:38:08 +02:00
Klaas Freitag
e795d04f30 cfg migration: Add a account migrator class. 2014-06-25 11:38:08 +02:00
Klaas Freitag
8d3806b080 folderman: make escapeAlias public as its now used in accountmigrator. 2014-06-25 11:38:08 +02:00
Klaas Freitag
5597ebe455 Account: Add a scoped pointer to the ownCloud theme. 2014-06-25 11:38:07 +02:00
51 changed files with 572 additions and 107 deletions

2
.gitmodules vendored
View File

@@ -3,4 +3,4 @@
url = https://github.com/owncloud/documentation
[submodule "src/3rdparty/qtmacgoodies"]
path = src/3rdparty/qtmacgoodies
url = git://github.com/shadone/qtmacgoodies.git
url = git://github.com/guruz/qtmacgoodies.git

View File

@@ -1,5 +1,26 @@
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
* Fixed upload problem with files >4 GB
* MacOSX, Linux: Bring Settings window to front properly
* Branded clients: If no configuration is detected, try to import the data
from a previously configured community edition.
version 1.6.2 (release 2014-07-28 )
* Limit the HTTP buffer size when downloading to limit memory consumption.
* Another small mem leak fixed in HTTP Credentials.

View File

@@ -1,10 +1,10 @@
set( MIRALL_VERSION_MAJOR 1 )
set( MIRALL_VERSION_MINOR 6 )
set( MIRALL_VERSION_PATCH 2 )
set( MIRALL_VERSION_PATCH 4 )
set( MIRALL_SOVERSION 0 )
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
set( MIRALL_VERSION_SUFFIX "") #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 )

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

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

@@ -34,6 +34,7 @@ use LWP::UserAgent;
use LWP::Protocol::https;
use HTTP::Request::Common qw( POST GET DELETE );
use File::Basename;
use POSIX qw/strftime/;
use Encode qw(from_to);
use utf8;
@@ -128,8 +129,9 @@ sub initTesting(;$)
# $d->DebugLevel(3);
$prefix = "t1" unless( defined $prefix );
my $dirId = sprintf("%#.3o", rand(1000));
my $dir = sprintf( "%s-%s/", $prefix, $dirId );
my $dirId = sprintf("%02d", rand(100));
my $dateTime = strftime('%Y%m%d%H%M%S',localtime);
my $dir = sprintf( "%s-%s-%s/", $prefix, $dateTime, $dirId );
$localDir = $dir;
$localDir .= "/" unless( $localDir =~ /\/$/ );

View File

@@ -45,6 +45,7 @@ if (APPLE)
list(APPEND 3rdparty_SRC
3rdparty/qtmacgoodies/src/macpreferenceswindow.mm
3rdparty/qtmacgoodies/src/macstandardicon.mm
3rdparty/qtmacgoodies/src/macwindow.mm
)
endif()
@@ -82,6 +83,7 @@ set(libsync_SRCS
mirall/folderman.cpp
mirall/folder.cpp
mirall/folderwatcher.cpp
mirall/authenticationdialog.cpp
mirall/syncresult.cpp
mirall/mirallconfigfile.cpp
mirall/syncengine.cpp
@@ -105,6 +107,7 @@ set(libsync_SRCS
mirall/clientproxy.cpp
mirall/syncrunfilelog.cpp
mirall/cookiejar.cpp
mirall/accountmigrator.cpp
creds/dummycredentials.cpp
creds/abstractcredentials.cpp
creds/credentialsfactory.cpp
@@ -124,7 +127,6 @@ else()
creds/shibbolethcredentials.cpp
creds/shibboleth/shibbolethwebview.cpp
creds/shibboleth/shibbolethrefresher.cpp
creds/shibboleth/authenticationdialog.cpp
creds/shibboleth/shibbolethuserjob.cpp
)
endif()
@@ -246,7 +248,7 @@ else()
install(TARGETS ${synclib_NAME} DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/MacOS)
if (SPARKLE_FOUND)
install(DIRECTORY "${SPARKLE_LIBRARY}"
DESTINATION "${OWNCLOUD_OSX_BUNDLE}/Contents/Frameworks")
DESTINATION "${OWNCLOUD_OSX_BUNDLE}/Contents/Frameworks" USE_SOURCE_PERMISSIONS)
endif (SPARKLE_FOUND)
endif()

View File

@@ -20,7 +20,6 @@
#include <QDebug>
#include "creds/shibbolethcredentials.h"
#include "creds/shibboleth/authenticationdialog.h"
#include "creds/shibboleth/shibbolethwebview.h"
#include "creds/shibboleth/shibbolethrefresher.h"
#include "creds/shibbolethcredentials.h"
@@ -173,8 +172,6 @@ QNetworkAccessManager* ShibbolethCredentials::getQNAM() const
QNetworkAccessManager* qnam(new MirallAccessManager);
connect(qnam, SIGNAL(finished(QNetworkReply*)),
this, SLOT(slotReplyFinished(QNetworkReply*)));
connect(qnam, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
SLOT(slotHandleAuthentication(QNetworkReply*,QAuthenticator*)));
return qnam;
}
@@ -319,23 +316,6 @@ void ShibbolethCredentials::invalidateAndFetch(Account* account)
job->start();
}
void ShibbolethCredentials::slotHandleAuthentication(QNetworkReply *reply, QAuthenticator *authenticator)
{
Q_UNUSED(reply)
QUrl url = reply->url();
// show only scheme, host and port
QUrl reducedUrl;
reducedUrl.setScheme(url.scheme());
reducedUrl.setHost(url.host());
reducedUrl.setPort(url.port());
AuthenticationDialog dialog(authenticator->realm(), reducedUrl.toString());
if (dialog.exec() == QDialog::Accepted) {
authenticator->setUser(dialog.user());
authenticator->setPassword(dialog.password());
}
}
void ShibbolethCredentials::slotInvalidateAndFetchInvalidateDone(QKeychain::Job* job)
{
Account *account = qvariant_cast<Account*>(job->property("account"));

View File

@@ -63,7 +63,6 @@ public:
public Q_SLOTS:
void invalidateAndFetch(Account *account);
void slotHandleAuthentication(QNetworkReply*,QAuthenticator*);
private Q_SLOTS:
void onShibbolethCookieReceived(const QNetworkCookie&, Account*);

View File

@@ -18,6 +18,7 @@
#include "mirall/mirallconfigfile.h"
#include "mirall/mirallaccessmanager.h"
#include "mirall/quotainfo.h"
#include "mirall/owncloudtheme.h"
#include "creds/abstractcredentials.h"
#include "creds/credentialsfactory.h"
@@ -27,6 +28,8 @@
#include <QNetworkAccessManager>
#include <QSslSocket>
#include <QNetworkCookieJar>
#include <QFileInfo>
#include <QDir>
#include <QDebug>
@@ -36,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;
@@ -71,6 +75,7 @@ Account::Account(AbstractSslErrorHandler *sslErrorHandler, QObject *parent)
, _treatSslErrorsAsFailure(false)
, _state(Account::Disconnected)
, _davPath("remote.php/webdav/")
, _wasMigrated(false)
{
qRegisterMetaType<Account*>("Account*");
}
@@ -98,25 +103,66 @@ 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 );
}
}
Account* Account::restore()
{
// try to open the correctly themed settings
QScopedPointer<QSettings> settings(settingsWithGroup(Theme::instance()->appName()));
Account *acc = 0;
bool migratedCreds = false;
// if the settings file could not be opened, the childKeys list is empty
if( settings->childKeys().isEmpty() ) {
// Now try to open the original ownCloud settings to see if they exist.
QString oCCfgFile = QDir::fromNativeSeparators( settings->fileName() );
// replace the last two segments with ownCloud/owncloud.cfg
oCCfgFile = oCCfgFile.left( oCCfgFile.lastIndexOf('/'));
oCCfgFile = oCCfgFile.left( oCCfgFile.lastIndexOf('/'));
oCCfgFile += QLatin1String("/ownCloud/owncloud.cfg");
qDebug() << "Migrate: checking old config " << oCCfgFile;
QFileInfo fi( oCCfgFile );
if( fi.isReadable() ) {
QSettings *oCSettings = new QSettings(oCCfgFile, QSettings::IniFormat);
oCSettings->beginGroup(QLatin1String("ownCloud"));
// Check the theme url to see if it is the same url that the oC config was for
QString overrideUrl = Theme::instance()->overrideServerUrl();
if( !overrideUrl.isEmpty() ) {
if (overrideUrl.endsWith('/')) { overrideUrl.chop(1); }
QString oCUrl = oCSettings->value(QLatin1String(urlC)).toString();
if (oCUrl.endsWith('/')) { oCUrl.chop(1); }
// in case the urls are equal reset the settings object to read from
// the ownCloud settings object
qDebug() << "Migrate oC config if " << oCUrl << " == " << overrideUrl << ":"
<< (oCUrl == overrideUrl ? "Yes" : "No");
if( oCUrl == overrideUrl ) {
migratedCreds = true;
settings.reset( oCSettings );
} else {
delete oCSettings;
}
}
}
}
if (!settings->childKeys().isEmpty()) {
Account *acc = new Account;
MirallConfigFile cfg;
acc->setApprovedCerts(QSslCertificate::fromData(cfg.caCerts()));
acc = new Account;
acc->setUrl(settings->value(QLatin1String(urlC)).toUrl());
acc->setCredentials(CredentialsFactory::create(settings->value(QLatin1String(authTypeC)).toString()));
@@ -128,6 +174,11 @@ Account* Account::restore()
continue;
acc->_settingsMap.insert(key, settings->value(key));
}
// now the cert, it is in the general group
settings->beginGroup(QLatin1String("General"));
acc->setApprovedCerts(QSslCertificate::fromData(settings->value(caCertsKeyC).toByteArray()));
acc->setMigrated(migratedCreds);
return acc;
}
return 0;
@@ -364,4 +415,14 @@ void Account::slotHandleErrors(QNetworkReply *reply , QList<QSslError> errors)
}
}
bool Account::wasMigrated()
{
return _wasMigrated;
}
void Account::setMigrated(bool mig)
{
_wasMigrated = mig;
}
} // namespace Mirall

View File

@@ -108,6 +108,13 @@ public:
/** Returns webdav entry URL, based on url() */
QUrl davUrl() const;
/** set and retrieve the migration flag: if an account of a branded
* client was migrated from a former ownCloud Account, this is true
*/
void setMigrated(bool mig);
bool wasMigrated();
QList<QNetworkCookie> lastAuthCookies() const;
QNetworkReply* headRequest(const QString &relPath);
@@ -147,8 +154,10 @@ public:
QNetworkAccessManager* networkAccessManager();
QuotaInfo *quotaInfo();
signals:
void stateChanged(int state);
void propagatorNetworkActivity();
protected Q_SLOTS:
void slotHandleErrors(QNetworkReply*,QList<QSslError>);
@@ -166,6 +175,7 @@ private:
int _state;
static QString _configFileName;
QString _davPath; // default "remote.php/webdav/";
bool _wasMigrated;
};
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "mirall/accountmigrator.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/folderman.h"
#include "mirall/theme.h"
#include <QSettings>
#include <QStringList>
#include <QDir>
#include <QFileInfo>
#include <QDebug>
namespace Mirall {
// The purpose of this class is to migrate an existing account that
// was set up with an unbranded client to an branded one.
// The usecase is: Usually people try first with the community client,
// later they maybe switch to a branded client. When they install the
// branded client first, it should automatically pick the information
// from the already configured account.
AccountMigrator::AccountMigrator()
{
}
// the list of folder definitions which are files in the directory "folders"
// underneath the ownCloud configPath (with ownCloud as a last segment)
// need to be copied to the themed path and adjusted.
QStringList AccountMigrator::migrateFolderDefinitons()
{
MirallConfigFile cfg;
QStringList re;
QString themePath = cfg.configPath();
// create the original ownCloud config path out of the theme path
// by removing the theme folder and append ownCloud.
QString oCPath = themePath;
if( oCPath.endsWith(QLatin1Char('/')) ) {
oCPath.truncate( oCPath.length()-1 );
}
oCPath = oCPath.left( oCPath.lastIndexOf('/'));
themePath += QLatin1String( "folders");
oCPath += QLatin1String( "/ownCloud/folders" );
qDebug() << "Migrator: theme-path: " << themePath;
qDebug() << "Migrator: ownCloud path: " << oCPath;
// get a dir listing of the ownCloud folder definitions and copy
// them over to the theme dir
QDir oCDir(oCPath);
oCDir.setFilter( QDir::Files );
QStringList files = oCDir.entryList();
foreach( const QString& file, files ) {
QString escapedAlias = FolderMan::instance()->escapeAlias(file);
QString themeFile = themePath + QDir::separator() + file;
QString oCFile = oCPath+QDir::separator()+file;
if( QFile::copy( oCFile, themeFile ) ) {
re.append(file);
qDebug() << "Migrator: Folder definition migrated: " << file;
// fix the connection entry of the folder definition
QSettings settings(themeFile, QSettings::IniFormat);
settings.beginGroup( escapedAlias );
settings.setValue(QLatin1String("connection"), Theme::instance()->appName());
settings.sync();
}
}
return re;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef ACCOUNTMIGRATOR_H
#define ACCOUNTMIGRATOR_H
#include <QStringList>
namespace Mirall {
class AccountMigrator {
public:
explicit AccountMigrator();
/**
* @brief migrateFolderDefinitons - migrate the folder definition files
* @return the list of migrated folder definitions
*/
QStringList migrateFolderDefinitons();
signals:
public slots:
};
}
#endif // ACCOUNTMIGRATOR_H

View File

@@ -713,7 +713,7 @@ void AccountSettings::slotIgnoreFilesEditor()
_ignoreEditor->setAttribute( Qt::WA_DeleteOnClose, true );
_ignoreEditor->open();
} else {
Utility::raiseDialog(_ignoreEditor);
ownCloudGui::raiseDialog(_ignoreEditor);
}
}

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

@@ -13,10 +13,13 @@
*/
#include "mirall/folderman.h"
#include "mirall/account.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/folder.h"
#include "mirall/syncresult.h"
#include "mirall/theme.h"
#include "mirall/accountmigrator.h"
#include <neon/ne_socket.h>
@@ -147,6 +150,15 @@ int FolderMan::setupFolders()
dir.setFilter(QDir::Files | QDir::Hidden);
QStringList list = dir.entryList();
if( list.count() == 0 ) {
// maybe the account was just migrated.
Account *acc = AccountManager::instance()->account();
if ( acc && acc->wasMigrated() ) {
AccountMigrator accMig;
list = accMig.migrateFolderDefinitons();
}
}
foreach ( const QString& alias, list ) {
Folder *f = setupFolderFromConfigFile( alias );
if( f ) {
@@ -588,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

@@ -83,6 +83,8 @@ public:
void removeMonitorPath( const QString& alias, const QString& path );
void addMonitorPath( const QString& alias, const QString& path );
QString escapeAlias( const QString& ) const;
signals:
/**
* signal to indicate a folder named by alias has changed its sync state.
@@ -130,7 +132,6 @@ private:
// Escaping of the alias which is used in QSettings AND the file
// system, thus need to be escaped.
QString escapeAlias( const QString& ) const;
QString unescapeAlias( const QString& ) const;
void removeFolder( const QString& );

View File

@@ -12,6 +12,7 @@
*/
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkProxy>
#include <QAuthenticator>
#include <QSslConfiguration>
@@ -19,6 +20,8 @@
#include "mirall/cookiejar.h"
#include "mirall/mirallaccessmanager.h"
#include "mirall/utility.h"
#include "mirall/authenticationdialog.h"
namespace Mirall
{
@@ -33,8 +36,11 @@ MirallAccessManager::MirallAccessManager(QObject* parent)
setProxy(proxy);
#endif
setCookieJar(new CookieJar);
QObject::connect(this, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
this, SLOT(slotProxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
connect(this, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
this, SLOT(slotProxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
connect(this, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
this, SLOT(slotAuthenticationRequired(QNetworkReply*,QAuthenticator*)));
}
QNetworkReply* MirallAccessManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest& request, QIODevice* outgoingData)
@@ -60,5 +66,27 @@ void MirallAccessManager::slotProxyAuthenticationRequired(const QNetworkProxy &p
authenticator->setPassword(proxy.password());
}
}
void MirallAccessManager::slotAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
{
// do not handle 401 created by the networkjobs. We may want
// to eventually exempt some, but for now we need
// it only for other things, e.g. the browser. Would we handle
// network jobs, this would break the wizard logic
if (reply->property("doNotHandleAuth").toBool()) {
return;
}
QUrl url = reply->url();
// show only scheme, host and port
QUrl reducedUrl;
reducedUrl.setScheme(url.scheme());
reducedUrl.setHost(url.host());
reducedUrl.setPort(url.port());
AuthenticationDialog dialog(authenticator->realm(), reducedUrl.toString());
if (dialog.exec() == QDialog::Accepted) {
authenticator->setUser(dialog.user());
authenticator->setPassword(dialog.password());
}
}
} // ns Mirall

View File

@@ -31,6 +31,8 @@ protected:
QNetworkReply* createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest& request, QIODevice* outgoingData = 0);
protected slots:
void slotProxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator);
void slotAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator);
};
} // ns Mirall

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)
@@ -57,6 +66,7 @@ void AbstractNetworkJob::setReply(QNetworkReply *reply)
if (_reply) {
_reply->deleteLater();
}
reply->setProperty("doNotHandleAuth", true);
_reply = reply;
}
@@ -79,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;
@@ -92,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)
@@ -178,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

@@ -21,6 +21,7 @@
#include "mirall/owncloudsetupwizard.h"
#if defined(Q_OS_MAC)
# include "mirall/settingsdialogmac.h"
# include "macwindow.h" // qtmacgoodies
#else
# include "mirall/settingsdialog.h"
#endif
@@ -33,6 +34,10 @@
#include <QMessageBox>
#include <QSignalMapper>
#if defined(Q_OS_X11)
#include <QX11Info>
#endif
namespace Mirall {
ownCloudGui::ownCloudGui(Application *parent) :
@@ -111,6 +116,14 @@ void ownCloudGui::slotTrayClicked( QSystemTrayIcon::ActivationReason reason )
if( reason == QSystemTrayIcon::Trigger ) {
slotOpenSettingsDialog(true); // start settings if config is existing.
}
#else
// On Mac, if the settings dialog is already visible but hidden
// by other applications, this will bring it to the front.
if( reason == QSystemTrayIcon::Trigger ) {
if (!_settingsDialog.isNull() && _settingsDialog->isVisible()) {
slotShowSettings();
}
}
#endif
}
@@ -475,7 +488,7 @@ void ownCloudGui::slotShowSettings()
_settingsDialog->show();
}
_settingsDialog->setGeneralErrors( _startupFails );
Utility::raiseDialog(_settingsDialog.data());
ownCloudGui::raiseDialog(_settingsDialog.data());
}
void ownCloudGui::slotShowSyncProtocol()
@@ -503,7 +516,7 @@ void ownCloudGui::slotToggleLogBrowser()
if (_logBrowser->isVisible() ) {
_logBrowser->hide();
} else {
Utility::raiseDialog(_logBrowser);
ownCloudGui::raiseDialog(_logBrowser);
}
}
@@ -519,5 +532,42 @@ void ownCloudGui::slotHelp()
QDesktopServices::openUrl(QUrl(Theme::instance()->helpUrl()));
}
void ownCloudGui::raiseDialog( QWidget *raiseWidget )
{
if( raiseWidget && raiseWidget->parentWidget() == 0) {
// Qt has a bug which causes parent-less dialogs to pop-under.
raiseWidget->showNormal();
raiseWidget->raise();
raiseWidget->activateWindow();
}
#if defined(Q_OS_MAC)
// viel hilft viel ;-)
MacWindow::bringToFront(raiseWidget);
#endif
#if defined(Q_OS_X11)
WId wid = widget->winId();
NETWM::init();
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.message_type = NETWM::NET_ACTIVE_WINDOW;
e.xclient.display = QX11Info::display();
e.xclient.window = wid;
e.xclient.format = 32;
e.xclient.data.l[0] = 2;
e.xclient.data.l[1] = QX11Info::appTime();
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
}
} // end namespace

View File

@@ -43,6 +43,8 @@ public:
bool checkAccountExists(bool openSettings);
static void raiseDialog( QWidget *raiseWidget );
signals:
void setupProxy();

View File

@@ -124,6 +124,16 @@ QPixmap ownCloudTheme::wizardHeaderLogo() const
}
#endif
QString ownCloudTheme::appName() const
{
return QLatin1String("ownCloud");
}
QString ownCloudTheme::appNameGUI() const
{
return QLatin1String("ownCloud");
}
}

View File

@@ -33,6 +33,9 @@ public:
QIcon trayFolderIcon( const QString& ) const;
QIcon folderDisabledIcon() const;
QIcon applicationIcon() const;
QString appName() const;
QString appNameGUI() const;
QVariant customMedia(CustomMediaType type);
QString helpUrl() const;

View File

@@ -27,7 +27,7 @@
namespace Mirall {
static uint chunkSize() {
static qint64 chunkSize() {
static uint chunkSize;
if (!chunkSize) {
chunkSize = qgetenv("OWNCLOUD_CHUNK_SIZE").toUInt();
@@ -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();
}
@@ -229,7 +229,7 @@ void PropagateUploadFileQNAM::startNextChunk()
currentChunkSize = chunkSize();
}
}
device = new ChunkDevice(_file, chunkSize() * sendingChunk, currentChunkSize);
device = new ChunkDevice(_file, chunkSize() * quint64(sendingChunk), currentChunkSize);
} else {
device = _file;
}
@@ -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();

View File

@@ -46,6 +46,13 @@ SettingsDialog::SettingsDialog(ownCloudGui *gui, QWidget *parent) :
{
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
_ui->setupUi(this);
// People perceive this as a Window, so also make Ctrl+W work
QAction *closeWindowAction = new QAction(this);
closeWindowAction->setShortcut(QKeySequence("Ctrl+W"));
connect(closeWindowAction, SIGNAL(triggered()), SLOT(accept()));
addAction(closeWindowAction);
setObjectName("Settings"); // required as group for saveGeometry call
setWindowTitle(tr("%1").arg(Theme::instance()->appNameGUI()));

View File

@@ -30,8 +30,13 @@ SettingsDialogMac::SettingsDialogMac(ownCloudGui *gui, QWidget *parent)
// Emulate dialog behavior: Escape means close
QAction *closeDialogAction = new QAction(this);
closeDialogAction->setShortcut(QKeySequence(Qt::Key_Escape));
connect(closeDialogAction, SIGNAL(triggered()), SLOT(close()));
addAction(closeDialogAction);
// People perceive this as a Window, so also make Ctrl+W work
QAction *closeWindowAction = new QAction(this);
closeWindowAction->setShortcut(QKeySequence(Qt::Key_Escape));
closeWindowAction->setShortcut(QKeySequence("Ctrl+W"));
connect(closeWindowAction, SIGNAL(triggered()), SLOT(close()));
addAction(closeWindowAction);

View File

@@ -176,6 +176,11 @@ void SslButton::updateAccountInfo(Account *account)
} else {
setVisible(true);
}
if(QMenu *oldMenu = menu()) {
oldMenu->hide(); // Need to be hidden because the QToolButton would be left in invalid state if the menu is deleted while it is visible
setMenu(0);
oldMenu->deleteLater(); // setMenu do not delete the previous menu.
}
if (account->url().scheme() == QLatin1String("https")) {
setIcon(QIcon(QPixmap(":/mirall/resources/lock-https.png")));
QSslCipher cipher = account->sslConfiguration().sessionCipher();
@@ -212,7 +217,6 @@ void SslButton::updateAccountInfo(Account *account)
} else {
setIcon(QIcon(QPixmap(":/mirall/resources/lock-http.png")));
setToolTip(tr("This connection is NOT secure as it is not encrypted.\n"));
setMenu(0);
}
}

View File

@@ -164,18 +164,6 @@ QByteArray Utility::userAgentString()
.toLatin1();
}
void Utility::raiseDialog( QWidget *raiseWidget )
{
#ifndef TOKEN_AUTH_ONLY
if( raiseWidget && raiseWidget->parentWidget() == 0) {
// Qt has a bug which causes parent-less dialogs to pop-under.
raiseWidget->showNormal();
raiseWidget->raise();
raiseWidget->activateWindow();
}
#endif
}
bool Utility::hasLaunchOnStartup(const QString &appName)
{
return hasLaunchOnStartup_private(appName);

View File

@@ -36,7 +36,6 @@ namespace Utility
OWNCLOUDSYNC_EXPORT QString octetsToString( qint64 octets );
OWNCLOUDSYNC_EXPORT QString platform();
OWNCLOUDSYNC_EXPORT QByteArray userAgentString();
OWNCLOUDSYNC_EXPORT void raiseDialog(QWidget *);
OWNCLOUDSYNC_EXPORT bool hasLaunchOnStartup(const QString &appName);
OWNCLOUDSYNC_EXPORT void setLaunchOnStartup(const QString &appName, const QString& guiName, bool launch);
OWNCLOUDSYNC_EXPORT qint64 freeDiskSpace(const QString &path, bool *ok = 0);