Comparar commits

..

1 Commits

Autor SHA1 Mensagem Data
Piotr M 54b94ff29c dynamic chunking prototype 2016-12-13 11:25:49 +01:00
89 arquivos alterados com 11138 adições e 14299 exclusões
+1 -4
Ver Arquivo
@@ -58,9 +58,6 @@ if( UNIX AND NOT APPLE )
endif()
####
# Enable Q_ASSERT etc. in all builds
add_definitions( -DQT_FORCE_ASSERTS )
include(GNUInstallDirs)
include(DefineInstallationPaths)
include(GenerateExportHeader)
@@ -72,7 +69,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,45 +1,6 @@
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,6 +44,11 @@
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,6 +103,9 @@ struct csync_s {
} callbacks;
c_strlist_t *excludes;
// needed for SSL client certificate support
struct csync_client_certs_s *clientCerts;
struct {
char *file;
+9 -1
Ver Arquivo
@@ -68,9 +68,17 @@ 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::
@@ -83,7 +91,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:$PATH
export PATH=/usr/local/Cellar/qt5/5.x.y/bin/qmake
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 /home/user/my_sync_folder https://carla:secret@server/owncloud/remote.php/webdav/
$ owncloudcmd / 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
-66
Ver Arquivo
@@ -553,72 +553,6 @@ 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
# Translations
# Translations
# Translations
# Translations
Comment[oc]=@APPLICATION_NAME@ sincronizacion del client
GenericName[oc]=Dorsièr de Sincronizacion
@@ -24,7 +24,6 @@
#include <KIOCore/kfileitem.h>
#include <KIOCore/KFileItemListProperties>
#include <QtWidgets/QAction>
#include <QtCore/QDir>
#include <QtCore/QTimer>
#include "ownclouddolphinpluginhelper.h"
@@ -44,8 +43,7 @@ public:
auto url = urls.first();
if (!url.isLocalFile())
return {};
QDir localPath(url.toLocalFile());
auto localFile = localPath.canonicalPath();
auto localFile = url.toLocalFile();
const auto paths = helper->paths();
if (!std::any_of(paths.begin(), paths.end(), [&](const QString &s) {
@@ -21,7 +21,6 @@
#include <KPluginFactory>
#include <QtNetwork/QLocalSocket>
#include <KIOCore/kfileitem.h>
#include <QDir>
#include <QTimer>
#include "ownclouddolphinpluginhelper.h"
@@ -47,8 +46,7 @@ public:
return QStringList();
if (!url.isLocalFile())
return QStringList();
QDir localPath(url.toLocalFile());
const QByteArray localFile = localPath.canonicalPath().toUtf8();
const QByteArray localFile = url.toLocalFile().toUtf8();
helper->sendCommand(QByteArray("RETRIEVE_FILE_STATUS:" + localFile + "\n"));
+110
Ver Arquivo
@@ -0,0 +1,110 @@
/*
* 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
@@ -0,0 +1,62 @@
/*
* 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 */
+4154 -6936
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+29 -125
Ver Arquivo
@@ -108,8 +108,7 @@ 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] ([dateof:3.6.18]),
** SQLite source code has been stored in the
** Since version 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
@@ -121,13 +120,13 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.16.1"
#define SQLITE_VERSION_NUMBER 3016001
#define SQLITE_SOURCE_ID "2017-01-03 18:27:03 979f04392853b8053817a3eea2fc679947b437fd"
#define SQLITE_VERSION "3.14.2"
#define SQLITE_VERSION_NUMBER 3014002
#define SQLITE_SOURCE_ID "2016-09-12 18:50:49 29dbef4b8585f753861a36d6dd102ca634197bd6"
/*
** 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
@@ -453,8 +452,7 @@ 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 [dateof:3.3.8]
** and later) include
** address this, newer versions of SQLite (version 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
@@ -978,12 +976,6 @@ 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
@@ -1034,8 +1026,6 @@ 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
@@ -1979,36 +1969,13 @@ 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* */
/*
@@ -3610,10 +3577,6 @@ 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);
@@ -4078,8 +4041,7 @@ 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] ([dateof:3.6.23.1],
** sqlite3_step() began
** sqlite3_step(). But after version 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
@@ -5442,8 +5404,7 @@ 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] ([dateof:3.5.0]).
** In prior versions of SQLite,
** This is a change as of SQLite version 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
@@ -5537,8 +5498,7 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
** from the heap.
** </ul>)^
**
** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]),
** the soft heap limit is enforced
** Beginning with SQLite version 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
@@ -5932,15 +5892,13 @@ 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] ([dateof:3.8.2]).
** If a virtual table extension is
** structure for SQLite version 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] ([dateof:3.9.0]).
** It may therefore only be used if
** was added for version 3.9.0. It may therefore only be used if
** sqlite3_libversion_number() returns a value greater than or equal to
** 3009000.
*/
@@ -6638,7 +6596,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_randomness() */
#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */
#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
@@ -6742,7 +6700,6 @@ 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
@@ -8229,8 +8186,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
**
** See also: [sqlite3_update_hook()]
*/
#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
SQLITE_API void *sqlite3_preupdate_hook(
SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_preupdate_hook(
sqlite3 *db,
void(*xPreUpdate)(
void *pCtx, /* Copy of third arg to preupdate_hook() */
@@ -8243,11 +8199,10 @@ SQLITE_API void *sqlite3_preupdate_hook(
),
void*
);
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
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 **);
/*
** CAPI3REF: Low-level system error code
@@ -8263,7 +8218,7 @@ SQLITE_API int sqlite3_system_errno(sqlite3*);
/*
** CAPI3REF: Database Snapshot
** KEYWORDS: {snapshot} {sqlite3_snapshot}
** KEYWORDS: {snapshot}
** EXPERIMENTAL
**
** An instance of the snapshot object records the state of a [WAL mode]
@@ -8287,9 +8242,7 @@ 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 {
unsigned char hidden[48];
} sqlite3_snapshot;
typedef struct sqlite3_snapshot sqlite3_snapshot;
/*
** CAPI3REF: Record A Database Snapshot
@@ -8300,32 +8253,9 @@ typedef struct 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 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.
** ^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].
**
** The [sqlite3_snapshot] object returned from a successful call to
** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()]
@@ -8418,28 +8348,6 @@ 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.
@@ -8731,7 +8639,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 object, the filter is called
** in tables that are not attached to the Session oject, 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.
@@ -8997,7 +8905,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 visited
** this function, all changes that relate to a single table are visted
** 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.
@@ -9084,7 +8992,7 @@ int sqlite3changeset_op(
** 0x01 if the corresponding column is part of the tables primary key, or
** 0x00 if it is not.
**
** If argument pnCol is not NULL, then *pnCol is set to the number of columns
** If argumet 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
@@ -9301,12 +9209,12 @@ int sqlite3changeset_concat(
/*
** CAPI3REF: Changegroup Handle
** Changegroup handle.
*/
typedef struct sqlite3_changegroup sqlite3_changegroup;
/*
** CAPI3REF: Create A New Changegroup Object
** CAPI3REF: Combine two or more changesets into a single changeset.
**
** An sqlite3_changegroup object is used to combine two or more changesets
** (or patchsets) into a single changeset (or patchset). A single changegroup
@@ -9343,8 +9251,6 @@ 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.
**
@@ -9359,7 +9265,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 do not already appear in the changegroup are
** Changes to rows that 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:
@@ -9420,8 +9326,6 @@ 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
@@ -9450,7 +9354,7 @@ int sqlite3changegroup_output(
);
/*
** CAPI3REF: Delete A Changegroup Object
** 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() != NoFollowUpSync) {
if (engine.isAnotherSyncNeeded()) {
if (restartCount < options.restartTimes) {
restartCount++;
qDebug() << "Restarting Sync, because another sync is needed" << restartCount;
+1
Ver Arquivo
@@ -151,6 +151,7 @@ set(3rdparty_SRC
../3rdparty/qtsingleapplication/qtlocalpeer.cpp
../3rdparty/qtsingleapplication/qtsingleapplication.cpp
../3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp
../3rdparty/certificates/p12topem.cpp
)
if (APPLE)
+1 -12
Ver Arquivo
@@ -214,17 +214,6 @@ 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() ) {
@@ -248,7 +237,7 @@ AccountPtr AccountManager::loadAccountHelper(QSettings& settings)
acc->setCredentials(CredentialsFactory::create(authType));
// now the server cert, it is in the general group
// now the 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,10 +214,8 @@ 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);
@@ -233,10 +231,6 @@ 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>188</height>
<height>186</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 &amp; Key (pkcs12) :</string>
<string>Certificate :</string>
</property>
</widget>
</item>
+12
Ver Arquivo
@@ -347,6 +347,14 @@ void Application::slotownCloudWizardDone( int res )
}
}
static void csyncLogCatcher(int /*verbosity*/,
const char */*function*/,
const char *buffer,
void */*userdata*/)
{
Logger::instance()->csyncLog( QString::fromUtf8(buffer) );
}
void Application::setupLogging()
{
// might be called from second instance
@@ -362,6 +370,10 @@ void Application::setupLogging()
.arg(property("ui_lang").toString())
.arg(_theme->version())
.arg(Utility::platformName());
// Setup CSYNC logging to forward to our own logger
csync_set_log_callback( csyncLogCatcher );
csync_set_log_level( Logger::instance()->isNoop() ? 0 : 11 );
}
void Application::slotUseMonoIconsChanged(bool)
+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 QSslCertificate& certificate, const QSslKey& key) : HttpCredentials(user, password, certificate, key) {}
HttpCredentialsGui(const QString& user, const QString& password, const QString& certificatePath, const QString& certificatePasswd) : HttpCredentials(user, password, certificatePath, certificatePasswd) {}
void askFromUser() Q_DECL_OVERRIDE;
Q_INVOKABLE void askFromUserAsync();
+6 -3
Ver Arquivo
@@ -65,6 +65,9 @@ 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();
@@ -823,7 +826,7 @@ void Folder::slotSyncFinished(bool success)
_fileLog->finish();
bubbleUpSyncResult();
auto anotherSyncNeeded = _engine->isAnotherSyncNeeded();
bool anotherSyncNeeded = _engine->isAnotherSyncNeeded();
if (_csyncError) {
_syncResult.setStatus(SyncResult::Error);
@@ -874,7 +877,7 @@ void Folder::slotSyncFinished(bool success)
_timeSinceLastSyncDone.restart();
// Increment the follow-up sync counter if necessary.
if (anotherSyncNeeded == ImmediateFollowUp) {
if (anotherSyncNeeded) {
_consecutiveFollowUpSyncs++;
qDebug() << "another sync was requested by the finished sync, this has"
<< "happened" << _consecutiveFollowUpSyncs << "times";
@@ -883,7 +886,7 @@ void Folder::slotSyncFinished(bool success)
}
// Maybe force a follow-up sync to take place, but only a couple of times.
if (anotherSyncNeeded == ImmediateFollowUp && _consecutiveFollowUpSyncs <= 3)
if (anotherSyncNeeded && _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
+10 -17
Ver Arquivo
@@ -148,7 +148,6 @@ 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);
@@ -731,10 +730,6 @@ 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() );
}
@@ -838,20 +833,18 @@ void FolderMan::slotScheduleFolderByTime()
continue;
}
// 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
// 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
if (f->consecutiveFailingSyncs() > 1)
syncAgainDelay = 60 * 1000; // 60s for each further attempt
if (syncAgain
&& msecsSinceSync > syncAgainDelay) {
syncAgainAfterFailDelay = 60 * 1000; // 60s for each further attempt
if (syncAgainAfterFail
&& msecsSinceSync > syncAgainAfterFailDelay) {
qDebug() << "** scheduling folder" << f->alias()
<< ", the last" << f->consecutiveFailingSyncs() << "syncs failed"
<< ", anotherSyncNeeded" << f->syncEngine().isAnotherSyncNeeded()
<< ", last status:" << f->syncResult().statusString()
<< ", time since last sync:" << msecsSinceSync;
<< "because the last"
<< f->consecutiveFailingSyncs() << "syncs failed, last status:"
<< f->syncResult().statusString()
<< "time since last sync:" << msecsSinceSync;
scheduleFolder(f);
continue;
+9 -6
Ver Arquivo
@@ -527,8 +527,10 @@ void FolderStatusModel::fetchMore(const QModelIndex& parent)
if (!info || info->_fetched || info->_fetching)
return;
info->resetSubs(this, parent);
info->_hasError = false;
info->_fetching = true;
info->_fetchingLabel = false;
QString path = info->_folder->remotePath();
if (info->_path != QLatin1String("/")) {
if (!path.endsWith(QLatin1Char('/'))) {
@@ -696,16 +698,17 @@ 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 {
Q_ASSERT(!parentInfo->hasLabel());
beginInsertRows(idx, 0, 0);
if (!parentInfo->hasLabel()) {
beginInsertRows(idx, 0, 0);
endInsertRows();
}
parentInfo->_hasError = true;
endInsertRows();
}
parentInfo->_fetching = false;
parentInfo->_fetchingLabel = false;
}
}
+1 -2
Ver Arquivo
@@ -110,9 +110,8 @@ LogBrowser::LogBrowser(QWidget *parent) :
setModal(false);
Logger::instance()->setLogWindowActivated(true);
// Direct connection for log coming from this thread, and queued for the one in a different thread
connect(Logger::instance(), SIGNAL(logWindowLog(QString)),this,SLOT(slotNewLog(QString)), Qt::AutoConnection);
connect(Logger::instance(), SIGNAL(newLog(QString)),this,SLOT(slotNewLog(QString)), Qt::AutoConnection);
QAction *showLogWindow = new QAction(this);
showLogWindow->setShortcut(QKeySequence("F12"));
+1 -13
Ver Arquivo
@@ -207,15 +207,10 @@ 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;
if (!_ocWizard->account()->url().isValid()) {
msg = tr("Invalid URL");
} else {
msg = tr("Failed to connect to %1 at %2:<br/>%3")
QString 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:
@@ -558,13 +553,6 @@ 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,11 +29,8 @@ OwncloudConnectionMethodDialog::OwncloudConnectionMethodDialog(QWidget *parent)
connect(ui->btnClientSideTLS, SIGNAL(clicked(bool)), this, SLOT(returnClientSideTLS()));
connect(ui->btnBack, SIGNAL(clicked(bool)), this, SLOT(returnBack()));
#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
// DM: TLS Client Cert GUI support disabled for now
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->_clientSslCertificate, _ocWizard->_clientSslKey);
return new HttpCredentialsGui(_ui.leUsername->text(), _ui.lePassword->text(), _ocWizard->ownCloudCertificatePath, _ocWizard->ownCloudCertificatePasswd);
}
+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,6 +71,7 @@ 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 )
@@ -138,7 +139,7 @@ void OwncloudSetupPage::slotUrlChanged(const QString& url)
void OwncloudSetupPage::slotUrlEditFinished()
{
QString url = _ui.leUrl->fullText();
if (QUrl(url).isRelative() && !url.isEmpty()) {
if (QUrl(url).isRelative()) {
// no scheme defined, set one
url.prepend("https://");
}
@@ -268,10 +269,7 @@ void OwncloudSetupPage::setErrorString( const QString& err, bool retryHTTPonly )
}
break;
case OwncloudConnectionMethodDialog::Client_Side_TLS:
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
addCertDial->show();
connect(addCertDial, SIGNAL(accepted()),this,SLOT(slotCertificateAccepted()));
#endif
slotAskSSLClientCertificate();
break;
case OwncloudConnectionMethodDialog::Closed:
case OwncloudConnectionMethodDialog::Back:
@@ -304,6 +302,12 @@ 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)
@@ -316,40 +320,36 @@ QString subjectInfoHelper(const QSslCertificate& cert, const QByteArray &qa)
//called during the validation of the client certificate.
void OwncloudSetupPage::slotCertificateAccepted()
{
#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())){
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();
AccountPtr acc = _ocWizard->account();
// 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?
acc->setCertificate(_ocWizard->ownCloudCertificate, _ocWizard->ownCloudPrivateKey);
addCertDial->reinit();
validatePage();
} else {
addCertDial->showErrorMessage("Could not load certificate");
QString message;
message = certif.Comment.c_str();
addCertDial->showErrorMessage(message);
addCertDial->show();
}
#endif
}
OwncloudSetupPage::~OwncloudSetupPage()
{
delete addCertDial;
}
} // namespace OCC
+1
Ver Arquivo
@@ -59,6 +59,7 @@ public slots:
void setErrorString( const QString&, bool retryHTTPonly );
void startSpinner();
void stopSpinner();
void slotAskSSLClientCertificate();
void slotCertificateAccepted();
protected slots:
+7
Ver Arquivo
@@ -224,4 +224,11 @@ AbstractCredentials* OwncloudWizard::getCredentials() const
return 0;
}
// outputs the signal needed to authenticate a certificate
void OwncloudWizard::raiseCertificatePopup()
{
emit needCertificate();
}
} // end namespace
+5 -6
Ver Arquivo
@@ -17,8 +17,6 @@
#define MIRALL_OWNCLOUD_WIZARD_H
#include <QWizard>
#include <QSslKey>
#include <QSslCertificate>
#include "wizard/owncloudwizardcommon.h"
#include "accountfwd.h"
@@ -65,10 +63,11 @@ public:
void displayError( const QString&, bool retryHTTPonly);
AbstractCredentials* getCredentials() const;
// FIXME: Can those be local variables?
// Set from the OwncloudSetupPage, later used from OwncloudHttpCredsPage
QSslKey _clientSslKey;
QSslCertificate _clientSslCertificate;
void raiseCertificatePopup();
QByteArray ownCloudCertificate;
QString ownCloudPrivateKey;
QString ownCloudCertificatePath;
QString ownCloudCertificatePasswd;
public slots:
void setAuthType(WizardCommon::AuthType type);
+1
Ver Arquivo
@@ -70,6 +70,7 @@ set(libsync_SRCS
creds/abstractcredentials.cpp
creds/credentialscommon.cpp
../3rdparty/qjson/json.cpp
../3rdparty/certificates/p12topem.cpp
)
if(TOKEN_AUTH_ONLY)
+33 -11
Ver Arquivo
@@ -18,6 +18,7 @@
#include "configfile.h"
#include "accessmanager.h"
#include "creds/abstractcredentials.h"
#include "../3rdparty/certificates/p12topem.h"
#include "capabilities.h"
#include "theme.h"
@@ -92,7 +93,7 @@ void Account::setDavUser(const QString &newDavUser)
QString Account::displayName() const
{
QString dn = QString("%1@%2").arg(_credentials->user(), _url.host());
QString dn = QString("%1@%2").arg(davUser(), _url.host());
int port = url().port();
if (port > 0 && port != 80 && port != 443) {
dn.append(QLatin1Char(':'));
@@ -148,14 +149,10 @@ 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())->setAllCookies(QList<QNetworkCookie>());
emit wantsAccountSaved(this);
static_cast<CookieJar*>(_am->cookieJar())->clearSessionCookies();
}
/*! This shares our official cookie jar (containing all the tasty
@@ -245,6 +242,12 @@ QNetworkReply *Account::davRequest(const QByteArray &verb, const QUrl &url, QNet
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;
@@ -261,7 +264,31 @@ 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);
@@ -352,11 +379,8 @@ 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);
@@ -368,8 +392,6 @@ 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())) {
+2 -1
Ver Arquivo
@@ -224,7 +224,8 @@ 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;
};
+5 -2
Ver Arquivo
@@ -116,9 +116,12 @@ bool Capabilities::chunkingNg() const
return _capabilities["dav"].toMap()["chunking"].toByteArray() >= "1.0";
}
bool Capabilities::chunkingParallelUploadDisabled() const
quint64 Capabilities::requestMaxDurationDC() const
{
return _capabilities["dav"].toMap()["chunkingParallelUploadDisabled"].toBool();
QByteArray requestMaxDurationDC = _capabilities["dav"].toMap()["max_single_upload_request_duration_msec"].toByteArray();
if (!requestMaxDurationDC.isEmpty())
return requestMaxDurationDC.toLongLong();
return 0;
}
}
+1 -3
Ver Arquivo
@@ -41,9 +41,7 @@ public:
int sharePublicLinkExpireDateDays() const;
bool shareResharing() const;
bool chunkingNg() const;
/// disable parallel upload in chunking
bool chunkingParallelUploadDisabled() const;
quint64 requestMaxDurationDC() const;
/// returns true if the capabilities report notifications
bool notificationsAvailable() const;
+13
Ver Arquivo
@@ -52,6 +52,7 @@ static const char updateCheckIntervalC[] = "updateCheckInterval";
static const char geometryC[] = "geometry";
static const char timeoutC[] = "timeout";
static const char chunkSizeC[] = "chunkSize";
static const char maxChunkSizeC[] = "maxChunkSizeC";
static const char proxyHostC[] = "Proxy/host";
static const char proxyTypeC[] = "Proxy/type";
@@ -128,6 +129,18 @@ quint64 ConfigFile::chunkSize() const
return settings.value(QLatin1String(chunkSizeC), 10*1000*1000).toLongLong(); // default to 10 MB
}
quint64 ConfigFile::maxChunkSize() const
{
QSettings settings(configFile(), QSettings::IniFormat);
return settings.value(QLatin1String(maxChunkSizeC), 50*1000*1000).toLongLong(); // default to 50 MB
}
quint64 ConfigFile::minChunkSize() const
{
QSettings settings(configFile(), QSettings::IniFormat);
return settings.value(QLatin1String(maxChunkSizeC), 1000*1000).toLongLong(); // default to 1 MB
}
void ConfigFile::setOptionalDesktopNotifications(bool show)
{
QSettings settings(configFile(), QSettings::IniFormat);
+2
Ver Arquivo
@@ -113,6 +113,8 @@ public:
int timeout() const;
quint64 chunkSize() const;
quint64 maxChunkSize() const;
quint64 minChunkSize() const;
void saveGeometry(QWidget *w);
void restoreGeometry(QWidget *w);
+1 -6
Ver Arquivo
@@ -144,12 +144,7 @@ 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() << 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
qDebug() << Q_FUNC_INFO << reply->error() << reply->errorString();
if( reply && ! _account->credentials()->stillValid(reply)) {
_errors.append(tr("Authentication error: Either username or password are wrong."));
} else {
+45 -127
Ver Arquivo
@@ -17,7 +17,6 @@
#include <QDebug>
#include <QNetworkReply>
#include <QSettings>
#include <QSslKey>
#include <keychain.h>
@@ -37,8 +36,8 @@ namespace OCC
namespace
{
const char userC[] = "user";
const char clientCertificatePEMC[] = "_clientCertificatePEM";
const char clientKeyPEMC[] = "_clientKeyPEM";
const char certifPathC[] = "certificatePath";
const char certifPasswdC[] = "certificatePasswd";
const char authenticationFailedC[] = "owncloud-authentication-failed";
} // ns
@@ -51,47 +50,24 @@ 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)
// << _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);
}
//qDebug() << "Request for " << req.url() << "with authorization" << QByteArray::fromBase64(credHash);
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)
{
}
// From wizard
HttpCredentials::HttpCredentials(const QString& user, const QString& password, const QSslCertificate& certificate, const QSslKey& key)
HttpCredentials::HttpCredentials(const QString& user, const QString& password, const QString& certificatePath, const QString& certificatePasswd)
: _user(user),
_password(password),
_ready(true),
_clientSslKey(key),
_clientSslCertificate(certificate)
_certificatePath(certificatePath),
_certificatePasswd(certificatePasswd)
{
}
@@ -110,6 +86,16 @@ 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);
@@ -143,83 +129,35 @@ 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());
addSettingsToJob(_account, job);
settings->setParent(job); // make the job parent to make setting deleted properly
job->setSettings(settings.release());
job->setInsecureFallback(false);
job->setKey(kck);
qDebug() << "-------- ----->" << _clientSslCertificate << _clientSslKey;
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadClientCertPEMJobDone(QKeychain::Job*)));
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(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)
@@ -228,10 +166,10 @@ bool HttpCredentials::stillValid(QNetworkReply *reply)
|| !reply->property(authenticationFailedC).toBool()));
}
void HttpCredentials::slotReadJobDone(QKeychain::Job *incomingJob)
void HttpCredentials::slotReadJobDone(QKeychain::Job *job)
{
QKeychain::ReadPasswordJob *job = static_cast<ReadPasswordJob*>(incomingJob);
_password = job->textData();
ReadPasswordJob *readJob = static_cast<ReadPasswordJob*>(job);
_password = readJob->textData();
if( _user.isEmpty()) {
qDebug() << "Strange: User is empty!";
@@ -240,6 +178,7 @@ void HttpCredentials::slotReadJobDone(QKeychain::Job *incomingJob)
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.
@@ -275,7 +214,9 @@ void HttpCredentials::invalidateToken()
}
DeletePasswordJob *job = new DeletePasswordJob(Theme::instance()->appName());
addSettingsToJob(_account, job);
auto settings = Utility::settingsWithGroup(Theme::instance()->appName());
settings->setParent(job); // make the job parent to make setting deleted properly
job->setSettings(settings.release());
job->setInsecureFallback(true);
job->setKey(kck);
job->start();
@@ -320,37 +261,14 @@ void HttpCredentials::persist()
// We never connected or fetched the user, there is nothing to save.
return;
}
_account->setCredentialSetting(QLatin1String(userC), _user);
// write cert
_account->setCredentialSetting(QLatin1String(certifPathC), _certificatePath);
_account->setCredentialSetting(QLatin1String(certifPasswdC), _certificatePasswd);
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();
}
auto settings = Utility::settingsWithGroup(Theme::instance()->appName());
settings->setParent(job); // make the job parent to make setting deleted properly
job->setSettings(settings.release());
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));
+9 -15
Ver Arquivo
@@ -17,8 +17,7 @@
#define MIRALL_CREDS_HTTP_CREDENTIALS_H
#include <QMap>
#include <QSslCertificate>
#include <QSslKey>
#include "creds/abstractcredentials.h"
class QNetworkReply;
@@ -26,8 +25,6 @@ class QAuthenticator;
namespace QKeychain {
class Job;
class WritePasswordJob;
class ReadPasswordJob;
}
namespace OCC
@@ -36,10 +33,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 QSslCertificate& certificate = QSslCertificate(), const QSslKey& key = QSslKey());
HttpCredentials(const QString& user, const QString& password, const QString& certificatePath, const QString& certificatePasswd);
QString authType() const Q_DECL_OVERRIDE;
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
@@ -53,19 +50,15 @@ 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();
@@ -73,11 +66,12 @@ protected:
QString _user;
QString _password;
QString _previousPassword;
QString _fetchErrorString;
bool _ready;
QSslKey _clientSslKey;
QSslCertificate _clientSslCertificate;
private:
QString _certificatePath;
QString _certificatePasswd;
};
} // namespace OCC
+7 -28
Ver Arquivo
@@ -19,8 +19,6 @@
#include <QThread>
#include <qmetaobject.h>
#include "csync.h"
namespace OCC {
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
@@ -50,14 +48,6 @@ static void mirallLogCatcher(QtMsgType type, const QMessageLogContext &ctx, cons
}
#endif
static void csyncLogCatcher(int /*verbosity*/,
const char * /*function*/,
const char *buffer,
void * /*userdata*/)
{
Logger::instance()->csyncLog( QString::fromUtf8(buffer) );
}
Logger *Logger::instance()
{
static Logger log;
@@ -65,7 +55,7 @@ Logger *Logger::instance()
}
Logger::Logger( QObject* parent) : QObject(parent),
_showTime(true), _logWindowActivated(false), _doFileFlush(false), _logExpire(0)
_showTime(true), _doLogging(false), _doFileFlush(false), _logExpire(0)
{
#ifndef NO_MSG_HANDLER
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
@@ -127,8 +117,12 @@ bool Logger::isNoop() const
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
return false;
#else
static auto signal = QMetaMethod::fromSignal(&Logger::newLog);
if (isSignalConnected(signal)) {
return false;
}
QMutexLocker lock(const_cast<QMutex *>(&_mutex));
return !_logstream && !_logWindowActivated;
return !_logstream;
#endif
}
@@ -142,7 +136,7 @@ void Logger::doLog(const QString& msg)
if( _doFileFlush ) _logstream->flush();
}
}
emit logWindowLog(msg);
emit newLog(msg);
}
void Logger::csyncLog( const QString& message )
@@ -170,25 +164,10 @@ void Logger::mirallLog( const QString& message )
Logger::instance()->log( log_ );
}
void Logger::setLogWindowActivated(bool activated)
{
QMutexLocker locker(&_mutex);
// Setup CSYNC logging to forward to our own logger
csync_set_log_callback(csyncLogCatcher);
csync_set_log_level(11);
_logWindowActivated = activated;
}
void Logger::setLogFile(const QString & name)
{
QMutexLocker locker(&_mutex);
// Setup CSYNC logging to forward to our own logger
csync_set_log_callback(csyncLogCatcher);
csync_set_log_level(11);
if( _logstream ) {
_logstream.reset(0);
_logFile.close();
+2 -4
Ver Arquivo
@@ -61,15 +61,13 @@ public:
void postOptionalGuiLog(const QString& title, const QString& message);
void postGuiMessage(const QString& title, const QString& message);
void setLogWindowActivated(bool activated);
void setLogFile( const QString & name );
void setLogExpire( int expire );
void setLogDir( const QString& dir );
void setLogFlush( bool flush );
signals:
void logWindowLog(const QString&);
void newLog(const QString&);
void guiLog(const QString&, const QString&);
void guiMessage(const QString&, const QString&);
void optionalGuiLog(const QString&, const QString&);
@@ -82,7 +80,7 @@ private:
~Logger();
QList<Log> _logs;
bool _showTime;
bool _logWindowActivated;
bool _doLogging;
QFile _logFile;
bool _doFileFlush;
int _logExpire;
+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!" << body << reply()->request().url();
qDebug() << "status.php from server is not valid JSON!";
}
qDebug() << "status.php returns: " << status << " " << reply()->error() << " Reply: " << reply();
+24 -2
Ver Arquivo
@@ -74,7 +74,17 @@ OwncloudPropagator::~OwncloudPropagator()
/* The maximum number of active jobs in parallel */
int OwncloudPropagator::maximumActiveJob()
{
return 50;
static int max = qgetenv("OWNCLOUD_MAX_PARALLEL").toUInt();
if (!max) {
max = 3; //default
}
if (_downloadLimit.fetchAndAddAcquire(0) != 0 || _uploadLimit.fetchAndAddAcquire(0) != 0) {
// disable parallelism when there is a network limit.
return 1;
}
return max;
}
int OwncloudPropagator::hardMaximumActiveJob()
@@ -267,7 +277,7 @@ PropagateItemJob* OwncloudPropagator::createJob(const SyncFileItemPtr &item) {
} else {
PropagateUploadFileCommon *job = 0;
if (item->_size > chunkSize() && account()->capabilities().chunkingNg()) {
job = new PropagateUploadFileNG(this, item);
job = new PropagateUploadFileNG(this, item, account()->capabilities().requestMaxDurationDC());
} else {
job = new PropagateUploadFileV1(this, item);
}
@@ -449,6 +459,18 @@ quint64 OwncloudPropagator::chunkSize()
return chunkSize;
}
quint64 OwncloudPropagator::maxChunkSize()
{
static uint chunkSize;
if (!chunkSize) {
chunkSize = qgetenv("OWNCLOUD_MAX_CHUNK_SIZE").toUInt();
if (chunkSize == 0) {
ConfigFile cfg;
chunkSize = cfg.maxChunkSize();
}
}
return chunkSize;
}
bool OwncloudPropagator::localFileNameClash( const QString& relFile )
{
+1 -1
Ver Arquivo
@@ -272,7 +272,6 @@ public:
SyncJournalDb * const _journal;
bool _finishedEmited; // used to ensure that finished is only emitted once
public:
OwncloudPropagator(AccountPtr account, const QString &localDir,
const QString &remoteFolder, SyncJournalDb *progressDb)
@@ -327,6 +326,7 @@ public:
/** returns the size of chunks in bytes */
static quint64 chunkSize();
static quint64 maxChunkSize();
AccountPtr account() const;
+3 -17
Ver Arquivo
@@ -70,9 +70,7 @@ bool SqlDatabase::openHelper( const QString& filename, int sqliteFlags )
bool SqlDatabase::checkDb()
{
// 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);
SqlQuery quick_check("PRAGMA quick_check;", *this);
if( !quick_check.exec() ) {
qDebug() << "Error running quick_check on database";
return false;
@@ -99,14 +97,6 @@ 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);
@@ -201,7 +191,7 @@ SqlQuery::SqlQuery(const QString& sql, SqlDatabase& db)
prepare(sql);
}
int SqlQuery::prepare( const QString& sql, bool allow_failure )
int SqlQuery::prepare( const QString& sql)
{
QString s(sql);
_sql = s.trimmed();
@@ -223,11 +213,7 @@ int SqlQuery::prepare( const QString& sql, bool allow_failure )
if( _errId != SQLITE_OK ) {
_error = QString::fromUtf8(sqlite3_errmsg(_db));
qWarning() << "Sqlite prepare statement error:" << _error << "in" <<_sql;
if (!allow_failure) {
qFatal("SQLITE Prepare error: %s in %s",
_error.toLocal8Bit().data(),
sql.toLocal8Bit().data());
}
Q_ASSERT(!"SQLITE Prepare error");
}
}
return _errId;
+1 -1
Ver Arquivo
@@ -80,7 +80,7 @@ public:
bool isSelect();
bool isPragma();
bool exec();
int prepare( const QString& sql, bool allow_failure = false );
int prepare( const QString& sql );
bool next();
void bindValue(int pos, const QVariant& value);
QString lastQuery() const;
+2 -6
Ver Arquivo
@@ -145,12 +145,8 @@ void ProgressInfo::reset()
_sizeProgress = Progress();
_fileProgress = Progress();
_totalSizeOfCompletedJobs = 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;
_maxBytesPerSecond = 100000.0;
_maxFilesPerSecond = 2.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, this);
&_tmpFile, headers, expectedEtagForResume, _resumeStart);
} 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, this);
&_tmpFile, headers, expectedEtagForResume, _resumeStart);
}
_job->setBandwidthManager(&_propagator->_bandwidthManager);
connect(_job, SIGNAL(finishedSignal()), this, SLOT(slotGetFinished()));
+27 -2
Ver Arquivo
@@ -290,12 +290,36 @@ private:
uint _transferId; /// transfer id (part of the url)
int _currentChunk; /// Id of the next chunk that will be sent
bool _removeJobError; /// If not null, there was an error removing the job
quint64 _lastChunkSize; /// current chunk size
/*
* This is value in ms obtained from the server.
*
* Dynamic Chunking attribute the maximum number of miliseconds that single request below chunk size can take
* This value should be based on heuristics with default value 10000ms, time it takes to transfer 10MB chunk on 1MB/s upload link.
*
* Suggested solution will be to evaluate max(SNR, MORD) where:
* > SNR - Slow network request, so time it will take to transmit default chunking sized request at specific low upload bandwidth
* > MORD - Maximum observed request time, so double the time of maximum observed RTT of the very small PUT request (e.g. 1kB) to the system
*
* Exemplary, syncing 100MB files, with chunking size 10MB, will cause sync of 10 PUT requests which max evaluation was set to <max_single_upload_request_duration_msec>
*
* Dynamic chunking client algorithm is specified in the ownCloud documentation and uses <max_single_upload_request_duration_msec> to estimate if given
* bandwidth allows higher chunk sizes (because of high goodput)
*/
quint64 _requestMaxDuration;
// Map chunk number with its size from the PROPFIND on resume.
// (Only used from slotPropfindIterate/slotPropfindFinished because the LsColJob use signals to report data.)
QMap<int, quint64> _serverChunks;
quint64 chunkSize() const { return _propagator->chunkSize(); }
quint64 maxChunkSize() const { return _propagator->maxChunkSize(); }
quint64 getRequestMaxDurationDC(){
return _requestMaxDuration;
}
/**
* Return the URL of a chunk.
* If chunk == -1, returns the URL of the parent folder containing the chunks
@@ -303,10 +327,11 @@ private:
QUrl chunkUrl(int chunk = -1);
public:
PropagateUploadFileNG(OwncloudPropagator* propagator,const SyncFileItemPtr& item) :
PropagateUploadFileCommon(propagator,item) {}
PropagateUploadFileNG(OwncloudPropagator* propagator,const SyncFileItemPtr& item, const quint64& requestMaxDuration) :
PropagateUploadFileCommon(propagator,item), _lastChunkSize(0), _requestMaxDuration(requestMaxDuration) {}
void doStartUpload() Q_DECL_OVERRIDE;
private:
void startNewUpload();
void startNextChunk();
+38 -3
Ver Arquivo
@@ -32,7 +32,7 @@
#include <QDir>
#include <cmath>
#include <cstring>
#include <cmath>
namespace OCC {
QUrl PropagateUploadFileNG::chunkUrl(int chunk)
@@ -262,7 +262,42 @@ void PropagateUploadFileNG::startNextChunk()
quint64 fileSize = _item->_size;
Q_ASSERT(fileSize >= _sent);
quint64 currentChunkSize = qMin(chunkSize(), fileSize - _sent);
quint64 currentChunkSize = chunkSize();
// this will check if getRequestMaxDurationDC is set to 0 or not
double requestMaxDurationDC = (double) getRequestMaxDurationDC();
if (requestMaxDurationDC != 0) {
// this if first chunked file request, so it can start with default size of chunkSize()
// if _lastChunkSize != 0 it means that we already have send one request
if(_lastChunkSize != 0){
//TODO: this is done step by step for debugging purposes
//get last request timestamp
double lastChunkLap = (double) _stopWatch.durationOfLap(QLatin1String("ChunkDuration"));
//get duration of the request
double requestDuration = (double) _stopWatch.addLapTime(QLatin1String("ChunkDuration")) - lastChunkLap;
// calculate natural logarithm
double correctionParameter = log(requestMaxDurationDC / requestDuration) - 1;
// If logarithm is smaller or equal zero, it means that we exceeded max request duration
// If exceeded it will use currentChunkSize = chunkSize()
// If did not exceeded, we will increase the chunk size
// motivation for logarithm is specified in the dynamic chunking documentation
// TODO: give link to documentation
if (correctionParameter>0){
currentChunkSize = qMin(_lastChunkSize + (qint64) correctionParameter*chunkSize(), maxChunkSize());
}
}
//remember the value of last chunk size
_lastChunkSize = currentChunkSize;
}
// prevent situation that chunk size is bigger then required one to send
currentChunkSize = qMin(currentChunkSize, fileSize - _sent);
if (currentChunkSize == 0) {
Q_ASSERT(_jobs.isEmpty()); // There should be no running job anymore
@@ -315,7 +350,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, this);
PUTFileJob* job = new PUTFileJob(_propagator->account(), url, device, headers, _currentChunk);
_jobs.append(job);
connect(job, SIGNAL(finishedSignal()), this, SLOT(slotPutFinished()));
connect(job, SIGNAL(uploadProgress(qint64,qint64)),
+9 -16
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, this);
PUTFileJob* job = new PUTFileJob(_propagator->account(), _propagator->_remoteFolder + path, device, headers, _currentChunk);
_jobs.append(job);
connect(job, SIGNAL(finishedSignal()), this, SLOT(slotPutFinished()));
connect(job, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(slotUploadProgress(qint64,qint64)));
@@ -134,25 +134,18 @@ void PropagateUploadFileV1::startNextChunk()
_currentChunk++;
bool parallelChunkUpload = true;
if (_propagator->account()->capabilities().chunkingParallelUploadDisabled()) {
// Server may also disable parallel chunked upload for any higher version
parallelChunkUpload = false;
QByteArray env = qgetenv("OWNCLOUD_PARALLEL_CHUNK");
if (!env.isEmpty()) {
parallelChunkUpload = env != "false" && env != "0";
} else {
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;
}
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
+5 -11
Ver Arquivo
@@ -73,13 +73,11 @@ SyncEngine::SyncEngine(AccountPtr account, const QString& localPath,
, _downloadLimit(0)
, _newBigFolderSizeLimit(-1)
, _checksum_hook(journal)
, _anotherSyncNeeded(NoFollowUpSync)
, _anotherSyncNeeded(false)
{
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('/')));
@@ -695,13 +693,12 @@ void SyncEngine::startSync()
Q_ASSERT(!_syncRunning);
s_anySyncRunning = true;
_syncRunning = true;
_anotherSyncNeeded = NoFollowUpSync;
_anotherSyncNeeded = false;
_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);
@@ -715,7 +712,6 @@ 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),
@@ -1052,9 +1048,7 @@ void SyncEngine::slotItemCompleted(const SyncFileItem &item, const PropagatorJob
void SyncEngine::slotFinished(bool success)
{
if (_propagator->_anotherSyncNeeded && _anotherSyncNeeded == NoFollowUpSync) {
_anotherSyncNeeded = ImmediateFollowUp;
}
_anotherSyncNeeded = _anotherSyncNeeded || _propagator->_anotherSyncNeeded;
if (success) {
_journal->setDataFingerprint(_discoveryMainThread->_dataFingerprint);
@@ -1177,7 +1171,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 = ImmediateFollowUp;
_anotherSyncNeeded = true;
qDebug() << "Moving of " << (*it)->_file << " canceled because no permission to add parent folder";
}
(*it)->_instruction = CSYNC_INSTRUCTION_ERROR;
@@ -1334,7 +1328,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 = ImmediateFollowUp;
_anotherSyncNeeded = true;
if ((*it)->_isDirectory) {
+3 -10
Ver Arquivo
@@ -49,13 +49,6 @@ 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
@@ -89,8 +82,8 @@ public:
Utility::StopWatch &stopWatch() { return _stopWatch; }
SyncFileStatusTracker &syncFileStatusTracker() { return *_syncFileStatusTracker; }
/* Returns whether another sync is needed to complete the sync */
AnotherSyncNeeded isAnotherSyncNeeded() { return _anotherSyncNeeded; }
/* Return true if we detected that another sync is needed to complete the sync */
bool isAnotherSyncNeeded() { return _anotherSyncNeeded; }
/** Get the ms since a file was touched, or -1 if it wasn't.
*
@@ -266,7 +259,7 @@ private:
/// Hook for computing checksums from csync_update
CSyncChecksumHook _checksum_hook;
AnotherSyncNeeded _anotherSyncNeeded;
bool _anotherSyncNeeded;
/** Stores the time since a job touched a file. */
QHash<QString, QElapsedTimer> _touchedFiles;
+1 -1
Ver Arquivo
@@ -138,7 +138,7 @@ public:
QString _file;
QString _renameTarget;
Type _type BITFIELD(3);
Direction _direction BITFIELD(3);
Direction _direction BITFIELD(2);
bool _isDirectory BITFIELD(1);
bool _serverHasIgnoredFiles BITFIELD(1);
-1
Ver Arquivo
@@ -131,7 +131,6 @@ 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