mirror of
https://github.com/chylex/Nextcloud-Desktop.git
synced 2026-04-03 18:11:32 +02:00
Compare commits
72 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4a9e524e6 | ||
|
|
1ad23e6ab0 | ||
|
|
f1dbba9e5a | ||
|
|
8d7408bb0c | ||
|
|
18f1b3c5ff | ||
|
|
7dcbbb0046 | ||
|
|
cc8408be8f | ||
|
|
4902271b19 | ||
|
|
b881b6db4e | ||
|
|
421177bfaf | ||
|
|
395ae1d4ed | ||
|
|
c0bb4cd938 | ||
|
|
06bcb8f3c8 | ||
|
|
8711a3ea6c | ||
|
|
984be698b4 | ||
|
|
4566ca3127 | ||
|
|
cc1121ef00 | ||
|
|
6f9938a2b2 | ||
|
|
a650dce17f | ||
|
|
7ddd3a36c7 | ||
|
|
c46f1aba89 | ||
|
|
2ab19b23d7 | ||
|
|
d770f9cc1a | ||
|
|
9d3b09159e | ||
|
|
819cb74cc3 | ||
|
|
2407469104 | ||
|
|
c1faff513e | ||
|
|
e5b4438d5c | ||
|
|
7ec43e9f36 | ||
|
|
c4dabe7ed2 | ||
|
|
6b4f11f4aa | ||
|
|
1edf3dd503 | ||
|
|
1daf9bc80b | ||
|
|
b7a91a6998 | ||
|
|
69dffc8882 | ||
|
|
753aa9132e | ||
|
|
cfdfd6a860 | ||
|
|
0c9d57228d | ||
|
|
5254c9785c | ||
|
|
0f37484b8a | ||
|
|
3d0c009719 | ||
|
|
208011f6ab | ||
|
|
f84e0010ee | ||
|
|
c97f46d403 | ||
|
|
1fb52f0d8b | ||
|
|
d4de024f15 | ||
|
|
1d9d88ca85 | ||
|
|
beb9300b4e | ||
|
|
c35880d4f1 | ||
|
|
d8ebebaf12 | ||
|
|
af3fae9c28 | ||
|
|
d3b72940fd | ||
|
|
e8de3e855a | ||
|
|
71338000a4 | ||
|
|
d697969f36 | ||
|
|
51e9c5fd96 | ||
|
|
0202351a27 | ||
|
|
63cd5ef563 | ||
|
|
82c254fecf | ||
|
|
86bea9a9af | ||
|
|
88f26fb548 | ||
|
|
a9f1de84f0 | ||
|
|
e17243bc1f | ||
|
|
0e45dd7a3d | ||
|
|
65f313f1b4 | ||
|
|
da4958c716 | ||
|
|
653b8494f5 | ||
|
|
6ed6f84f6e | ||
|
|
ff0ba56bc3 | ||
|
|
e795d04f30 | ||
|
|
8d3806b080 | ||
|
|
5597ebe455 |
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -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
|
||||
|
||||
36
ChangeLog
36
ChangeLog
@@ -1,5 +1,41 @@
|
||||
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.
|
||||
* Fix local file name clash detection for MacOSX.
|
||||
* Limit maximum wait time to ten seconds in network limiting.
|
||||
* Fix data corruption while trying to resume and the server does
|
||||
not support it.
|
||||
* HTTP Credentials: Read password from legacy place if not found.
|
||||
* Shibboleth: Fix the waiting curser that would not disapear (#1915)
|
||||
* Limit memory usage to avoid mem wasting and crashes
|
||||
* Propagator: Fix crash when logging out during upload (#1957)
|
||||
* Propagator_qnam: Fix signal slot connection (#1963)
|
||||
* Use more elaborated way to detect that the server was reconfigured (#1948)
|
||||
* Setup Wizard: Reconfigure Server also if local path was changed (#1948)
|
||||
|
||||
version 1.6.1 (release 2014-06-26 )
|
||||
* Fix 'precondition failed' bug with broken upload
|
||||
* Fix openSSL problems for windows deployment
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
set( MIRALL_VERSION_MAJOR 1 )
|
||||
set( MIRALL_VERSION_MINOR 6 )
|
||||
set( MIRALL_VERSION_PATCH 1 )
|
||||
set( MIRALL_VERSION_PATCH 4 )
|
||||
set( MIRALL_SOVERSION 0 )
|
||||
|
||||
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||
|
||||
@@ -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}
|
||||
#
|
||||
|
||||
@@ -111,8 +111,8 @@ ReserveFile "${NSISDIR}\Plugins\InstallOptions.dll"
|
||||
!define MUI_HEADERIMAGE
|
||||
!define MUI_HEADERIMAGE_BITMAP ${WIN_SETUP_BITMAP_PATH}/page_header.bmp
|
||||
!define MUI_COMPONENTSPAGE_SMALLDESC
|
||||
!define MUI_FINISHPAGE_LINK "www.${APPLICATION_DOMAIN}"
|
||||
!define MUI_FINISHPAGE_LINK_LOCATION "http://www.${APPLICATION_DOMAIN}"
|
||||
!define MUI_FINISHPAGE_LINK "${APPLICATION_DOMAIN}"
|
||||
!define MUI_FINISHPAGE_LINK_LOCATION "http://${APPLICATION_DOMAIN}"
|
||||
!define MUI_FINISHPAGE_NOREBOOTSUPPORT
|
||||
!ifdef OPTION_FINISHPAGE_RELEASE_NOTES
|
||||
!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
|
||||
@@ -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"
|
||||
@@ -414,9 +415,9 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
|
||||
|
||||
;Qt deps
|
||||
File "${MING_BIN}\libpng16-16.dll"
|
||||
File "${MING_BIN}\icudata51.dll"
|
||||
File "${MING_BIN}\icui18n51.dll"
|
||||
File "${MING_BIN}\icuuc51.dll"
|
||||
File "${MING_BIN}\icudata53.dll"
|
||||
File "${MING_BIN}\icui18n53.dll"
|
||||
File "${MING_BIN}\icuuc53.dll"
|
||||
File "${MING_BIN}\libEGL.dll"
|
||||
File "${MING_BIN}\libGLESv2.dll"
|
||||
File "${MING_BIN}\libjpeg-8.dll"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 =~ /\/$/ );
|
||||
|
||||
@@ -4,7 +4,7 @@ if(SPHINX_FOUND)
|
||||
set(SPHINX_CACHE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees")
|
||||
# HTML output directory
|
||||
set(SPHINX_HTML_DIR "${CMAKE_CURRENT_BINARY_DIR}/html")
|
||||
set(SPHINX_MAN_DIR "${CMAKE_CURRENT_BINARY_DIR}/man")
|
||||
set(SPHINX_MAN_DIR "${CMAKE_CURRENT_BINARY_DIR}/man1")
|
||||
set(SPHINX_PDF_DIR "${CMAKE_CURRENT_BINARY_DIR}/latex")
|
||||
set(SPHINX_QCH_DIR "${CMAKE_CURRENT_BINARY_DIR}/qthelp")
|
||||
set(SPHINX_HTMLHELP_DIR "${CMAKE_CURRENT_BINARY_DIR}/htmlhelp")
|
||||
|
||||
Submodule doc/ocdoc updated: 2c3e584b23...c612df399e
2
src/3rdparty/qtmacgoodies
vendored
2
src/3rdparty/qtmacgoodies
vendored
Submodule src/3rdparty/qtmacgoodies updated: cf09d34dc7...fa06775714
@@ -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()
|
||||
@@ -388,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")
|
||||
|
||||
@@ -425,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()
|
||||
|
||||
@@ -101,7 +101,8 @@ HttpCredentials::HttpCredentials()
|
||||
: _user(),
|
||||
_password(),
|
||||
_ready(false),
|
||||
_fetchJobInProgress(false)
|
||||
_fetchJobInProgress(false),
|
||||
_readPwdFromDeprecatedPlace(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -230,6 +231,7 @@ void HttpCredentials::fetch(Account *account)
|
||||
job->setProperty("account", QVariant::fromValue(account));
|
||||
job->start();
|
||||
_fetchJobInProgress = true;
|
||||
_readPwdFromDeprecatedPlace = true;
|
||||
}
|
||||
}
|
||||
bool HttpCredentials::stillValid(QNetworkReply *reply)
|
||||
@@ -261,18 +263,40 @@ void HttpCredentials::slotReadJobDone(QKeychain::Job *job)
|
||||
_ready = true;
|
||||
emit fetched();
|
||||
} else {
|
||||
if( error != NoError ) {
|
||||
qDebug() << "Error while reading password" << job->errorString();
|
||||
// we come here if the password is empty or any other keychain
|
||||
// error happend.
|
||||
// In all error conditions it should
|
||||
// ask the user for the password interactively now.
|
||||
if( _readPwdFromDeprecatedPlace ) {
|
||||
// there simply was not a password. Lets restart a read job without
|
||||
// a settings object as we did it in older client releases.
|
||||
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
|
||||
|
||||
const QString kck = keychainKey(account->url().toString(), _user);
|
||||
job->setKey(kck);
|
||||
|
||||
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(QKeychain::Job*)));
|
||||
job->setProperty("account", QVariant::fromValue(account));
|
||||
job->start();
|
||||
_readPwdFromDeprecatedPlace = false; // do try that only once.
|
||||
_fetchJobInProgress = true;
|
||||
// Note: if this read job succeeds, the value from the old place is still
|
||||
// NOT persisted into the new account.
|
||||
} else {
|
||||
// interactive password dialog starts here
|
||||
bool ok;
|
||||
QString pwd = queryPassword(&ok);
|
||||
_fetchJobInProgress = false;
|
||||
if (ok) {
|
||||
_password = pwd;
|
||||
_ready = true;
|
||||
persist(account);
|
||||
} else {
|
||||
_password = QString::null;
|
||||
_ready = false;
|
||||
}
|
||||
emit fetched();
|
||||
}
|
||||
bool ok;
|
||||
QString pwd = queryPassword(&ok);
|
||||
_fetchJobInProgress = false;
|
||||
if (ok) {
|
||||
_password = pwd;
|
||||
_ready = true;
|
||||
persist(account);
|
||||
}
|
||||
emit fetched();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +366,8 @@ void HttpCredentials::slotWriteJobDone(QKeychain::Job *job)
|
||||
default:
|
||||
qDebug() << "Error while writing password" << job->errorString();
|
||||
}
|
||||
WritePasswordJob *wjob = qobject_cast<WritePasswordJob*>(job);
|
||||
wjob->deleteLater();
|
||||
}
|
||||
|
||||
void HttpCredentials::slotAuthentication(QNetworkReply* reply, QAuthenticator* authenticator)
|
||||
|
||||
@@ -63,6 +63,7 @@ private:
|
||||
QString _password;
|
||||
bool _ready;
|
||||
bool _fetchJobInProgress; //True if the keychain job is in progress or the input dialog visible
|
||||
bool _readPwdFromDeprecatedPlace;
|
||||
};
|
||||
|
||||
} // ns Mirall
|
||||
|
||||
@@ -34,6 +34,7 @@ ShibbolethWebView::ShibbolethWebView(Account* account, QWidget* parent)
|
||||
: QWebView(parent)
|
||||
, _account(account)
|
||||
, _accepted(false)
|
||||
, _cursorOverriden(false)
|
||||
{
|
||||
// no minimize
|
||||
setWindowFlags(Qt::Dialog);
|
||||
@@ -79,6 +80,10 @@ void ShibbolethWebView::onNewCookiesForUrl (const QList<QNetworkCookie>& cookieL
|
||||
|
||||
void ShibbolethWebView::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
if (_cursorOverriden) {
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
if (!_accepted) {
|
||||
Q_EMIT rejected();
|
||||
}
|
||||
@@ -87,12 +92,17 @@ void ShibbolethWebView::closeEvent(QCloseEvent *event)
|
||||
|
||||
void ShibbolethWebView::slotLoadStarted()
|
||||
{
|
||||
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||
if (!_cursorOverriden) {
|
||||
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||
_cursorOverriden = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ShibbolethWebView::slotLoadFinished(bool success)
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
if (_cursorOverriden) {
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
if (!title().isNull()) {
|
||||
setWindowTitle(tr("%1 - %2").arg(Theme::instance()->appNameGUI(), title()));
|
||||
|
||||
@@ -55,6 +55,7 @@ private:
|
||||
void setup(Account *account, ShibbolethCookieJar* jar);
|
||||
QPointer<Account> _account;
|
||||
bool _accepted;
|
||||
bool _cursorOverriden;
|
||||
};
|
||||
|
||||
} // ns Mirall
|
||||
|
||||
@@ -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"));
|
||||
@@ -405,7 +385,7 @@ void ShibbolethCredentials::showLoginWindow(Account* account)
|
||||
|
||||
QList<QNetworkCookie> ShibbolethCredentials::accountCookies(Account *account)
|
||||
{
|
||||
return account->networkAccessManager()->cookieJar()->cookiesForUrl(account->url());
|
||||
return account->networkAccessManager()->cookieJar()->cookiesForUrl(account->davUrl());
|
||||
}
|
||||
|
||||
QNetworkCookie ShibbolethCredentials::findShibCookie(Account *account, QList<QNetworkCookie> cookies)
|
||||
|
||||
@@ -63,7 +63,6 @@ public:
|
||||
|
||||
public Q_SLOTS:
|
||||
void invalidateAndFetch(Account *account);
|
||||
void slotHandleAuthentication(QNetworkReply*,QAuthenticator*);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onShibbolethCookieReceived(const QNetworkCookie&, Account*);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
89
src/mirall/accountmigrator.cpp
Normal file
89
src/mirall/accountmigrator.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
38
src/mirall/accountmigrator.h
Normal file
38
src/mirall/accountmigrator.h
Normal 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
|
||||
@@ -713,7 +713,7 @@ void AccountSettings::slotIgnoreFilesEditor()
|
||||
_ignoreEditor->setAttribute( Qt::WA_DeleteOnClose, true );
|
||||
_ignoreEditor->open();
|
||||
} else {
|
||||
Utility::raiseDialog(_ignoreEditor);
|
||||
ownCloudGui::raiseDialog(_ignoreEditor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -704,10 +705,7 @@ void Folder::slotTransmissionProgress(const Progress::Info &pi)
|
||||
void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction direction, bool *cancel)
|
||||
{
|
||||
#ifndef TOKEN_AUTH_ONLY
|
||||
QString msg = direction == SyncFileItem::Down ?
|
||||
tr("This sync would remove all the files in the local sync folder '%1'.\n"
|
||||
"If you or your administrator have reset your account on the server, choose "
|
||||
"\"Keep files\". If you want your data to be removed, choose \"Remove all files\".") :
|
||||
QString msg =
|
||||
tr("This sync would remove all the files in the sync folder '%1'.\n"
|
||||
"This might be because the folder was silently reconfigured, or that all "
|
||||
"the file were manually removed.\n"
|
||||
@@ -779,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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& );
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -43,6 +43,8 @@ public:
|
||||
|
||||
bool checkAccountExists(bool openSettings);
|
||||
|
||||
static void raiseDialog( QWidget *raiseWidget );
|
||||
|
||||
signals:
|
||||
void setupProxy();
|
||||
|
||||
|
||||
@@ -337,8 +337,15 @@ bool OwncloudPropagator::localFileNameClash( const QString& relFile )
|
||||
QFileInfo fileInfo(file);
|
||||
if (!fileInfo.exists()) {
|
||||
re = false;
|
||||
qDebug() << Q_FUNC_INFO << "No valid fileinfo";
|
||||
} else {
|
||||
re = ( ! fileInfo.canonicalFilePath().endsWith(relFile, Qt::CaseSensitive) );
|
||||
// Need to normalize to composited form because of
|
||||
// https://bugreports.qt-project.org/browse/QTBUG-39622
|
||||
const QString cName = fileInfo.canonicalFilePath().normalized(QString::NormalizationForm_C);
|
||||
// qDebug() << Q_FUNC_INFO << "comparing " << cName << " with " << file;
|
||||
bool equal = (file == cName);
|
||||
re = (!equal && ! cName.endsWith(relFile, Qt::CaseSensitive) );
|
||||
// qDebug() << Q_FUNC_INFO << "Returning for localFileNameClash: " << re;
|
||||
}
|
||||
#elif defined(Q_OS_WIN)
|
||||
const QString file( _localDir + relFile );
|
||||
|
||||
@@ -111,6 +111,15 @@ void OwncloudSetupWizard::startWizard()
|
||||
}
|
||||
|
||||
_ocWizard->setProperty("localFolder", localFolder);
|
||||
|
||||
// remember the local folder to compare later if it changed, but clean first
|
||||
QString lf = QDir::fromNativeSeparators(localFolder);
|
||||
if( !lf.endsWith(QLatin1Char('/'))) {
|
||||
lf.append(QLatin1Char('/'));
|
||||
}
|
||||
|
||||
_initLocalFolder = lf;
|
||||
|
||||
_ocWizard->setRemoteFolder(_remoteFolder);
|
||||
|
||||
_ocWizard->setStartId(WizardCommon::Page_ServerSetup);
|
||||
@@ -135,6 +144,8 @@ void OwncloudSetupWizard::slotDetermineAuthType(const QString &urlString)
|
||||
}
|
||||
Account *account = _ocWizard->account();
|
||||
account->setUrl(url);
|
||||
// Set fake credentials beforfe we check what credidential it actually is.
|
||||
account->setCredentials(CredentialsFactory::create("dummy"));
|
||||
CheckServerJob *job = new CheckServerJob(_ocWizard->account(), false, this);
|
||||
job->setIgnoreCredentialFailure(true);
|
||||
connect(job, SIGNAL(instanceFound(QUrl,QVariantMap)), SLOT(slotOwnCloudFoundAuth(QUrl,QVariantMap)));
|
||||
@@ -392,10 +403,17 @@ void OwncloudSetupWizard::slotAssistantFinished( int result )
|
||||
|
||||
Account *newAccount = _ocWizard->account();
|
||||
Account *origAccount = AccountManager::instance()->account();
|
||||
const QString localFolder = _ocWizard->localFolder();
|
||||
|
||||
QString localFolder = QDir::fromNativeSeparators(_ocWizard->localFolder());
|
||||
if( !localFolder.endsWith(QLatin1Char('/'))) {
|
||||
localFolder.append(QLatin1Char('/'));
|
||||
}
|
||||
|
||||
bool isInitialSetup = (origAccount == 0);
|
||||
bool reinitRequired = newAccount->changed(origAccount, true /* ignoreProtocol, allows http->https */);
|
||||
|
||||
// check if either the account or the local folder changed, than reinit
|
||||
bool reinitRequired = _initLocalFolder != localFolder ||
|
||||
newAccount->changed(origAccount, true /* ignoreProtocol, allows http->https */);
|
||||
bool startFromScratch = _ocWizard->field("OCSyncFromScratch").toBool();
|
||||
|
||||
// This distinguishes three possibilities:
|
||||
|
||||
@@ -94,6 +94,7 @@ private:
|
||||
|
||||
Account* _account;
|
||||
OwncloudWizard* _ocWizard;
|
||||
QString _initLocalFolder;
|
||||
QString _remoteFolder;
|
||||
|
||||
};
|
||||
|
||||
@@ -124,6 +124,16 @@ QPixmap ownCloudTheme::wizardHeaderLogo() const
|
||||
}
|
||||
#endif
|
||||
|
||||
QString ownCloudTheme::appName() const
|
||||
{
|
||||
return QLatin1String("ownCloud");
|
||||
}
|
||||
|
||||
QString ownCloudTheme::appNameGUI() const
|
||||
{
|
||||
return QLatin1String("ownCloud");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -328,8 +328,7 @@ void PropagateNeonJob::limitBandwidth(qint64 progress, qint64 bandwidth_limit)
|
||||
// -bandwidth_limit is the % of bandwidth
|
||||
int64_t wait_time = -diff * (1 + 100.0 / bandwidth_limit);
|
||||
if (wait_time > 0) {
|
||||
Mirall::Utility::usleep(wait_time);
|
||||
|
||||
Mirall::Utility::usleep(qMin(wait_time, int64_t(1000000*10)));
|
||||
}
|
||||
}
|
||||
_lastTime.start();
|
||||
@@ -397,24 +396,39 @@ void PropagateDownloadFileLegacy::install_content_reader( ne_request *req, void
|
||||
|
||||
if (etag.isEmpty()) {
|
||||
qDebug() << Q_FUNC_INFO << "No E-Tag reply by server, considering it invalid" << ne_get_response_header(req, "etag");
|
||||
that->errorString = tr("No E-Tag received from server, check Proxy/Gateway");
|
||||
ne_set_error(that->_propagator->_session, "%s", that->errorString.toUtf8().data());
|
||||
ne_add_response_body_reader( req, do_not_accept,
|
||||
do_not_download_content_reader,
|
||||
(void*) that );
|
||||
that->abortTransfer(req, tr("No E-Tag received from server, check Proxy/Gateway"));
|
||||
return;
|
||||
} else if (!that->_expectedEtagForResume.isEmpty() && that->_expectedEtagForResume != etag) {
|
||||
qDebug() << Q_FUNC_INFO << "We received a different E-Tag for resuming!"
|
||||
<< QString::fromLatin1(that->_expectedEtagForResume.data()) << "vs"
|
||||
<< QString::fromLatin1(etag.data());
|
||||
that->errorString = tr("We received a different E-Tag for resuming. Retrying next time.");
|
||||
ne_set_error(that->_propagator->_session, "%s", that->errorString.toUtf8().data());
|
||||
ne_add_response_body_reader( req, do_not_accept,
|
||||
do_not_download_content_reader,
|
||||
(void*) that );
|
||||
that->abortTransfer(req, tr("We received a different E-Tag for resuming. Retrying next time."));
|
||||
return;
|
||||
}
|
||||
|
||||
quint64 start = 0;
|
||||
QByteArray ranges = ne_get_response_header(req, "content-range");
|
||||
if (!ranges.isEmpty()) {
|
||||
QRegExp rx("bytes (\\d+)-");
|
||||
if (rx.indexIn(ranges) >= 0) {
|
||||
start = rx.cap(1).toULongLong();
|
||||
}
|
||||
}
|
||||
if (start != that->_resumeStart) {
|
||||
qDebug() << Q_FUNC_INFO << "Wrong content-range: "<< ranges << " while expecting start was" << that->_resumeStart;
|
||||
if (start == 0) {
|
||||
// device don't support range, just stry again from scratch
|
||||
that->_file->close();
|
||||
if (!that->_file->open(QIODevice::WriteOnly)) {
|
||||
that->abortTransfer(req, that->_file->errorString());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
that->abortTransfer(req, tr("Server returned wrong content-range"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char *enc = ne_get_response_header( req, "Content-Encoding" );
|
||||
qDebug("Content encoding ist <%s> with status %d", enc ? enc : "empty",
|
||||
@@ -431,6 +445,16 @@ void PropagateDownloadFileLegacy::install_content_reader( ne_request *req, void
|
||||
}
|
||||
}
|
||||
|
||||
void PropagateDownloadFileLegacy::abortTransfer(ne_request* req, const QString& error)
|
||||
{
|
||||
errorString = error;
|
||||
ne_set_error(_propagator->_session, "%s", errorString.toUtf8().data());
|
||||
ne_add_response_body_reader( req, do_not_accept,
|
||||
do_not_download_content_reader,
|
||||
this);
|
||||
}
|
||||
|
||||
|
||||
void PropagateDownloadFileLegacy::notify_status_cb(void* userdata, ne_session_status status,
|
||||
const ne_session_status_info* info)
|
||||
{
|
||||
@@ -521,6 +545,7 @@ void PropagateDownloadFileLegacy::start()
|
||||
ne_add_request_header(req.data(), "Range", rangeRequest.constData());
|
||||
ne_add_request_header(req.data(), "Accept-Ranges", "bytes");
|
||||
qDebug() << "Retry with range " << rangeRequest;
|
||||
_resumeStart = done;
|
||||
}
|
||||
|
||||
/* hook called before the content is parsed to set the correct reader,
|
||||
|
||||
@@ -53,13 +53,14 @@ class PropagateDownloadFileLegacy: public PropagateNeonJob {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PropagateDownloadFileLegacy(OwncloudPropagator* propagator,const SyncFileItem& item)
|
||||
: PropagateNeonJob(propagator, item), _file(0) {}
|
||||
: PropagateNeonJob(propagator, item), _file(0), _resumeStart(0) {}
|
||||
void start();
|
||||
private:
|
||||
QFile *_file;
|
||||
QScopedPointer<ne_decompress, ScopedPointerHelpers> _decompress;
|
||||
QString errorString;
|
||||
QByteArray _expectedEtagForResume;
|
||||
quint64 _resumeStart;
|
||||
|
||||
static int do_not_accept (void *userdata, ne_request *req, const ne_status *st)
|
||||
{
|
||||
@@ -78,6 +79,9 @@ private:
|
||||
static void install_content_reader( ne_request *req, void *userdata, const ne_status *status );
|
||||
static void notify_status_cb(void* userdata, ne_session_status status,
|
||||
const ne_session_status_info* info);
|
||||
|
||||
/** To be called from install_content_reader if we want to abort the transfer */
|
||||
void abortTransfer(ne_request *req, const QString &error);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -119,14 +119,15 @@ void PropagateUploadFileQNAM::start()
|
||||
|
||||
struct ChunkDevice : QIODevice {
|
||||
public:
|
||||
QIODevice *_file;
|
||||
QPointer<QIODevice> _file;
|
||||
qint64 _read;
|
||||
qint64 _size;
|
||||
qint64 _start;
|
||||
|
||||
ChunkDevice(QIODevice *file, qint64 start, qint64 size)
|
||||
: QIODevice(file), _file(file), _read(0), _size(size), _start(start) {
|
||||
_file->seek(start);
|
||||
_file = QPointer<QIODevice>(file);
|
||||
_file.data()->seek(start);
|
||||
}
|
||||
|
||||
virtual qint64 writeData(const char* , qint64 ) {
|
||||
@@ -135,10 +136,15 @@ public:
|
||||
}
|
||||
|
||||
virtual qint64 readData(char* data, qint64 maxlen) {
|
||||
if (_file.isNull()) {
|
||||
qDebug() << Q_FUNC_INFO << "Upload file object deleted during upload";
|
||||
close();
|
||||
return -1;
|
||||
}
|
||||
maxlen = qMin(maxlen, chunkSize() - _read);
|
||||
if (maxlen == 0)
|
||||
return 0;
|
||||
qint64 ret = _file->read(data, maxlen);
|
||||
qint64 ret = _file.data()->read(data, maxlen);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
_read += ret;
|
||||
@@ -146,7 +152,11 @@ public:
|
||||
}
|
||||
|
||||
virtual bool atEnd() const {
|
||||
return _read >= chunkSize() || _file->atEnd();
|
||||
if (_file.isNull()) {
|
||||
qDebug() << Q_FUNC_INFO << "Upload file object deleted during upload";
|
||||
return true;
|
||||
}
|
||||
return _read >= chunkSize() || _file.data()->atEnd();
|
||||
}
|
||||
|
||||
virtual qint64 size() const{
|
||||
@@ -164,8 +174,13 @@ public:
|
||||
}
|
||||
|
||||
virtual bool seek ( qint64 pos ) {
|
||||
if (_file.isNull()) {
|
||||
qDebug() << Q_FUNC_INFO << "Upload file object deleted during upload";
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
_read = pos;
|
||||
return _file->seek(pos + _start);
|
||||
return _file.data()->seek(pos + _start);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -214,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;
|
||||
}
|
||||
@@ -287,8 +302,10 @@ void PropagateUploadFileQNAM::slotPutFinished()
|
||||
return;
|
||||
}
|
||||
|
||||
if (Utility::qDateTimeToTime_t(fi.lastModified()) != _item._modtime) {
|
||||
/* Uh oh: The local file has changed during upload */
|
||||
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.
|
||||
@@ -380,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());
|
||||
@@ -387,6 +410,7 @@ void GETFileJob::start() {
|
||||
|
||||
setReply(davRequest("GET", path(), req));
|
||||
setupConnections(reply());
|
||||
reply()->setReadBufferSize(128 * 1024);
|
||||
|
||||
if( reply()->error() != QNetworkReply::NoError ) {
|
||||
qWarning() << Q_FUNC_INFO << " Network error: " << reply()->errorString();
|
||||
@@ -395,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;
|
||||
}
|
||||
|
||||
@@ -423,11 +454,39 @@ void GETFileJob::slotMetaDataChanged()
|
||||
reply()->abort();
|
||||
return;
|
||||
}
|
||||
|
||||
quint64 start = 0;
|
||||
QByteArray ranges = parseEtag(reply()->rawHeader("Content-Range"));
|
||||
if (!ranges.isEmpty()) {
|
||||
QRegExp rx("bytes (\\d+)-");
|
||||
if (rx.indexIn(ranges) >= 0) {
|
||||
start = rx.cap(1).toULongLong();
|
||||
}
|
||||
}
|
||||
if (start != _resumeStart) {
|
||||
qDebug() << Q_FUNC_INFO << "Wrong content-range: "<< ranges << " while expecting start was" << _resumeStart;
|
||||
if (start == 0) {
|
||||
// device don't support range, just stry again from scratch
|
||||
_device->close();
|
||||
if (!_device->open(QIODevice::WriteOnly)) {
|
||||
_errorString = _device->errorString();
|
||||
_errorStatus = SyncFileItem::NormalError;
|
||||
reply()->abort();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
_errorString = tr("Server returned wrong content-range");
|
||||
_errorStatus = SyncFileItem::NormalError;
|
||||
reply()->abort();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GETFileJob::slotReadyRead()
|
||||
{
|
||||
int bufferSize = qMax(1024*8ll , reply()->bytesAvailable());
|
||||
int bufferSize = qMin(1024*8ll , reply()->bytesAvailable());
|
||||
QByteArray buffer(bufferSize, Qt::Uninitialized);
|
||||
|
||||
while(reply()->bytesAvailable() > 0) {
|
||||
@@ -440,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()
|
||||
@@ -514,22 +574,18 @@ 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(),
|
||||
_propagator->_remoteFolder + _item._file,
|
||||
&_tmpFile, headers, expectedEtagForResume);
|
||||
&_tmpFile, headers, expectedEtagForResume, _startSize);
|
||||
_job->setTimeout(_propagator->httpTimeout() * 1000);
|
||||
connect(_job, SIGNAL(finishedSignal()), this, SLOT(slotGetFinished()));
|
||||
connect(_job, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(slotDownloadProgress(qint64,qint64)));
|
||||
@@ -551,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;
|
||||
}
|
||||
|
||||
@@ -99,26 +99,27 @@ private slots:
|
||||
void slotUploadProgress(qint64,qint64);
|
||||
void abort();
|
||||
void startNextChunk();
|
||||
void finalize(const Mirall::SyncFileItem&);
|
||||
void finalize(const SyncFileItem&);
|
||||
};
|
||||
|
||||
|
||||
class GETFileJob : public AbstractNetworkJob {
|
||||
Q_OBJECT
|
||||
QIODevice* _device;
|
||||
QFile* _device;
|
||||
QMap<QByteArray, QByteArray> _headers;
|
||||
QString _errorString;
|
||||
QByteArray _expectedEtagForResume;
|
||||
quint64 _resumeStart;
|
||||
SyncFileItem::Status _errorStatus;
|
||||
public:
|
||||
|
||||
// DOES NOT take owncership of the device.
|
||||
explicit GETFileJob(Account* account, const QString& path, QIODevice *device,
|
||||
explicit GETFileJob(Account* account, const QString& path, QFile *device,
|
||||
const QMap<QByteArray, QByteArray> &headers, QByteArray expectedEtagForResume,
|
||||
QObject* parent = 0)
|
||||
quint64 resumeStart, QObject* parent = 0)
|
||||
: AbstractNetworkJob(account, path, parent),
|
||||
_device(device), _headers(headers), _expectedEtagForResume(expectedEtagForResume),
|
||||
_errorStatus(SyncFileItem::NoStatus) {}
|
||||
_resumeStart(resumeStart), _errorStatus(SyncFileItem::NoStatus) {}
|
||||
|
||||
virtual void start();
|
||||
virtual bool finished() {
|
||||
@@ -132,6 +133,8 @@ public:
|
||||
|
||||
SyncFileItem::Status errorStatus() { return _errorStatus; }
|
||||
|
||||
quint64 resumeStart() const { return _resumeStart; }
|
||||
|
||||
virtual void slotTimeout();
|
||||
|
||||
|
||||
|
||||
@@ -131,6 +131,13 @@ void ProtocolWidget::slotClearBlacklist()
|
||||
void ProtocolWidget::cleanIgnoreItems(const QString& folder)
|
||||
{
|
||||
int itemCnt = _ui->_treeWidget->topLevelItemCount();
|
||||
|
||||
// Limit the number of items
|
||||
while(itemCnt > 2000) {
|
||||
delete _ui->_treeWidget->takeTopLevelItem(itemCnt - 1);
|
||||
itemCnt--;
|
||||
}
|
||||
|
||||
for( int cnt = itemCnt-1; cnt >=0 ; cnt-- ) {
|
||||
QTreeWidgetItem *item = _ui->_treeWidget->topLevelItem(cnt);
|
||||
bool isErrorItem = item->data(0, IgnoredIndicatorRole).toBool();
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,8 @@ SyncEngine::SyncEngine(CSYNC *ctx, const QString& localPath, const QString& remo
|
||||
, _remoteUrl(remoteURL)
|
||||
, _remotePath(remotePath)
|
||||
, _journal(journal)
|
||||
, _hasFiles(false)
|
||||
, _hasNoneFiles(false)
|
||||
, _hasRemoveFile(false)
|
||||
, _downloadLimit(0)
|
||||
, _uploadLimit(0)
|
||||
|
||||
@@ -330,7 +331,7 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
dir = SyncFileItem::None;
|
||||
} else {
|
||||
// No need to do anything.
|
||||
_hasFiles = true;
|
||||
_hasNoneFiles = true;
|
||||
|
||||
emit syncItemDiscovered(item);
|
||||
return re;
|
||||
@@ -343,8 +344,9 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
_renamedFolders.insert(item._file, item._renameTarget);
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_REMOVE:
|
||||
_hasRemoveFile = true;
|
||||
dir = !remote ? SyncFileItem::Down : SyncFileItem::Up;
|
||||
break;
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_CONFLICT:
|
||||
case CSYNC_INSTRUCTION_IGNORE:
|
||||
case CSYNC_INSTRUCTION_ERROR:
|
||||
@@ -356,6 +358,11 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
case CSYNC_INSTRUCTION_STAT_ERROR:
|
||||
default:
|
||||
dir = remote ? SyncFileItem::Down : SyncFileItem::Up;
|
||||
if (!remote && file->instruction == CSYNC_INSTRUCTION_SYNC) {
|
||||
// An upload of an existing file means that the file was left unchanged on the server
|
||||
// This count as a NONE for detecting if all the file on the server were changed
|
||||
_hasNoneFiles = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -364,11 +371,6 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
// if the item is on blacklist, the instruction was set to IGNORE
|
||||
checkBlacklisting( &item );
|
||||
|
||||
if (file->instruction != CSYNC_INSTRUCTION_IGNORE
|
||||
&& file->instruction != CSYNC_INSTRUCTION_REMOVE) {
|
||||
_hasFiles = true;
|
||||
}
|
||||
|
||||
if (!item._isDirectory) {
|
||||
_progressInfo._totalFileCount++;
|
||||
if (Progress::isSizeDependent(file->instruction)) {
|
||||
@@ -526,7 +528,8 @@ void SyncEngine::slotUpdateFinished(int updateResult)
|
||||
|
||||
_progressInfo = Progress::Info();
|
||||
|
||||
_hasFiles = false;
|
||||
_hasNoneFiles = false;
|
||||
_hasRemoveFile = false;
|
||||
bool walkOk = true;
|
||||
_seenFiles.clear();
|
||||
|
||||
@@ -556,8 +559,8 @@ void SyncEngine::slotUpdateFinished(int updateResult)
|
||||
emit aboutToPropagate(_syncedItems);
|
||||
emit transmissionProgress(_progressInfo);
|
||||
|
||||
if (!_hasFiles && !_syncedItems.isEmpty()) {
|
||||
qDebug() << Q_FUNC_INFO << "All the files are going to be removed, asking the user";
|
||||
if (!_hasNoneFiles && _hasRemoveFile) {
|
||||
qDebug() << Q_FUNC_INFO << "All the files are going to be changed, asking the user";
|
||||
bool cancel = false;
|
||||
emit aboutToRemoveAllFiles(_syncedItems.first()._direction, &cancel);
|
||||
if (cancel) {
|
||||
|
||||
@@ -127,7 +127,8 @@ private:
|
||||
QHash<QString, QString> _renamedFolders;
|
||||
QString adjustRenamedPath(const QString &original);
|
||||
|
||||
bool _hasFiles; // true if there is at least one file that is not ignored or removed
|
||||
bool _hasNoneFiles; // true if there is at least one file with instruction NONE
|
||||
bool _hasRemoveFile; // true if there is at leasr one file with instruction REMOVE
|
||||
|
||||
int _downloadLimit;
|
||||
int _uploadLimit;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <QDir>
|
||||
#include <QFileDialog>
|
||||
#include <QUrl>
|
||||
#include <QTimer>
|
||||
#include <QPushButton>
|
||||
#include <QMessageBox>
|
||||
|
||||
@@ -145,9 +146,12 @@ void OwncloudSetupPage::initializePage()
|
||||
if (Theme::instance()->overrideServerUrl().isEmpty()) {
|
||||
_ui.leUrl->setFocus();
|
||||
} else {
|
||||
setVisible(false);
|
||||
setCommitPage(true);
|
||||
validatePage();
|
||||
setVisible(false);
|
||||
// because the wizard will call show on us right after this call, we need to hide in the
|
||||
// next event loop iteration.
|
||||
QTimer::singleShot(0, this, SLOT(hide()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -161,7 +161,6 @@ void OwncloudWizard::slotCurrentPageChanged( int id )
|
||||
|
||||
if( id == WizardCommon::Page_ServerSetup ) {
|
||||
emit clearPendingRequests();
|
||||
_setupPage->initializePage();
|
||||
}
|
||||
|
||||
if( id == WizardCommon::Page_Result ) {
|
||||
|
||||
Reference in New Issue
Block a user