Comparar commits

..

48 Commits

Autor SHA1 Mensagem Data
Piotr M 43e071aea9 add http2 support 2017-01-12 17:49:05 +01:00
Jenkins for ownCloud 355a644020 [tx-robot] updated from transifex 2017-01-10 02:18:34 +01:00
Jenkins for ownCloud 5e6e4e7464 [tx-robot] updated from transifex 2017-01-08 02:18:35 +01:00
Markus Goetz 76fde49282 sqlite: Update bundled version to 3.16.1
For OS X and Windows.
2017-01-05 17:27:46 +01:00
Markus Goetz 4ef7d0410d First iteration ChangeLog for 2.3.0 2017-01-05 16:56:37 +01:00
octotree a1b4984d14 Symlink Support for Dolphin Plugins (#5428)
Add Symlink Support to Dolphin Overlay Plugin
2017-01-05 13:24:22 +01:00
Christian Kamm adbe5ecf55 ownsql: qFatal on prepare errors #5357 2017-01-04 15:15:06 +01:00
Jenkins for ownCloud ba32571039 [tx-robot] updated from transifex 2017-01-04 02:19:32 +01:00
Christian Kamm 084146756b Account: Fix displayName() #5413
This displayName() seemed to be based on Account::user() which used
to call _credentials->user(). But then we repurposed user() to be
davUser() and this usage wasn't updated to point back to the username
used for the credentials.
2017-01-03 13:54:59 +01:00
ckamm e1f5a49c21 Don't blacklist 507 Insufficent Storage #5346 (#5424) 2017-01-03 13:48:32 +01:00
ckamm 143320341e Build: Enable Q_ASSERT in release mode (#5425) 2017-01-03 13:42:25 +01:00
Christian Kamm e286bb1b64 Wizard: Don't accidentally pre-fill url field #5412
slotUrlEditFinished() is called when the wizard is triggered in
some situations.
2017-01-03 11:53:40 +01:00
Olivier Goffart d433f0e08e HTTPCreds: remove all cookies when logging out (#5383)
Some custom server use persistent cookies with the auth token. So we should
clear all the cookies when disconnecting.
Account::clearCookieJar is only called from the HTTPCredentials. This funciton
is not used for shibboleth.
There is probably no reasons to keep the HTTP cookie anyway.

Issue #5370
2017-01-03 11:39:10 +01:00
Christian Kamm 107149d601 Doc: Improve example #5422 2017-01-03 11:31:51 +01:00
Christian Kamm fa9b36f829 Wizard: Let the user know if url is invalid #5398 2017-01-03 11:28:56 +01:00
Christian Kamm 6775292d63 Fix compile of tests 2017-01-03 10:52:39 +01:00
Christian Kamm 6835429a28 Sql: Allow prepare fail for PRAGMA quick_check #5357
This actually happens in low-disk situations.
2017-01-03 10:43:29 +01:00
Christian Kamm 22135f9f57 Fixup broken authType on load #5408 2017-01-03 10:38:20 +01:00
Jenkins for ownCloud 0fd06a225c [tx-robot] updated from transifex 2017-01-03 02:19:30 +01:00
Christian Kamm 473dcb0947 Only create a FolderWatcher if the path exists
Also retry creating it before each sync.

See #5317
2017-01-02 08:52:26 +01:00
Christian Kamm e306f4611c Reschedule a folder regularly with some delay for some errors
Like "folder doesn't exist" - such that we will detect when the folder
becomes available and start syncing.

See #5317
2017-01-02 08:52:26 +01:00
Markus Goetz c6f4f44619 Fix up SSL client certificates #5213 #69 (#5289)
The re-enables the UI, uses Qt API for importing and
stores the certificate/key in the system keychain.
People who had set up client certs need to re-setup the account. This is ok
since it was an undocumented feature anyway.
2017-01-02 08:34:02 +01:00
Jenkins for ownCloud 0865c63745 [tx-robot] updated from transifex 2017-01-02 02:19:26 +01:00
Jenkins for ownCloud b81c3a6a67 [tx-robot] updated from transifex 2017-01-01 02:19:32 +01:00
Jenkins for ownCloud cc56e5639d [tx-robot] updated from transifex 2016-12-30 02:18:34 +01:00
Jenkins for ownCloud 3ce5b358ae [tx-robot] updated from transifex 2016-12-25 02:18:27 +01:00
Jenkins for ownCloud e968284618 [tx-robot] updated from transifex 2016-12-24 02:18:26 +01:00
Jenkins for ownCloud c7723179d8 [tx-robot] updated from transifex 2016-12-23 02:18:34 +01:00
Jenkins for ownCloud 1872f3f94a [tx-robot] updated from transifex 2016-12-22 02:18:30 +01:00
Christian Kamm 3b7887ca35 Wizard: Detach saved account from wizard
Fixes #5408 #5407.

The problem was that cleanup of the credentials page set the
credentials of the account back to dummy, thereby overriding
things like shib usernames.

This should be broken since a932eac832.
2016-12-21 15:31:12 +01:00
Piotr Mrówczyński d781e63fab Add capability to disable parallel chunked upload #5364 - technical review (#5403) 2016-12-21 15:08:45 +01:00
Kyle Fazzari d1237cdda3 Correctly handle possible missing GIT_SHA1. (#5401)
Currently, if get_git_head_revision() doesn't define GIT_SHA1 (which it
doesn't in some cases) it's possible to end up with the following error:

    CMake Error at CMakeLists.txt:69 (if):
      if given arguments:

        "STREQUAL" "GITDIR-NOTFOUND"

      Unknown arguments specified

Fix this by making sure both left and right hand arguments to STREQUAL
are always strings, even if GIT_SHA1 is undefined.

Signed-off-by: Kyle Fazzari <kyle@canonical.com>
2016-12-21 14:14:26 +01:00
Christian Kamm 030e3a5d4a Increase initial bandwidth estimates #4428 #5390
To 2 MB/s and 10 files/s.
2016-12-21 08:53:47 +01:00
Jenkins for ownCloud 4fa4a6a5ed [tx-robot] updated from transifex 2016-12-21 02:18:28 +01:00
Phil Davis 23fb07240b Fix Mac PATH command
Reported in the doc repo owncloud/documentation#1618
This version as suggested by @jturcotte
2016-12-20 20:01:38 +01:00
Christian Kamm 3912dba33a Move qDeclareMetatype from Folder to SyncEngine 2016-12-20 11:43:39 +01:00
Christian Kamm d8c479ab1e Don't wipe db if check fails while disk space is low #5357
An experimental fix for the issue, merged because it's low risk and
makes testing easier.
2016-12-20 09:33:59 +01:00
Jenkins for ownCloud bec67455c1 [tx-robot] updated from transifex 2016-12-20 02:18:27 +01:00
Jenkins for ownCloud ba6a37a601 [tx-robot] updated from transifex 2016-12-19 02:18:28 +01:00
Jenkins for ownCloud 03f5091e73 [tx-robot] updated from transifex 2016-12-18 02:18:28 +01:00
Jenkins for ownCloud 6b6ff08821 [tx-robot] updated from transifex 2016-12-17 02:18:27 +01:00
Jenkins for ownCloud 35a0ee4893 [tx-robot] updated from transifex 2016-12-16 02:18:29 +01:00
Jenkins for ownCloud 3519391119 [tx-robot] updated from transifex 2016-12-15 02:18:37 +01:00
Olivier Goffart 775a1c9ad8 FolderStatusModel: Fix insert/remove items when there are labels
Otherwise it might happen that the model is inconsistant and this can
lead to crash in the worst case.

(For example, if there was a "fetching" label, and we hide it because it
was a 404. In this case, we would not call begin/endRemoveRows, so the
view could still call the model with an index of row 0, that used to be
for the label, but now correspond to the first element of _subs. And
because _subs is empty, this could lead to crashes)
2016-12-14 14:13:47 +01:00
Olivier Goffart ac95844ebd Propagator: make sure every network job has a parent
This could make sure that the network job gets deleted if the parent job gets
deleted, and would avoid crashes like:

Crash: EXCEPTION_ACCESS_VIOLATION_READ at 0xffffffff8b008a04
  File "qiodevice.cpp", line 1617, in QIODevice::errorString
  File "propagatedownload.cpp", line 264, in OCC::GETFileJob::slotReadyRead
  File "moc_propagatedownload.cpp", line 85, in OCC::GETFileJob::qt_static_metacall
  File "qobject.cpp", line 3716, in QMetaObject::activate
  File "moc_qiodevice.cpp", line 154, in QIODevice::readyRead
  File "qnetworkreplyhttpimpl.cpp", line 1045, in QNetworkReplyHttpImplPrivate::replyDownloadData

(#5329)
2016-12-14 14:13:47 +01:00
Olivier Goffart c5b90d9507 Account::slotHandleSslErrors: add guards in case the reply gets deleted in the dialog event loop
Since slotHandleSslErrors will show a dialog with an eventloop, it could be
That the reply gets deleted. Guard against that.

(#5329)
2016-12-14 14:13:47 +01:00
Christian Kamm d631f2e070 Sync now: Disable on disconnect, rename while running #2158 2016-12-13 15:28:52 +01:00
Jonathan Kawohl 5bae2ed5ef fixed merge conflicts 2016-12-13 09:12:50 +01:00
79 arquivos alterados com 14059 adições e 10810 exclusões
+4 -1
Ver Arquivo
@@ -58,6 +58,9 @@ if( UNIX AND NOT APPLE )
endif()
####
# Enable Q_ASSERT etc. in all builds
add_definitions( -DQT_FORCE_ASSERTS )
include(GNUInstallDirs)
include(DefineInstallationPaths)
include(GenerateExportHeader)
@@ -69,7 +72,7 @@ get_git_head_revision(GIT_REFSPEC GIT_SHA1)
# if we cannot get it from git, directly try .tag (packages)
# this will work if the tar balls have been properly created
# via git-archive.
if (${GIT_SHA1} STREQUAL "GITDIR-NOTFOUND")
if ("${GIT_SHA1}" STREQUAL "GITDIR-NOTFOUND")
file(READ ${CMAKE_SOURCE_DIR}/.tag sha1_candidate)
string(REPLACE "\n" "" sha1_candidate ${sha1_candidate})
if (NOT ${sha1_candidate} STREQUAL "$Format:%H$")
+39
Ver Arquivo
@@ -1,6 +1,45 @@
ChangeLog
=========
version 2.3.0 (2017-0x-xx)
* WiP!
* WiP Switch Windows and OS X build to 5.6.2
* WiP Performance improvements for exclude detection
* Switch to new ownCloud server WebDAV endpoint
* Chunking NG: New file upload chunking algorithmn for ownCloud server 9.2
* Allow to sync a folder to multiple different servers (Filename change from .csync_journal.db to _sync_$HASH.db)
* Conflicts: Use the local mtime for the conflict file name (#5273)
* "Sync now" menu item
* SSL Client certificate support improved (Show UI, Store keys in keychain)
* Propagator: Upload more small files in parallel
* Sync Engine: Read data-fingerprint property to detect backups (#2325)
* GUI: Show link to ceate an app password/token for syncing
* Share dialog: Add 'Mail link' button
* Caja file manager plugin
* Make "backup detected" message to not trigger in wrong cases
* SyncEngine: Fix renaming of folder when file are changed (#5192)
* Fix reconnect bug if status.php intermittently returns wrong data (#5188)
* Improve sync scheduling (#5317)
* Overlay icons: Improvements in correctnes
* Tray menu: Only update on demand to fix Linux desktop integration glitches
* Progress: Better time/bandwidth estimations
* Network: Follow certain HTTP redirects (#2791)
* Network: Remove all cookies (including load balancers etc) when logging out
* Discovery thread: Low priority
* owncloudsync.log: Write during propagation
* Better error message for files with trailing spaces on Windows
* Excludes: Consider files in hidden folders excluded (#5163)
* Allow sync directory to be a symlinked directory
* Add manifest file on Windows to make the application UAC aware
* macOS: Improve monochrome tray icons
* Don't blacklist 507 Insufficent Storage #5346 (#5424)
* Shibboleth bugfixes
* Fixes with regards to low disk space
* A ton of other bugfixes
* Refactorings
* Improved documentation
* Crash fixes
version 2.2.4 (release 2016-09-27)
* Dolphin Plugin: Use the Application name for the socket path (#5172)
* SyncEngine: Fix renaming of folder when file are changed (#5195)
-5
Ver Arquivo
@@ -44,11 +44,6 @@
extern "C" {
#endif
struct csync_client_certs_s {
char *certificatePath;
char *certificatePasswd;
};
enum csync_status_codes_e {
CSYNC_STATUS_OK = 0,
-3
Ver Arquivo
@@ -103,9 +103,6 @@ struct csync_s {
} callbacks;
c_strlist_t *excludes;
// needed for SSL client certificate support
struct csync_client_certs_s *clientCerts;
struct {
char *file;
+1 -9
Ver Arquivo
@@ -68,17 +68,9 @@ To set up your build environment for development using HomeBrew_:
1. Install Xcode
2. Install Xcode command line tools::
<<<<<<< HEAD
xcode-select --install
3. Install homebrew::
=======
xcode-select --install
3. Install homebrew::
>>>>>>> ca9ec4625391ae23940b3a62aaa0afe89f3d98e8
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
4. Add the ownCloud repository using the following command::
@@ -91,7 +83,7 @@ To set up your build environment for development using HomeBrew_:
3. Add Qt from brew to the path::
export PATH=/usr/local/Cellar/qt5/5.x.y/bin/qmake
export PATH=/usr/local/Cellar/qt5/5.x.y/bin:$PATH
Where ``x.z`` is the current version of Qt 5 that brew has installed
on your machine.
+1 -1
Ver Arquivo
@@ -65,7 +65,7 @@ If no client is configured, or if you choose to use a different user to synchron
you can specify the user
password setting with the usual URL pattern. For example::
$ owncloudcmd / https://carla:secret@server/owncloud/remote.php/webdav/
$ owncloudcmd /home/user/my_sync_folder https://carla:secret@server/owncloud/remote.php/webdav/
To synchronize the ownCloud directory ``Music`` to the local directory
``media/music``, through a proxy listening on port ``8080``, and on a gateway
+57
Ver Arquivo
@@ -571,6 +571,60 @@ X-GNOME-Autostart-Delay=3
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
Comment[oc]=@APPLICATION_NAME@ sincronizacion del client
GenericName[oc]=Dorsièr de Sincronizacion
@@ -706,7 +760,10 @@ Comment[th_TH]=@APPLICATION_NAME@ ไคลเอนต์ประสานข
GenericName[th_TH]=ประสานข้อมูลโฟลเดอร์
Name[th_TH]= @APPLICATION_NAME@ ไคลเอนต์ประสานข้อมูลเดสก์ท็อป
Icon[th_TH]=@APPLICATION_EXECUTABLE@
Comment[es_MX]=Cliente de escritorio para sincronziación de @APPLICATION_NAME@
GenericName[es_MX]=Sincronización de Carpetas
Name[es_MX]=Cliente de escritorio para sincronziación de @APPLICATION_NAME@
Icon[es_MX]=@APPLICATION_EXECUTABLE@
Comment[nb_NO]=@APPLICATION_NAME@ skrivebordssynkroniseringsklient
GenericName[nb_NO]=Mappesynkronisering
Name[nb_NO]=@APPLICATION_NAME@ skrivebordssynkroniseringsklient
@@ -24,6 +24,7 @@
#include <KIOCore/kfileitem.h>
#include <KIOCore/KFileItemListProperties>
#include <QtWidgets/QAction>
#include <QtCore/QDir>
#include <QtCore/QTimer>
#include "ownclouddolphinpluginhelper.h"
@@ -43,7 +44,8 @@ public:
auto url = urls.first();
if (!url.isLocalFile())
return {};
auto localFile = url.toLocalFile();
QDir localPath(url.toLocalFile());
auto localFile = localPath.canonicalPath();
const auto paths = helper->paths();
if (!std::any_of(paths.begin(), paths.end(), [&](const QString &s) {
@@ -21,6 +21,7 @@
#include <KPluginFactory>
#include <QtNetwork/QLocalSocket>
#include <KIOCore/kfileitem.h>
#include <QDir>
#include <QTimer>
#include "ownclouddolphinpluginhelper.h"
@@ -46,7 +47,8 @@ public:
return QStringList();
if (!url.isLocalFile())
return QStringList();
const QByteArray localFile = url.toLocalFile().toUtf8();
QDir localPath(url.toLocalFile());
const QByteArray localFile = localPath.canonicalPath().toUtf8();
helper->sendCommand(QByteArray("RETRIEVE_FILE_STATUS:" + localFile + "\n"));
-110
Ver Arquivo
@@ -1,110 +0,0 @@
/*
* Copyright (C) by Pierre MOREAU <p.moreau@agim.idshost.fr>
*
* 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.
*/
/**
* \file p12topem.cpp
* \brief Static library to convert p12 to pem
* \author Pierre MOREAU <p.moreau@agim.idshost.fr>
* \version 1.0.0
* \date 09 January 2014
*/
#include "p12topem.h"
/**
* \fn string x509ToString (BIO)
* \brief Return string from BIO SSL
* \param BIO o PEM_write_BIO_...
* \return string PEM
*/
string x509ToString(BIO *o) {
BUF_MEM *bptr;
BIO_get_mem_ptr(o, &bptr);
int len = bptr->length;
void* data = calloc(len+10, sizeof(char));
BIO_read(o, data, len);
string ret = std::string(static_cast<char*>(data));
free(data);
return ret;
}
/**
* \fn resultP12ToPem p12ToPem (string, string)
* \brief Convert P12 to PEM
* \param string p12File Path to P12 file
* \param string p12Passwd Password to open P12 file
* \return result (bool ReturnCode, Int ErrorCode, String Comment, String PrivateKey, String Certificate)
*/
resultP12ToPem p12ToPem(string p12File, string p12Passwd) {
FILE *fp;
PKCS12 *p12 = NULL;
EVP_PKEY *pkey = NULL;
X509 *cert = NULL;
STACK_OF(X509) *ca = NULL;
BIO *o = BIO_new(BIO_s_mem());
string privateKey = "";
string certificate = "";
resultP12ToPem ret;
ret.ReturnCode = false;
ret.ErrorCode = 0;
ret.Comment = "";
ret.PrivateKey = "";
ret.Certificate = "";
SSLeay_add_all_algorithms();
ERR_load_crypto_strings();
if(!(fp = fopen(p12File.c_str(), "rb"))) {
ret.ErrorCode = 1;
ret.Comment = strerror(errno);
return ret;
}
p12 = d2i_PKCS12_fp(fp, &p12);
fclose (fp);
if (!p12) {
ret.ErrorCode = 2;
ret.Comment = "Unable to open PKCS#12 file";
return ret;
}
if (!PKCS12_parse(p12, p12Passwd.c_str(), &pkey, &cert, &ca)) {
ret.ErrorCode = 3;
ret.Comment = "Unable to parse PKCS#12 file (wrong password ?)";
return ret;
}
PKCS12_free(p12);
if (!(pkey && cert)) {
ret.ErrorCode = 4;
ret.Comment = "Certificate and/or key file doesn't exists";
} else {
PEM_write_bio_PrivateKey(o, pkey, 0, 0, 0, NULL, 0);
privateKey = x509ToString(o);
PEM_write_bio_X509(o, cert);
certificate = x509ToString(o);
BIO_free(o);
ret.ReturnCode = true;
ret.ErrorCode = 0;
ret.Comment = "All is fine";
ret.PrivateKey = privateKey;
ret.Certificate = certificate;
}
return ret;
}
-62
Ver Arquivo
@@ -1,62 +0,0 @@
/*
* Copyright (C) by Pierre MOREAU <p.moreau@agim.idshost.fr>
*
* 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 P12TOPEM_H
#define P12TOPEM_H
/**
* \file p12topem.h
* \brief Static library to convert p12 to pem
* \author Pierre MOREAU <p.moreau@agim.idshost.fr>
* \version 1.0.0
* \date 09 January 2014
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/pkcs12.h>
using namespace std;
/**
* \struct resultP12ToPem p12topem.h
*/
struct resultP12ToPem {
bool ReturnCode;
int ErrorCode;
string Comment;
string PrivateKey;
string Certificate;
};
/**
* \brief Return string from BIO SSL
* \param BIO o PEM_write_BIO_...
* \return string PEM
*/
string x509ToString(BIO *o);
/**
* \brief Convert P12 to PEM
* \param string p12File Path to P12 file
* \param string p12Passwd Password to open P12 file
* \return result (bool ReturnCode, Int ErrorCode, String Comment, String PrivateKey, String Certificate)
*/
resultP12ToPem p12ToPem(string p12File, string p12Passwd);
#endif /* P12TOPEM_H */
+6941 -4159
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+125 -29
Ver Arquivo
@@ -108,7 +108,8 @@ extern "C" {
** be held constant and Z will be incremented or else Y will be incremented
** and Z will be reset to zero.
**
** Since version 3.6.18, SQLite source code has been stored in the
** Since [version 3.6.18] ([dateof:3.6.18]),
** SQLite source code has been stored in the
** <a href="http://www.fossil-scm.org/">Fossil configuration management
** system</a>. ^The SQLITE_SOURCE_ID macro evaluates to
** a string which identifies a particular check-in of SQLite
@@ -120,13 +121,13 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.14.2"
#define SQLITE_VERSION_NUMBER 3014002
#define SQLITE_SOURCE_ID "2016-09-12 18:50:49 29dbef4b8585f753861a36d6dd102ca634197bd6"
#define SQLITE_VERSION "3.16.1"
#define SQLITE_VERSION_NUMBER 3016001
#define SQLITE_SOURCE_ID "2017-01-03 18:27:03 979f04392853b8053817a3eea2fc679947b437fd"
/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version, sqlite3_sourceid
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
@@ -452,7 +453,8 @@ SQLITE_API int sqlite3_exec(
** [result codes]. However, experience has shown that many of
** these result codes are too coarse-grained. They do not provide as
** much information about problems as programmers might like. In an effort to
** address this, newer versions of SQLite (version 3.3.8 and later) include
** address this, newer versions of SQLite (version 3.3.8 [dateof:3.3.8]
** and later) include
** support for additional result codes that provide more detailed information
** about errors. These [extended result codes] are enabled or disabled
** on a per database connection basis using the
@@ -976,6 +978,12 @@ struct sqlite3_io_methods {
** on whether or not the file has been renamed, moved, or deleted since it
** was first opened.
**
** <li>[[SQLITE_FCNTL_WIN32_GET_HANDLE]]
** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the
** underlying native file handle associated with a file handle. This file
** control interprets its argument as a pointer to a native file handle and
** writes the resulting value there.
**
** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
** opcode causes the xFileControl method to swap the file handle with the one
@@ -1026,6 +1034,8 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_RBU 26
#define SQLITE_FCNTL_VFS_POINTER 27
#define SQLITE_FCNTL_JOURNAL_POINTER 28
#define SQLITE_FCNTL_WIN32_GET_HANDLE 29
#define SQLITE_FCNTL_PDB 30
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -1969,13 +1979,36 @@ struct sqlite3_mem_methods {
** be a NULL pointer, in which case the new setting is not reported back.
** </dd>
**
** <dt>SQLITE_DBCONFIG_MAINDBNAME</dt>
** <dd> ^This option is used to change the name of the "main" database
** schema. ^The sole argument is a pointer to a constant UTF8 string
** which will become the new schema name in place of "main". ^SQLite
** does not make a copy of the new main schema name string, so the application
** must ensure that the argument passed into this DBCONFIG option is unchanged
** until after the database connection closes.
** </dd>
**
** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt>
** <dd> Usually, when a database in wal mode is closed or detached from a
** database handle, SQLite checks if this will mean that there are now no
** connections at all to the database. If so, it performs a checkpoint
** operation before closing the connection. This option may be used to
** override this behaviour. The first parameter passed to this operation
** is an integer - non-zero to disable checkpoints-on-close, or zero (the
** default) to enable them. The second parameter is a pointer to an integer
** into which is written 0 or 1 to indicate whether checkpoints-on-close
** have been disabled - 0 if they are not disabled, 1 if they are.
** </dd>
**
** </dl>
*/
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */
/*
@@ -3577,6 +3610,10 @@ SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
** sqlite3_stmt_readonly() to return true since, while those statements
** change the configuration of a database connection, they do not make
** changes to the content of the database files on disk.
** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since
** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
** sqlite3_stmt_readonly() returns false for those commands.
*/
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
@@ -4041,7 +4078,8 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** other than [SQLITE_ROW] before any subsequent invocation of
** sqlite3_step(). Failure to reset the prepared statement using
** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
** sqlite3_step(). But after version 3.6.23.1, sqlite3_step() began
** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1],
** sqlite3_step() began
** calling [sqlite3_reset()] automatically in this circumstance rather
** than returning [SQLITE_MISUSE]. This is not considered a compatibility
** break because any application that ever receives an SQLITE_MISUSE error
@@ -5404,7 +5442,8 @@ SQLITE_API void *sqlite3_update_hook(
** and disabled if the argument is false.)^
**
** ^Cache sharing is enabled and disabled for an entire process.
** This is a change as of SQLite version 3.5.0. In prior versions of SQLite,
** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]).
** In prior versions of SQLite,
** sharing was enabled or disabled for each thread separately.
**
** ^(The cache sharing mode set by this interface effects all subsequent
@@ -5498,7 +5537,8 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
** from the heap.
** </ul>)^
**
** Beginning with SQLite version 3.7.3, the soft heap limit is enforced
** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]),
** the soft heap limit is enforced
** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT]
** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT],
** the soft heap limit is enforced on every memory allocation. Without
@@ -5892,13 +5932,15 @@ struct sqlite3_module {
** the xUpdate method are automatically rolled back by SQLite.
**
** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
** structure for SQLite version 3.8.2. If a virtual table extension is
** structure for SQLite [version 3.8.2] ([dateof:3.8.2]).
** If a virtual table extension is
** used with an SQLite version earlier than 3.8.2, the results of attempting
** to read or write the estimatedRows field are undefined (but are likely
** to included crashing the application). The estimatedRows field should
** therefore only be used if [sqlite3_libversion_number()] returns a
** value greater than or equal to 3008002. Similarly, the idxFlags field
** was added for version 3.9.0. It may therefore only be used if
** was added for [version 3.9.0] ([dateof:3.9.0]).
** It may therefore only be used if
** sqlite3_libversion_number() returns a value greater than or equal to
** 3009000.
*/
@@ -6596,7 +6638,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */
#define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */
#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */
#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */
#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_randomness() */
#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
@@ -6700,6 +6742,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19
#define SQLITE_TESTCTRL_NEVER_CORRUPT 20
#define SQLITE_TESTCTRL_VDBE_COVERAGE 21
#define SQLITE_TESTCTRL_BYTEORDER 22
@@ -8186,7 +8229,8 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
**
** See also: [sqlite3_update_hook()]
*/
SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_preupdate_hook(
#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
SQLITE_API void *sqlite3_preupdate_hook(
sqlite3 *db,
void(*xPreUpdate)(
void *pCtx, /* Copy of third arg to preupdate_hook() */
@@ -8199,10 +8243,11 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_preupdate_hook(
),
void*
);
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_count(sqlite3 *);
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_depth(sqlite3 *);
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
SQLITE_API int sqlite3_preupdate_count(sqlite3 *);
SQLITE_API int sqlite3_preupdate_depth(sqlite3 *);
SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
#endif
/*
** CAPI3REF: Low-level system error code
@@ -8218,7 +8263,7 @@ SQLITE_API int sqlite3_system_errno(sqlite3*);
/*
** CAPI3REF: Database Snapshot
** KEYWORDS: {snapshot}
** KEYWORDS: {snapshot} {sqlite3_snapshot}
** EXPERIMENTAL
**
** An instance of the snapshot object records the state of a [WAL mode]
@@ -8242,7 +8287,9 @@ SQLITE_API int sqlite3_system_errno(sqlite3*);
** to an historical snapshot (if possible). The destructor for
** sqlite3_snapshot objects is [sqlite3_snapshot_free()].
*/
typedef struct sqlite3_snapshot sqlite3_snapshot;
typedef struct sqlite3_snapshot {
unsigned char hidden[48];
} sqlite3_snapshot;
/*
** CAPI3REF: Record A Database Snapshot
@@ -8253,9 +8300,32 @@ typedef struct sqlite3_snapshot sqlite3_snapshot;
** schema S in database connection D. ^On success, the
** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly
** created [sqlite3_snapshot] object into *P and returns SQLITE_OK.
** ^If schema S of [database connection] D is not a [WAL mode] database
** that is in a read transaction, then [sqlite3_snapshot_get(D,S,P)]
** leaves the *P value unchanged and returns an appropriate [error code].
** If there is not already a read-transaction open on schema S when
** this function is called, one is opened automatically.
**
** The following must be true for this function to succeed. If any of
** the following statements are false when sqlite3_snapshot_get() is
** called, SQLITE_ERROR is returned. The final value of *P is undefined
** in this case.
**
** <ul>
** <li> The database handle must be in [autocommit mode].
**
** <li> Schema S of [database connection] D must be a [WAL mode] database.
**
** <li> There must not be a write transaction open on schema S of database
** connection D.
**
** <li> One or more transactions must have been written to the current wal
** file since it was created on disk (by any connection). This means
** that a snapshot cannot be taken on a wal mode database with no wal
** file immediately after it is first opened. At least one transaction
** must be written to it first.
** </ul>
**
** This function may also return SQLITE_NOMEM. If it is called with the
** database handle in autocommit mode but fails for some other reason,
** whether or not a read transaction is opened on schema S is undefined.
**
** The [sqlite3_snapshot] object returned from a successful call to
** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()]
@@ -8348,6 +8418,28 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
sqlite3_snapshot *p2
);
/*
** CAPI3REF: Recover snapshots from a wal file
** EXPERIMENTAL
**
** If all connections disconnect from a database file but do not perform
** a checkpoint, the existing wal file is opened along with the database
** file the next time the database is opened. At this point it is only
** possible to successfully call sqlite3_snapshot_open() to open the most
** recent snapshot of the database (the one at the head of the wal file),
** even though the wal file may contain other valid snapshots for which
** clients have sqlite3_snapshot handles.
**
** This function attempts to scan the wal file associated with database zDb
** of database handle db and make all valid snapshots available to
** sqlite3_snapshot_open(). It is an error if there is already a read
** transaction open on the database, or if the database is not a wal mode
** database.
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
@@ -8639,7 +8731,7 @@ int sqlite3session_attach(
** CAPI3REF: Set a table filter on a Session Object.
**
** The second argument (xFilter) is the "filter callback". For changes to rows
** in tables that are not attached to the Session oject, the filter is called
** in tables that are not attached to the Session object, the filter is called
** to determine whether changes to the table's rows should be tracked or not.
** If xFilter returns 0, changes is not tracked. Note that once a table is
** attached, xFilter will not be called again.
@@ -8905,7 +8997,7 @@ int sqlite3session_isempty(sqlite3_session *pSession);
** [sqlite3changeset_invert()] functions, all changes within the changeset
** that apply to a single table are grouped together. This means that when
** an application iterates through a changeset using an iterator created by
** this function, all changes that relate to a single table are visted
** this function, all changes that relate to a single table are visited
** consecutively. There is no chance that the iterator will visit a change
** the applies to table X, then one for table Y, and then later on visit
** another change for table X.
@@ -8992,7 +9084,7 @@ int sqlite3changeset_op(
** 0x01 if the corresponding column is part of the tables primary key, or
** 0x00 if it is not.
**
** If argumet pnCol is not NULL, then *pnCol is set to the number of columns
** If argument pnCol is not NULL, then *pnCol is set to the number of columns
** in the table.
**
** If this function is called when the iterator does not point to a valid
@@ -9209,12 +9301,12 @@ int sqlite3changeset_concat(
/*
** Changegroup handle.
** CAPI3REF: Changegroup Handle
*/
typedef struct sqlite3_changegroup sqlite3_changegroup;
/*
** CAPI3REF: Combine two or more changesets into a single changeset.
** CAPI3REF: Create A New Changegroup Object
**
** An sqlite3_changegroup object is used to combine two or more changesets
** (or patchsets) into a single changeset (or patchset). A single changegroup
@@ -9251,6 +9343,8 @@ typedef struct sqlite3_changegroup sqlite3_changegroup;
int sqlite3changegroup_new(sqlite3_changegroup **pp);
/*
** CAPI3REF: Add A Changeset To A Changegroup
**
** Add all changes within the changeset (or patchset) in buffer pData (size
** nData bytes) to the changegroup.
**
@@ -9265,7 +9359,7 @@ int sqlite3changegroup_new(sqlite3_changegroup **pp);
** apply to the same row as a change already present in the changegroup if
** the two rows have the same primary key.
**
** Changes to rows that that do not already appear in the changegroup are
** Changes to rows that do not already appear in the changegroup are
** simply copied into it. Or, if both the new changeset and the changegroup
** contain changes that apply to a single row, the final contents of the
** changegroup depends on the type of each change, as follows:
@@ -9326,6 +9420,8 @@ int sqlite3changegroup_new(sqlite3_changegroup **pp);
int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
/*
** CAPI3REF: Obtain A Composite Changeset From A Changegroup
**
** Obtain a buffer containing a changeset (or patchset) representing the
** current contents of the changegroup. If the inputs to the changegroup
** were themselves changesets, the output is a changeset. Or, if the
@@ -9354,7 +9450,7 @@ int sqlite3changegroup_output(
);
/*
** Delete a changegroup object.
** CAPI3REF: Delete A Changegroup Object
*/
void sqlite3changegroup_delete(sqlite3_changegroup*);
+2 -2
Ver Arquivo
@@ -121,7 +121,7 @@ QString queryPassword(const QString &user)
class HttpCredentialsText : public HttpCredentials {
public:
HttpCredentialsText(const QString& user, const QString& password)
: HttpCredentials(user, password, "", ""), // FIXME: not working with client certs yet (qknight)
: HttpCredentials(user, password), // FIXME: not working with client certs yet (qknight)
_sslTrusted(false)
{}
@@ -507,7 +507,7 @@ restart_sync:
app.exec();
if (engine.isAnotherSyncNeeded()) {
if (engine.isAnotherSyncNeeded() != NoFollowUpSync) {
if (restartCount < options.restartTimes) {
restartCount++;
qDebug() << "Restarting Sync, because another sync is needed" << restartCount;
-1
Ver Arquivo
@@ -151,7 +151,6 @@ set(3rdparty_SRC
../3rdparty/qtsingleapplication/qtlocalpeer.cpp
../3rdparty/qtsingleapplication/qtsingleapplication.cpp
../3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp
../3rdparty/certificates/p12topem.cpp
)
if (APPLE)
+12 -1
Ver Arquivo
@@ -214,6 +214,17 @@ AccountPtr AccountManager::loadAccountHelper(QSettings& settings)
auto acc = createAccount();
QString authType = settings.value(QLatin1String(authTypeC)).toString();
// There was an account-type saving bug when 'skip folder config' was used
// See #5408. This attempts to fix up the "dummy" authType
if (authType == QLatin1String("dummy")) {
if (settings.contains(QLatin1String("http_user"))) {
authType = "http";
} else if (settings.contains(QLatin1String("shibboleth_shib_user"))) {
authType = "shibboleth";
}
}
QString overrideUrl = Theme::instance()->overrideServerUrl();
QString forceAuth = Theme::instance()->forceConfigAuthType();
if(!forceAuth.isEmpty() && !overrideUrl.isEmpty() ) {
@@ -237,7 +248,7 @@ AccountPtr AccountManager::loadAccountHelper(QSettings& settings)
acc->setCredentials(CredentialsFactory::create(authType));
// now the cert, it is in the general group
// now the server cert, it is in the general group
settings.beginGroup(QLatin1String("General"));
acc->setApprovedCerts(QSslCertificate::fromData(settings.value(caCertsKeyC).toByteArray()));
settings.endGroup();
+6
Ver Arquivo
@@ -214,8 +214,10 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
}
tv->setCurrentIndex(index);
QString alias = _model->data( index, FolderStatusDelegate::FolderAliasRole ).toString();
bool folderPaused = _model->data( index, FolderStatusDelegate::FolderSyncPaused).toBool();
bool folderConnected = _model->data( index, FolderStatusDelegate::FolderAccountConnected ).toBool();
auto folderMan = FolderMan::instance();
QMenu *menu = new QMenu(tv);
menu->setAttribute(Qt::WA_DeleteOnClose);
@@ -231,6 +233,10 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
if (!folderPaused) {
ac = menu->addAction(tr("Force sync now"));
if (folderMan->currentSyncFolder() == folderMan->folder(alias)) {
ac->setText(tr("Restart sync"));
}
ac->setEnabled(folderConnected);
connect(ac, SIGNAL(triggered(bool)), this, SLOT(slotForceSyncCurrentFolder()));
}
+2 -2
Ver Arquivo
@@ -10,7 +10,7 @@
<x>0</x>
<y>0</y>
<width>462</width>
<height>186</height>
<height>188</height>
</rect>
</property>
<property name="windowTitle">
@@ -32,7 +32,7 @@
<item row="0" column="0">
<widget class="QLabel" name="labelCertificateFile">
<property name="text">
<string>Certificate :</string>
<string>Certificate &amp; Key (pkcs12) :</string>
</property>
</widget>
</item>
+1 -1
Ver Arquivo
@@ -27,7 +27,7 @@ class HttpCredentialsGui : public HttpCredentials {
Q_OBJECT
public:
explicit HttpCredentialsGui() : HttpCredentials() {}
HttpCredentialsGui(const QString& user, const QString& password, const QString& certificatePath, const QString& certificatePasswd) : HttpCredentials(user, password, certificatePath, certificatePasswd) {}
HttpCredentialsGui(const QString& user, const QString& password, const QSslCertificate& certificate, const QSslKey& key) : HttpCredentials(user, password, certificate, key) {}
void askFromUser() Q_DECL_OVERRIDE;
Q_INVOKABLE void askFromUserAsync();
+3 -6
Ver Arquivo
@@ -65,9 +65,6 @@ Folder::Folder(const FolderDefinition& definition,
, _fileLog(new SyncRunFileLog)
, _saveBackwardsCompatible(false)
{
qRegisterMetaType<SyncFileItemVector>("SyncFileItemVector");
qRegisterMetaType<SyncFileItem::Direction>("SyncFileItem::Direction");
qsrand(QTime::currentTime().msec());
_timeSinceLastSyncStart.start();
_timeSinceLastSyncDone.start();
@@ -826,7 +823,7 @@ void Folder::slotSyncFinished(bool success)
_fileLog->finish();
bubbleUpSyncResult();
bool anotherSyncNeeded = _engine->isAnotherSyncNeeded();
auto anotherSyncNeeded = _engine->isAnotherSyncNeeded();
if (_csyncError) {
_syncResult.setStatus(SyncResult::Error);
@@ -877,7 +874,7 @@ void Folder::slotSyncFinished(bool success)
_timeSinceLastSyncDone.restart();
// Increment the follow-up sync counter if necessary.
if (anotherSyncNeeded) {
if (anotherSyncNeeded == ImmediateFollowUp) {
_consecutiveFollowUpSyncs++;
qDebug() << "another sync was requested by the finished sync, this has"
<< "happened" << _consecutiveFollowUpSyncs << "times";
@@ -886,7 +883,7 @@ void Folder::slotSyncFinished(bool success)
}
// Maybe force a follow-up sync to take place, but only a couple of times.
if (anotherSyncNeeded && _consecutiveFollowUpSyncs <= 3)
if (anotherSyncNeeded == ImmediateFollowUp && _consecutiveFollowUpSyncs <= 3)
{
// Sometimes another sync is requested because a local file is still
// changing, so wait at least a small amount of time before syncing
+17 -10
Ver Arquivo
@@ -148,6 +148,7 @@ int FolderMan::unloadAndDeleteAllFolders()
void FolderMan::registerFolderMonitor( Folder *folder )
{
if( !folder ) return;
if( !QDir(folder->path()).exists() ) return;
if( !_folderWatchers.contains(folder->alias() ) ) {
FolderWatcher *fw = new FolderWatcher(folder->path(), folder);
@@ -730,6 +731,10 @@ void FolderMan::slotStartScheduledFolderSync()
// Start syncing this folder!
if( folder ) {
// Safe to call several times, and necessary to try again if
// the folder path didn't exist previously.
registerFolderMonitor(folder);
_currentSyncFolder = folder;
folder->startSync( QStringList() );
}
@@ -833,18 +838,20 @@ void FolderMan::slotScheduleFolderByTime()
continue;
}
// Retry a couple of times after failure
bool syncAgainAfterFail = f->consecutiveFailingSyncs() > 0 && f->consecutiveFailingSyncs() < 3;
qint64 syncAgainAfterFailDelay = 10 * 1000; // 10s for the first retry-after-fail
// Retry a couple of times after failure; or regularly if requested
bool syncAgain =
(f->consecutiveFailingSyncs() > 0 && f->consecutiveFailingSyncs() < 3)
|| f->syncEngine().isAnotherSyncNeeded() == DelayedFollowUp;
qint64 syncAgainDelay = 10 * 1000; // 10s for the first retry-after-fail
if (f->consecutiveFailingSyncs() > 1)
syncAgainAfterFailDelay = 60 * 1000; // 60s for each further attempt
if (syncAgainAfterFail
&& msecsSinceSync > syncAgainAfterFailDelay) {
syncAgainDelay = 60 * 1000; // 60s for each further attempt
if (syncAgain
&& msecsSinceSync > syncAgainDelay) {
qDebug() << "** scheduling folder" << f->alias()
<< "because the last"
<< f->consecutiveFailingSyncs() << "syncs failed, last status:"
<< f->syncResult().statusString()
<< "time since last sync:" << msecsSinceSync;
<< ", the last" << f->consecutiveFailingSyncs() << "syncs failed"
<< ", anotherSyncNeeded" << f->syncEngine().isAnotherSyncNeeded()
<< ", last status:" << f->syncResult().statusString()
<< ", time since last sync:" << msecsSinceSync;
scheduleFolder(f);
continue;
+6 -9
Ver Arquivo
@@ -527,10 +527,8 @@ void FolderStatusModel::fetchMore(const QModelIndex& parent)
if (!info || info->_fetched || info->_fetching)
return;
info->_hasError = false;
info->resetSubs(this, parent);
info->_fetching = true;
info->_fetchingLabel = false;
QString path = info->_folder->remotePath();
if (info->_path != QLatin1String("/")) {
if (!path.endsWith(QLatin1Char('/'))) {
@@ -698,17 +696,16 @@ void FolderStatusModel::slotLscolFinishedWithError(QNetworkReply* r)
qDebug() << r->errorString();
parentInfo->_lastErrorString = r->errorString();
parentInfo->resetSubs(this, idx);
if (r->error() == QNetworkReply::ContentNotFoundError) {
parentInfo->_fetched = true;
} else {
if (!parentInfo->hasLabel()) {
beginInsertRows(idx, 0, 0);
endInsertRows();
}
Q_ASSERT(!parentInfo->hasLabel());
beginInsertRows(idx, 0, 0);
parentInfo->_hasError = true;
endInsertRows();
}
parentInfo->_fetching = false;
parentInfo->_fetchingLabel = false;
}
}
+13 -1
Ver Arquivo
@@ -207,10 +207,15 @@ void OwncloudSetupWizard::slotNoOwnCloudFoundAuth(QNetworkReply *reply)
QString contentType = reply->header(QNetworkRequest::ContentTypeHeader).toString();
// Do this early because reply might be deleted in message box event loop
QString msg = tr("Failed to connect to %1 at %2:<br/>%3")
QString msg;
if (!_ocWizard->account()->url().isValid()) {
msg = tr("Invalid URL");
} else {
msg = tr("Failed to connect to %1 at %2:<br/>%3")
.arg(Theme::instance()->appNameGUI(),
reply->url().toString(),
reply->errorString());
}
bool isDowngradeAdvised = checkDowngradeAdvised(reply);
// If a client cert is needed, nginx sends:
@@ -553,6 +558,13 @@ void OwncloudSetupWizard::slotSkipFolderConfiguration()
AccountState *OwncloudSetupWizard::applyAccountChanges()
{
AccountPtr newAccount = _ocWizard->account();
// Detach the account that is going to be saved from the
// wizard to ensure it doesn't accidentally get modified
// later (such as from running cleanup such as
// AbstractCredentialsWizardPage::cleanupPage())
_ocWizard->setAccount(AccountManager::createAccount());
auto manager = AccountManager::instance();
auto newState = manager->addAccount(newAccount);
@@ -29,8 +29,11 @@ OwncloudConnectionMethodDialog::OwncloudConnectionMethodDialog(QWidget *parent)
connect(ui->btnClientSideTLS, SIGNAL(clicked(bool)), this, SLOT(returnClientSideTLS()));
connect(ui->btnBack, SIGNAL(clicked(bool)), this, SLOT(returnBack()));
// DM: TLS Client Cert GUI support disabled for now
#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0)
// We support only from Qt 5.4.x because of https://doc.qt.io/qt-5/qsslcertificate.html#importPkcs12
ui->btnClientSideTLS->hide();
#endif
}
void OwncloudConnectionMethodDialog::setUrl(const QUrl &url)
+1 -1
Ver Arquivo
@@ -192,7 +192,7 @@ void OwncloudHttpCredsPage::setErrorString(const QString& err)
AbstractCredentials* OwncloudHttpCredsPage::getCredentials() const
{
return new HttpCredentialsGui(_ui.leUsername->text(), _ui.lePassword->text(), _ocWizard->ownCloudCertificatePath, _ocWizard->ownCloudCertificatePasswd);
return new HttpCredentialsGui(_ui.leUsername->text(), _ui.lePassword->text(), _ocWizard->_clientSslCertificate, _ocWizard->_clientSslKey);
}
+31 -31
Ver Arquivo
@@ -21,13 +21,13 @@
#include <QMessageBox>
#include <QSsl>
#include <QSslCertificate>
#include <QNetworkAccessManager>
#include "QProgressIndicator.h"
#include "wizard/owncloudwizardcommon.h"
#include "wizard/owncloudsetuppage.h"
#include "wizard/owncloudconnectionmethoddialog.h"
#include "../3rdparty/certificates/p12topem.h"
#include "theme.h"
#include "account.h"
@@ -71,7 +71,6 @@ OwncloudSetupPage::OwncloudSetupPage(QWidget *parent)
connect(_ui.leUrl, SIGNAL(editingFinished()), SLOT(slotUrlEditFinished()));
addCertDial = new AddCertificateDialog(this);
connect(_ocWizard,SIGNAL(needCertificate()),this,SLOT(slotAskSSLClientCertificate()));
}
void OwncloudSetupPage::setServerUrl( const QString& newUrl )
@@ -139,7 +138,7 @@ void OwncloudSetupPage::slotUrlChanged(const QString& url)
void OwncloudSetupPage::slotUrlEditFinished()
{
QString url = _ui.leUrl->fullText();
if (QUrl(url).isRelative()) {
if (QUrl(url).isRelative() && !url.isEmpty()) {
// no scheme defined, set one
url.prepend("https://");
}
@@ -269,7 +268,10 @@ void OwncloudSetupPage::setErrorString( const QString& err, bool retryHTTPonly )
}
break;
case OwncloudConnectionMethodDialog::Client_Side_TLS:
slotAskSSLClientCertificate();
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
addCertDial->show();
connect(addCertDial, SIGNAL(accepted()),this,SLOT(slotCertificateAccepted()));
#endif
break;
case OwncloudConnectionMethodDialog::Closed:
case OwncloudConnectionMethodDialog::Back:
@@ -302,12 +304,6 @@ void OwncloudSetupPage::stopSpinner()
_progressIndi->stopAnimation();
}
void OwncloudSetupPage::slotAskSSLClientCertificate()
{
addCertDial->show();
connect(addCertDial, SIGNAL(accepted()),this,SLOT(slotCertificateAccepted()));
}
QString subjectInfoHelper(const QSslCertificate& cert, const QByteArray &qa)
{
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
@@ -320,36 +316,40 @@ QString subjectInfoHelper(const QSslCertificate& cert, const QByteArray &qa)
//called during the validation of the client certificate.
void OwncloudSetupPage::slotCertificateAccepted()
{
QSslCertificate sslCertificate;
resultP12ToPem certif = p12ToPem(addCertDial->getCertificatePath().toStdString() , addCertDial->getCertificatePasswd().toStdString());
if(certif.ReturnCode){
QString s = QString::fromStdString(certif.Certificate);
QByteArray ba = s.toLocal8Bit();
QList<QSslCertificate> sslCertificateList = QSslCertificate::fromData(ba, QSsl::Pem);
sslCertificate = sslCertificateList.takeAt(0);
_ocWizard->ownCloudCertificate = ba;
_ocWizard->ownCloudPrivateKey = certif.PrivateKey.c_str();
_ocWizard->ownCloudCertificatePath = addCertDial->getCertificatePath();
_ocWizard->ownCloudCertificatePasswd = addCertDial->getCertificatePasswd();
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
QList<QSslCertificate> clientCaCertificates;
QFile certFile(addCertDial->getCertificatePath());
certFile.open(QFile::ReadOnly);
if(QSslCertificate::importPkcs12(&certFile,
&_ocWizard->_clientSslKey, &_ocWizard->_clientSslCertificate,
&clientCaCertificates,
addCertDial->getCertificatePasswd().toLocal8Bit())){
AccountPtr acc = _ocWizard->account();
acc->setCertificate(_ocWizard->ownCloudCertificate, _ocWizard->ownCloudPrivateKey);
addCertDial->reinit();
// to re-create the session ticket because we added a key/cert
acc->setSslConfiguration(QSslConfiguration());
QSslConfiguration sslConfiguration = acc->getOrCreateSslConfig();
// We're stuffing the certificate into the configuration form here. Later the
// cert will come via the HttpCredentials
sslConfiguration.setLocalCertificate(_ocWizard->_clientSslCertificate);
sslConfiguration.setPrivateKey(_ocWizard->_clientSslKey);
acc->setSslConfiguration(sslConfiguration);
// Make sure TCP connections get re-established
acc->networkAccessManager()->clearAccessCache();
addCertDial->reinit(); // FIXME: Why not just have this only created on use?
validatePage();
} else {
QString message;
message = certif.Comment.c_str();
addCertDial->showErrorMessage(message);
addCertDial->showErrorMessage("Could not load certificate");
addCertDial->show();
}
#endif
}
OwncloudSetupPage::~OwncloudSetupPage()
{
delete addCertDial;
}
} // namespace OCC
-1
Ver Arquivo
@@ -59,7 +59,6 @@ public slots:
void setErrorString( const QString&, bool retryHTTPonly );
void startSpinner();
void stopSpinner();
void slotAskSSLClientCertificate();
void slotCertificateAccepted();
protected slots:
-7
Ver Arquivo
@@ -224,11 +224,4 @@ AbstractCredentials* OwncloudWizard::getCredentials() const
return 0;
}
// outputs the signal needed to authenticate a certificate
void OwncloudWizard::raiseCertificatePopup()
{
emit needCertificate();
}
} // end namespace
+6 -5
Ver Arquivo
@@ -17,6 +17,8 @@
#define MIRALL_OWNCLOUD_WIZARD_H
#include <QWizard>
#include <QSslKey>
#include <QSslCertificate>
#include "wizard/owncloudwizardcommon.h"
#include "accountfwd.h"
@@ -63,11 +65,10 @@ public:
void displayError( const QString&, bool retryHTTPonly);
AbstractCredentials* getCredentials() const;
void raiseCertificatePopup();
QByteArray ownCloudCertificate;
QString ownCloudPrivateKey;
QString ownCloudCertificatePath;
QString ownCloudCertificatePasswd;
// FIXME: Can those be local variables?
// Set from the OwncloudSetupPage, later used from OwncloudHttpCredsPage
QSslKey _clientSslKey;
QSslCertificate _clientSslCertificate;
public slots:
void setAuthType(WizardCommon::AuthType type);
-1
Ver Arquivo
@@ -70,7 +70,6 @@ set(libsync_SRCS
creds/abstractcredentials.cpp
creds/credentialscommon.cpp
../3rdparty/qjson/json.cpp
../3rdparty/certificates/p12topem.cpp
)
if(TOKEN_AUTH_ONLY)
+15 -33
Ver Arquivo
@@ -18,7 +18,6 @@
#include "configfile.h"
#include "accessmanager.h"
#include "creds/abstractcredentials.h"
#include "../3rdparty/certificates/p12topem.h"
#include "capabilities.h"
#include "theme.h"
@@ -93,7 +92,7 @@ void Account::setDavUser(const QString &newDavUser)
QString Account::displayName() const
{
QString dn = QString("%1@%2").arg(davUser(), _url.host());
QString dn = QString("%1@%2").arg(_credentials->user(), _url.host());
int port = url().port();
if (port > 0 && port != 80 && port != 443) {
dn.append(QLatin1Char(':'));
@@ -149,10 +148,14 @@ QUrl Account::davUrl() const
return Utility::concatUrlPath(url(), davPath());
}
/**
* clear all cookies. (Session cookies or not)
*/
void Account::clearCookieJar()
{
Q_ASSERT(qobject_cast<CookieJar*>(_am->cookieJar()));
static_cast<CookieJar*>(_am->cookieJar())->clearSessionCookies();
static_cast<CookieJar*>(_am->cookieJar())->setAllCookies(QList<QNetworkCookie>());
emit wantsAccountSaved(this);
}
/*! This shares our official cookie jar (containing all the tasty
@@ -201,6 +204,7 @@ QNetworkReply *Account::headRequest(const QUrl &url)
QNetworkRequest request(url);
#if QT_VERSION > QT_VERSION_CHECK(4, 8, 4)
request.setSslConfiguration(this->getOrCreateSslConfig());
request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true);
#endif
return _am->head(request);
}
@@ -215,6 +219,7 @@ QNetworkReply *Account::getRequest(const QUrl &url)
QNetworkRequest request(url);
#if QT_VERSION > QT_VERSION_CHECK(4, 8, 4)
request.setSslConfiguration(this->getOrCreateSslConfig());
request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true);
#endif
return _am->get(request);
}
@@ -224,6 +229,7 @@ QNetworkReply *Account::deleteRequest( const QUrl &url)
QNetworkRequest request(url);
#if QT_VERSION > QT_VERSION_CHECK(4, 8, 4)
request.setSslConfiguration(this->getOrCreateSslConfig());
request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true);
#endif
return _am->deleteResource(request);
}
@@ -238,16 +244,11 @@ QNetworkReply *Account::davRequest(const QByteArray &verb, const QUrl &url, QNet
req.setUrl(url);
#if QT_VERSION > QT_VERSION_CHECK(4, 8, 4)
req.setSslConfiguration(this->getOrCreateSslConfig());
req.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true);
#endif
return _am->sendCustomRequest(req, verb, data);
}
void Account::setCertificate(const QByteArray certficate, const QString privateKey)
{
_pemCertificate=certficate;
_pemPrivateKey=privateKey;
}
void Account::setSslConfiguration(const QSslConfiguration &config)
{
_sslConfiguration = config;
@@ -264,31 +265,7 @@ QSslConfiguration Account::getOrCreateSslConfig()
// if setting the client certificate fails, you will probably get an error similar to this:
// "An internal error number 1060 happened. SSL handshake failed, client certificate was requested: SSL error: sslv3 alert handshake failure"
QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();
QSslCertificate sslClientCertificate;
ConfigFile cfgFile;
if(!cfgFile.certificatePath().isEmpty() && !cfgFile.certificatePasswd().isEmpty()) {
resultP12ToPem certif = p12ToPem(cfgFile.certificatePath().toStdString(), cfgFile.certificatePasswd().toStdString());
QString s = QString::fromStdString(certif.Certificate);
QByteArray ba = s.toLocal8Bit();
this->setCertificate(ba, QString::fromStdString(certif.PrivateKey));
}
if((!_pemCertificate.isEmpty())&&(!_pemPrivateKey.isEmpty())) {
// Read certificates
QList<QSslCertificate> sslCertificateList = QSslCertificate::fromData(_pemCertificate, QSsl::Pem);
if(sslCertificateList.length() != 0) {
sslClientCertificate = sslCertificateList.takeAt(0);
}
// Read key from file
QSslKey privateKey(_pemPrivateKey.toLocal8Bit(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey , "");
// SSL configuration
sslConfig.setCaCertificates(QSslSocket::systemCaCertificates());
sslConfig.setLocalCertificate(sslClientCertificate);
sslConfig.setPrivateKey(privateKey);
qDebug() << "Added SSL client certificate to the query";
}
#if QT_VERSION > QT_VERSION_CHECK(5, 2, 0)
// Try hard to re-use session for different requests
sslConfig.setSslOption(QSsl::SslOptionDisableSessionTickets, false);
@@ -379,8 +356,11 @@ void Account::slotHandleSslErrors(QNetworkReply *reply , QList<QSslError> errors
// Keep a ref here on our stackframe to make sure that it doesn't get deleted before
// handleErrors returns.
QSharedPointer<QNetworkAccessManager> qnamLock = _am;
QPointer<QObject> guard = reply;
if (_sslErrorHandler->handleErrors(errors, reply->sslConfiguration(), &approvedCerts, sharedFromThis())) {
if (!guard) return;
QSslSocket::addDefaultCaCertificates(approvedCerts);
addApprovedCerts(approvedCerts);
emit wantsAccountSaved(this);
@@ -392,6 +372,8 @@ void Account::slotHandleSslErrors(QNetworkReply *reply , QList<QSslError> errors
// certificate changes.
reply->ignoreSslErrors(errors);
} else {
if (!guard) return;
// Mark all involved certificates as rejected, so we don't ask the user again.
foreach (const QSslError &error, errors) {
if (!_rejectedCertificates.contains(error.certificate())) {
+1 -2
Ver Arquivo
@@ -224,8 +224,7 @@ private:
QList<QSslCertificate> _rejectedCertificates;
static QString _configFileName;
QByteArray _pemCertificate;
QString _pemPrivateKey;
QString _davPath; // defaults to value from theme, might be overwritten in brandings
friend class AccountManager;
};
+4
Ver Arquivo
@@ -116,5 +116,9 @@ bool Capabilities::chunkingNg() const
return _capabilities["dav"].toMap()["chunking"].toByteArray() >= "1.0";
}
bool Capabilities::chunkingParallelUploadDisabled() const
{
return _capabilities["dav"].toMap()["chunkingParallelUploadDisabled"].toBool();
}
}
+3
Ver Arquivo
@@ -42,6 +42,9 @@ public:
bool shareResharing() const;
bool chunkingNg() const;
/// disable parallel upload in chunking
bool chunkingParallelUploadDisabled() const;
/// returns true if the capabilities report notifications
bool notificationsAvailable() const;
+6 -1
Ver Arquivo
@@ -144,7 +144,12 @@ void ConnectionValidator::slotStatusFound(const QUrl&url, const QVariantMap &inf
// status.php could not be loaded (network or server issue!).
void ConnectionValidator::slotNoStatusFound(QNetworkReply *reply)
{
qDebug() << Q_FUNC_INFO << reply->error() << reply->errorString();
qDebug() << Q_FUNC_INFO << reply->error() << reply->errorString() << reply->peek(1024);
if (reply && !_account->credentials()->ready()) {
// This could be needed for SSL client certificates
// We need to load them from keychain and try
reportResult( CredentialsMissingOrWrong );
} else
if( reply && ! _account->credentials()->stillValid(reply)) {
_errors.append(tr("Authentication error: Either username or password are wrong."));
} else {
+129 -47
Ver Arquivo
@@ -17,6 +17,7 @@
#include <QDebug>
#include <QNetworkReply>
#include <QSettings>
#include <QSslKey>
#include <keychain.h>
@@ -36,8 +37,8 @@ namespace OCC
namespace
{
const char userC[] = "user";
const char certifPathC[] = "certificatePath";
const char certifPasswdC[] = "certificatePasswd";
const char clientCertificatePEMC[] = "_clientCertificatePEM";
const char clientKeyPEMC[] = "_clientKeyPEM";
const char authenticationFailedC[] = "owncloud-authentication-failed";
} // ns
@@ -50,24 +51,47 @@ protected:
QByteArray credHash = QByteArray(_cred->user().toUtf8()+":"+_cred->password().toUtf8()).toBase64();
QNetworkRequest req(request);
req.setRawHeader(QByteArray("Authorization"), QByteArray("Basic ") + credHash);
//qDebug() << "Request for " << req.url() << "with authorization" << QByteArray::fromBase64(credHash);
//qDebug() << "Request for " << req.url() << "with authorization"
// << QByteArray::fromBase64(credHash)
// << _cred->_clientSslKey << _cred->_clientSslCertificate
// << _cred->_clientSslKey.isNull() << _cred->_clientSslCertificate.isNull();
if (!_cred->_clientSslKey.isNull() && !_cred->_clientSslCertificate.isNull()) {
// SSL configuration
QSslConfiguration sslConfiguration = req.sslConfiguration();
sslConfiguration.setLocalCertificate(_cred->_clientSslCertificate);
sslConfiguration.setPrivateKey(_cred->_clientSslKey);
req.setSslConfiguration(sslConfiguration);
}
return AccessManager::createRequest(op, req, outgoingData);
}
private:
const HttpCredentials *_cred;
};
static void addSettingsToJob(Account *account, QKeychain::Job *job)
{
Q_UNUSED(account);
auto settings = Utility::settingsWithGroup(Theme::instance()->appName());
settings->setParent(job); // make the job parent to make setting deleted properly
job->setSettings(settings.release());
}
HttpCredentials::HttpCredentials()
: _ready(false)
{
}
HttpCredentials::HttpCredentials(const QString& user, const QString& password, const QString& certificatePath, const QString& certificatePasswd)
// From wizard
HttpCredentials::HttpCredentials(const QString& user, const QString& password, const QSslCertificate& certificate, const QSslKey& key)
: _user(user),
_password(password),
_ready(true),
_certificatePath(certificatePath),
_certificatePasswd(certificatePasswd)
_clientSslKey(key),
_clientSslCertificate(certificate)
{
}
@@ -86,16 +110,6 @@ QString HttpCredentials::password() const
return _password;
}
QString HttpCredentials::certificatePath() const
{
return _certificatePath;
}
QString HttpCredentials::certificatePasswd() const
{
return _certificatePasswd;
}
void HttpCredentials::setAccount(Account* account)
{
AbstractCredentials::setAccount(account);
@@ -129,35 +143,83 @@ void HttpCredentials::fetchFromKeychain()
{
// User must be fetched from config file
fetchUser();
_certificatePath = _account->credentialSetting(QLatin1String(certifPathC)).toString();
_certificatePasswd = _account->credentialSetting(QLatin1String(certifPasswdC)).toString();
auto settings = Utility::settingsWithGroup(Theme::instance()->appName());
const QString kck = keychainKey(_account->url().toString(), _user );
QString key = QString::fromLatin1( "%1/data" ).arg( kck );
if( settings && settings->contains(key) ) {
// Clean the password from the config file if it is in there.
// we do not want a security problem.
settings->remove(key);
key = QString::fromLatin1( "%1/type" ).arg( kck );
settings->remove(key);
settings->sync();
}
if (_ready) {
Q_EMIT fetched();
} else {
// Read client cert from keychain
const QString kck = keychainKey(_account->url().toString(), _user + clientCertificatePEMC);
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
settings->setParent(job); // make the job parent to make setting deleted properly
job->setSettings(settings.release());
addSettingsToJob(_account, job);
job->setInsecureFallback(false);
job->setKey(kck);
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(QKeychain::Job*)));
qDebug() << "-------- ----->" << _clientSslCertificate << _clientSslKey;
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadClientCertPEMJobDone(QKeychain::Job*)));
job->start();
}
}
void HttpCredentials::slotReadClientCertPEMJobDone(QKeychain::Job* incoming)
{
// Store PEM in memory
ReadPasswordJob *readJob = static_cast<ReadPasswordJob*>(incoming);
if (readJob->error() == NoError && readJob->binaryData().length() > 0) {
QList<QSslCertificate> sslCertificateList = QSslCertificate::fromData(readJob->binaryData(), QSsl::Pem);
if(sslCertificateList.length() >= 1) {
_clientSslCertificate = sslCertificateList.at(0);
}
}
// Load key too
const QString kck = keychainKey(_account->url().toString(), _user + clientKeyPEMC);
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
addSettingsToJob(_account, job);
job->setInsecureFallback(false);
job->setKey(kck);
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadClientKeyPEMJobDone(QKeychain::Job*)));
job->start();
}
void HttpCredentials::slotReadClientKeyPEMJobDone(QKeychain::Job* incoming)
{
// Store key in memory
ReadPasswordJob *readJob = static_cast<ReadPasswordJob*>(incoming);
if (readJob->error() == NoError && readJob->binaryData().length() > 0) {
QByteArray clientKeyPEM = readJob->binaryData();
// FIXME Unfortunately Qt has a bug and we can't just use QSsl::Opaque to let it
// load whatever we have. So we try until it works.
_clientSslKey = QSslKey(clientKeyPEM, QSsl::Rsa);
if (_clientSslKey.isNull()) {
_clientSslKey = QSslKey(clientKeyPEM, QSsl::Dsa);
}
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
// ec keys are Qt 5.5
if (_clientSslKey.isNull()) {
_clientSslKey = QSslKey(clientKeyPEM, QSsl::Ec);
}
#endif
if (_clientSslKey.isNull()) {
qDebug() << "Warning: Could not load SSL key into Qt!";
}
}
// Now fetch the actual server password
const QString kck = keychainKey(_account->url().toString(), _user );
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
addSettingsToJob(_account, job);
job->setInsecureFallback(false);
job->setKey(kck);
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(QKeychain::Job*)));
job->start();
}
bool HttpCredentials::stillValid(QNetworkReply *reply)
{
return ((reply->error() != QNetworkReply::AuthenticationRequiredError)
@@ -166,10 +228,10 @@ bool HttpCredentials::stillValid(QNetworkReply *reply)
|| !reply->property(authenticationFailedC).toBool()));
}
void HttpCredentials::slotReadJobDone(QKeychain::Job *job)
void HttpCredentials::slotReadJobDone(QKeychain::Job *incomingJob)
{
ReadPasswordJob *readJob = static_cast<ReadPasswordJob*>(job);
_password = readJob->textData();
QKeychain::ReadPasswordJob *job = static_cast<ReadPasswordJob*>(incomingJob);
_password = job->textData();
if( _user.isEmpty()) {
qDebug() << "Strange: User is empty!";
@@ -178,7 +240,6 @@ void HttpCredentials::slotReadJobDone(QKeychain::Job *job)
QKeychain::Error error = job->error();
if( !_password.isEmpty() && error == NoError ) {
// All cool, the keychain did not come back with error.
// Still, the password can be empty which indicates a problem and
// the password dialog has to be opened.
@@ -214,9 +275,7 @@ void HttpCredentials::invalidateToken()
}
DeletePasswordJob *job = new DeletePasswordJob(Theme::instance()->appName());
auto settings = Utility::settingsWithGroup(Theme::instance()->appName());
settings->setParent(job); // make the job parent to make setting deleted properly
job->setSettings(settings.release());
addSettingsToJob(_account, job);
job->setInsecureFallback(true);
job->setKey(kck);
job->start();
@@ -261,14 +320,37 @@ void HttpCredentials::persist()
// We never connected or fetched the user, there is nothing to save.
return;
}
_account->setCredentialSetting(QLatin1String(userC), _user);
_account->setCredentialSetting(QLatin1String(certifPathC), _certificatePath);
_account->setCredentialSetting(QLatin1String(certifPasswdC), _certificatePasswd);
WritePasswordJob *job = new WritePasswordJob(Theme::instance()->appName());
auto settings = Utility::settingsWithGroup(Theme::instance()->appName());
settings->setParent(job); // make the job parent to make setting deleted properly
job->setSettings(settings.release());
_account->setCredentialSetting(QLatin1String(userC), _user);
// write cert
WritePasswordJob *job = new WritePasswordJob(Theme::instance()->appName());
addSettingsToJob(_account, job);
job->setInsecureFallback(false);
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotWriteClientCertPEMJobDone(QKeychain::Job*)));
job->setKey(keychainKey(_account->url().toString(), _user + clientCertificatePEMC));
job->setBinaryData(_clientSslCertificate.toPem());
job->start();
}
void HttpCredentials::slotWriteClientCertPEMJobDone(Job *incomingJob)
{
Q_UNUSED(incomingJob);
// write ssl key
WritePasswordJob* job = new WritePasswordJob(Theme::instance()->appName());
addSettingsToJob(_account, job);
job->setInsecureFallback(false);
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotWriteClientKeyPEMJobDone(QKeychain::Job*)));
job->setKey(keychainKey(_account->url().toString(), _user + clientKeyPEMC));
job->setBinaryData(_clientSslKey.toPem());
job->start();
}
void HttpCredentials::slotWriteClientKeyPEMJobDone(Job *incomingJob)
{
Q_UNUSED(incomingJob);
WritePasswordJob* job = new WritePasswordJob(Theme::instance()->appName());
addSettingsToJob(_account, job);
job->setInsecureFallback(false);
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotWriteJobDone(QKeychain::Job*)));
job->setKey(keychainKey(_account->url().toString(), _user));
+15 -9
Ver Arquivo
@@ -17,7 +17,8 @@
#define MIRALL_CREDS_HTTP_CREDENTIALS_H
#include <QMap>
#include <QSslCertificate>
#include <QSslKey>
#include "creds/abstractcredentials.h"
class QNetworkReply;
@@ -25,6 +26,8 @@ class QAuthenticator;
namespace QKeychain {
class Job;
class WritePasswordJob;
class ReadPasswordJob;
}
namespace OCC
@@ -33,10 +36,10 @@ namespace OCC
class OWNCLOUDSYNC_EXPORT HttpCredentials : public AbstractCredentials
{
Q_OBJECT
friend class HttpCredentialsAccessManager;
public:
explicit HttpCredentials();
HttpCredentials(const QString& user, const QString& password, const QString& certificatePath, const QString& certificatePasswd);
HttpCredentials(const QString& user, const QString& password, const QSslCertificate& certificate = QSslCertificate(), const QSslKey& key = QSslKey());
QString authType() const Q_DECL_OVERRIDE;
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
@@ -50,15 +53,19 @@ public:
void forgetSensitiveData() Q_DECL_OVERRIDE;
QString fetchUser();
virtual bool sslIsTrusted() { return false; }
QString certificatePath() const;
QString certificatePasswd() const;
// To fetch the user name as early as possible
void setAccount(Account* account) Q_DECL_OVERRIDE;
private Q_SLOTS:
void slotAuthentication(QNetworkReply*, QAuthenticator*);
void slotReadClientCertPEMJobDone(QKeychain::Job*);
void slotReadClientKeyPEMJobDone(QKeychain::Job*);
void slotReadJobDone(QKeychain::Job*);
void slotWriteClientCertPEMJobDone(QKeychain::Job*);
void slotWriteClientKeyPEMJobDone(QKeychain::Job*);
void slotWriteJobDone(QKeychain::Job*);
void clearQNAMCache();
@@ -66,12 +73,11 @@ protected:
QString _user;
QString _password;
QString _previousPassword;
QString _fetchErrorString;
bool _ready;
private:
QString _certificatePath;
QString _certificatePasswd;
QSslKey _clientSslKey;
QSslCertificate _clientSslCertificate;
};
} // namespace OCC
+1 -1
Ver Arquivo
@@ -472,7 +472,7 @@ bool CheckServerJob::finished()
QVariantMap status = QtJson::parse(QString::fromUtf8(body), success).toMap();
// empty or invalid response
if (!success || status.isEmpty()) {
qDebug() << "status.php from server is not valid JSON!";
qDebug() << "status.php from server is not valid JSON!" << body << reply()->request().url();
}
qDebug() << "status.php returns: " << status << " " << reply()->error() << " Reply: " << reply();
+17 -3
Ver Arquivo
@@ -70,7 +70,9 @@ bool SqlDatabase::openHelper( const QString& filename, int sqliteFlags )
bool SqlDatabase::checkDb()
{
SqlQuery quick_check("PRAGMA quick_check;", *this);
// quick_check can fail with a disk IO error when diskspace is low
SqlQuery quick_check(*this);
quick_check.prepare("PRAGMA quick_check;", /*allow_failure=*/true);
if( !quick_check.exec() ) {
qDebug() << "Error running quick_check on database";
return false;
@@ -97,6 +99,14 @@ bool SqlDatabase::openOrCreateReadWrite( const QString& filename )
}
if( !checkDb() ) {
// When disk space is low, checking the db may fail even though it's fine.
qint64 freeSpace = Utility::freeDiskSpace(filename);
if (freeSpace < 1000000) {
qDebug() << "Consistency check failed, disk space is low, aborting" << freeSpace;
close();
return false;
}
qDebug() << "Consistency check failed, removing broken db" << filename;
close();
QFile::remove(filename);
@@ -191,7 +201,7 @@ SqlQuery::SqlQuery(const QString& sql, SqlDatabase& db)
prepare(sql);
}
int SqlQuery::prepare( const QString& sql)
int SqlQuery::prepare( const QString& sql, bool allow_failure )
{
QString s(sql);
_sql = s.trimmed();
@@ -213,7 +223,11 @@ int SqlQuery::prepare( const QString& sql)
if( _errId != SQLITE_OK ) {
_error = QString::fromUtf8(sqlite3_errmsg(_db));
qWarning() << "Sqlite prepare statement error:" << _error << "in" <<_sql;
Q_ASSERT(!"SQLITE Prepare error");
if (!allow_failure) {
qFatal("SQLITE Prepare error: %s in %s",
_error.toLocal8Bit().data(),
sql.toLocal8Bit().data());
}
}
}
return _errId;
+1 -1
Ver Arquivo
@@ -80,7 +80,7 @@ public:
bool isSelect();
bool isPragma();
bool exec();
int prepare( const QString& sql );
int prepare( const QString& sql, bool allow_failure = false );
bool next();
void bindValue(int pos, const QVariant& value);
QString lastQuery() const;
+6 -2
Ver Arquivo
@@ -145,8 +145,12 @@ void ProgressInfo::reset()
_sizeProgress = Progress();
_fileProgress = Progress();
_totalSizeOfCompletedJobs = 0;
_maxBytesPerSecond = 100000.0;
_maxFilesPerSecond = 2.0;
// Historically, these starting estimates were way lower, but that lead
// to gross overestimation of ETA when a good estimate wasn't available.
_maxBytesPerSecond = 2000000.0; // 2 MB/s
_maxFilesPerSecond = 10.0;
_updateEstimatesTimer.stop();
_lastCompletedItem = SyncFileItem();
}
+2 -2
Ver Arquivo
@@ -401,7 +401,7 @@ void PropagateDownloadFile::start()
// Normal job, download from oC instance
_job = new GETFileJob(_propagator->account(),
_propagator->_remoteFolder + _item->_file,
&_tmpFile, headers, expectedEtagForResume, _resumeStart);
&_tmpFile, headers, expectedEtagForResume, _resumeStart, this);
} else {
// We were provided a direct URL, use that one
qDebug() << Q_FUNC_INFO << "directDownloadUrl given for " << _item->_file << _item->_directDownloadUrl;
@@ -413,7 +413,7 @@ void PropagateDownloadFile::start()
QUrl url = QUrl::fromUserInput(_item->_directDownloadUrl);
_job = new GETFileJob(_propagator->account(),
url,
&_tmpFile, headers, expectedEtagForResume, _resumeStart);
&_tmpFile, headers, expectedEtagForResume, _resumeStart, this);
}
_job->setBandwidthManager(&_propagator->_bandwidthManager);
connect(_job, SIGNAL(finishedSignal()), this, SLOT(slotGetFinished()));
+1 -1
Ver Arquivo
@@ -315,7 +315,7 @@ void PropagateUploadFileNG::startNextChunk()
QUrl url = chunkUrl(_currentChunk);
// job takes ownership of device via a QScopedPointer. Job deletes itself when finishing
PUTFileJob* job = new PUTFileJob(_propagator->account(), url, device, headers, _currentChunk);
PUTFileJob* job = new PUTFileJob(_propagator->account(), url, device, headers, _currentChunk, this);
_jobs.append(job);
connect(job, SIGNAL(finishedSignal()), this, SLOT(slotPutFinished()));
connect(job, SIGNAL(uploadProgress(qint64,qint64)),
+16 -9
Ver Arquivo
@@ -123,7 +123,7 @@ void PropagateUploadFileV1::startNextChunk()
}
// job takes ownership of device via a QScopedPointer. Job deletes itself when finishing
PUTFileJob* job = new PUTFileJob(_propagator->account(), _propagator->_remoteFolder + path, device, headers, _currentChunk);
PUTFileJob* job = new PUTFileJob(_propagator->account(), _propagator->_remoteFolder + path, device, headers, _currentChunk, this);
_jobs.append(job);
connect(job, SIGNAL(finishedSignal()), this, SLOT(slotPutFinished()));
connect(job, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(slotUploadProgress(qint64,qint64)));
@@ -134,18 +134,25 @@ void PropagateUploadFileV1::startNextChunk()
_currentChunk++;
bool parallelChunkUpload = true;
QByteArray env = qgetenv("OWNCLOUD_PARALLEL_CHUNK");
if (!env.isEmpty()) {
parallelChunkUpload = env != "false" && env != "0";
if (_propagator->account()->capabilities().chunkingParallelUploadDisabled()) {
// Server may also disable parallel chunked upload for any higher version
parallelChunkUpload = false;
} else {
int versionNum = _propagator->account()->serverVersionInt();
if (versionNum < 0x080003) {
// Disable parallel chunk upload severs older than 8.0.3 to avoid too many
// internal sever errors (#2743, #2938)
parallelChunkUpload = false;
QByteArray env = qgetenv("OWNCLOUD_PARALLEL_CHUNK");
if (!env.isEmpty()) {
parallelChunkUpload = env != "false" && env != "0";
} else {
int versionNum = _propagator->account()->serverVersionInt();
if (versionNum < 0x080003) {
// Disable parallel chunk upload severs older than 8.0.3 to avoid too many
// internal sever errors (#2743, #2938)
parallelChunkUpload = false;
}
}
}
if (_currentChunk + _startChunk >= _chunkCount - 1) {
// Don't do parallel upload of chunk if this might be the last chunk because the server cannot handle that
// https://github.com/owncloud/core/issues/11106
+11 -5
Ver Arquivo
@@ -73,11 +73,13 @@ SyncEngine::SyncEngine(AccountPtr account, const QString& localPath,
, _downloadLimit(0)
, _newBigFolderSizeLimit(-1)
, _checksum_hook(journal)
, _anotherSyncNeeded(false)
, _anotherSyncNeeded(NoFollowUpSync)
{
qRegisterMetaType<SyncFileItem>("SyncFileItem");
qRegisterMetaType<SyncFileItem::Status>("SyncFileItem::Status");
qRegisterMetaType<SyncFileStatus>("SyncFileStatus");
qRegisterMetaType<SyncFileItemVector>("SyncFileItemVector");
qRegisterMetaType<SyncFileItem::Direction>("SyncFileItem::Direction");
// Everything in the SyncEngine expects a trailing slash for the localPath.
Q_ASSERT(localPath.endsWith(QLatin1Char('/')));
@@ -693,12 +695,13 @@ void SyncEngine::startSync()
Q_ASSERT(!_syncRunning);
s_anySyncRunning = true;
_syncRunning = true;
_anotherSyncNeeded = false;
_anotherSyncNeeded = NoFollowUpSync;
_clearTouchedFilesTimer.stop();
_progressInfo->reset();
if (!QDir(_localPath).exists()) {
_anotherSyncNeeded = DelayedFollowUp;
// No _tr, it should only occur in non-mirall
emit csyncError("Unable to find local sync folder.");
finalize(false);
@@ -712,6 +715,7 @@ void SyncEngine::startSync()
qDebug() << "There are" << freeBytes << "bytes available at" << _localPath
<< "and at least" << minFree << "are required";
if (freeBytes < minFree) {
_anotherSyncNeeded = DelayedFollowUp;
emit csyncError(tr("Only %1 are available, need at least %2 to start",
"Placeholders are postfixed with file sizes using Utility::octetsToString()").arg(
Utility::octetsToString(freeBytes),
@@ -1048,7 +1052,9 @@ void SyncEngine::slotItemCompleted(const SyncFileItem &item, const PropagatorJob
void SyncEngine::slotFinished(bool success)
{
_anotherSyncNeeded = _anotherSyncNeeded || _propagator->_anotherSyncNeeded;
if (_propagator->_anotherSyncNeeded && _anotherSyncNeeded == NoFollowUpSync) {
_anotherSyncNeeded = ImmediateFollowUp;
}
if (success) {
_journal->setDataFingerprint(_discoveryMainThread->_dataFingerprint);
@@ -1171,7 +1177,7 @@ void SyncEngine::checkForPermission()
// be restored. Do that in the next sync by not considering as a rename
// but delete and upload. It will then be restored if needed.
_journal->avoidRenamesOnNextSync((*it)->_file);
_anotherSyncNeeded = true;
_anotherSyncNeeded = ImmediateFollowUp;
qDebug() << "Moving of " << (*it)->_file << " canceled because no permission to add parent folder";
}
(*it)->_instruction = CSYNC_INSTRUCTION_ERROR;
@@ -1328,7 +1334,7 @@ void SyncEngine::checkForPermission()
// At this point we would need to go back to the propagate phase on both remote to take
// the decision.
_journal->avoidRenamesOnNextSync((*it)->_file);
_anotherSyncNeeded = true;
_anotherSyncNeeded = ImmediateFollowUp;
if ((*it)->_isDirectory) {
+10 -3
Ver Arquivo
@@ -49,6 +49,13 @@ class SyncJournalDb;
class OwncloudPropagator;
class PropagatorJob;
enum AnotherSyncNeeded
{
NoFollowUpSync,
ImmediateFollowUp, // schedule this again immediately (limited amount of times)
DelayedFollowUp // regularly schedule this folder again (around 1/minute, unlimited)
};
/**
* @brief The SyncEngine class
* @ingroup libsync
@@ -82,8 +89,8 @@ public:
Utility::StopWatch &stopWatch() { return _stopWatch; }
SyncFileStatusTracker &syncFileStatusTracker() { return *_syncFileStatusTracker; }
/* Return true if we detected that another sync is needed to complete the sync */
bool isAnotherSyncNeeded() { return _anotherSyncNeeded; }
/* Returns whether another sync is needed to complete the sync */
AnotherSyncNeeded isAnotherSyncNeeded() { return _anotherSyncNeeded; }
/** Get the ms since a file was touched, or -1 if it wasn't.
*
@@ -259,7 +266,7 @@ private:
/// Hook for computing checksums from csync_update
CSyncChecksumHook _checksum_hook;
bool _anotherSyncNeeded;
AnotherSyncNeeded _anotherSyncNeeded;
/** Stores the time since a job touched a file. */
QHash<QString, QElapsedTimer> _touchedFiles;
+1
Ver Arquivo
@@ -131,6 +131,7 @@ SyncJournalErrorBlacklistRecord SyncJournalErrorBlacklistRecord::update(
bool mayBlacklist =
item._errorMayBeBlacklisted // explicitly flagged for blacklisting
|| (item._httpErrorCode != 0 // or non-local error
&& item._httpErrorCode != 507 // Don't blacklist "Insufficient Storage"
#ifdef OWNCLOUD_5XX_NO_BLACKLIST
&& item._httpErrorCode / 100 != 5 // In this configuration, never blacklist error 5xx
#endif
+1 -1
Ver Arquivo
@@ -23,7 +23,7 @@ using namespace OCC;
class HttpCredentialsTest : public HttpCredentials {
public:
HttpCredentialsTest(const QString& user, const QString& password)
: HttpCredentials(user, password, "", "")
: HttpCredentials(user, password)
{}
void askFromUser() Q_DECL_OVERRIDE {
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff