Comparar commits
43 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 6a8e718d4a | |||
| 353cd16303 | |||
| 4ac2b764a4 | |||
| 0614cda337 | |||
| 9e895b9b3e | |||
| f501211c63 | |||
| 77ac1b46dd | |||
| 745c21623c | |||
| b91c116518 | |||
| d090a3330a | |||
| d04e7841e2 | |||
| d7a4726544 | |||
| 19d2677db1 | |||
| acb155503b | |||
| 4cb80b08a2 | |||
| cd85b7c6d7 | |||
| 109056e676 | |||
| 51a1bea5de | |||
| 68f99bcc27 | |||
| 7523db354d | |||
| 4919c9e7b1 | |||
| 045498c71a | |||
| 679ac0d26a | |||
| 2e3a3bcf84 | |||
| ad437a49f9 | |||
| 6b2282bf0d | |||
| 42aed56a5a | |||
| ca9ec46253 | |||
| a92eec160a | |||
| cc91c42dfa | |||
| d22d0e7e30 | |||
| 4998303c42 | |||
| ceef2f2d46 | |||
| 8b18600d7e | |||
| 6cc63462b3 | |||
| a1dc4069c9 | |||
| 86846af59d | |||
| 5bfa02602d | |||
| ffac3f6213 | |||
| 4f1feab845 | |||
| f738cfd7fe | |||
| 092c935422 | |||
| 72d8175032 |
+2
-9
@@ -89,7 +89,7 @@ static int _data_cmp(const void *key, const void *data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void csync_create(CSYNC **csync, const char *local, const char *remote) {
|
||||
void csync_create(CSYNC **csync, const char *local) {
|
||||
CSYNC *ctx;
|
||||
size_t len = 0;
|
||||
|
||||
@@ -103,12 +103,6 @@ void csync_create(CSYNC **csync, const char *local, const char *remote) {
|
||||
|
||||
ctx->local.uri = c_strndup(local, len);
|
||||
|
||||
/* remove trailing slashes */
|
||||
len = strlen(remote);
|
||||
while(len > 0 && remote[len - 1] == '/') --len;
|
||||
|
||||
ctx->remote.uri = c_strndup(remote, len);
|
||||
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
ctx->current_fs = NULL;
|
||||
@@ -199,7 +193,7 @@ int csync_update(CSYNC *ctx) {
|
||||
ctx->current = REMOTE_REPLICA;
|
||||
ctx->replica = ctx->remote.type;
|
||||
|
||||
rc = csync_ftw(ctx, ctx->remote.uri, csync_walker, MAX_DEPTH);
|
||||
rc = csync_ftw(ctx, "", csync_walker, MAX_DEPTH);
|
||||
if (rc < 0) {
|
||||
if(ctx->status_code == CSYNC_STATUS_OK) {
|
||||
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_UPDATE_ERROR);
|
||||
@@ -579,7 +573,6 @@ int csync_destroy(CSYNC *ctx) {
|
||||
_csync_clean_ctx(ctx);
|
||||
|
||||
SAFE_FREE(ctx->local.uri);
|
||||
SAFE_FREE(ctx->remote.uri);
|
||||
SAFE_FREE(ctx->error_string);
|
||||
|
||||
#ifdef WITH_ICONV
|
||||
|
||||
+1
-1
@@ -317,7 +317,7 @@ typedef const char* (*csync_checksum_hook) (
|
||||
*
|
||||
* @param csync The context variable to allocate.
|
||||
*/
|
||||
void OCSYNC_EXPORT csync_create(CSYNC **csync, const char *local, const char *remote);
|
||||
void OCSYNC_EXPORT csync_create(CSYNC **csync, const char *local);
|
||||
|
||||
/**
|
||||
* @brief Initialize the file synchronizer.
|
||||
|
||||
@@ -126,7 +126,6 @@ struct csync_s {
|
||||
} local;
|
||||
|
||||
struct {
|
||||
char *uri;
|
||||
c_rbtree_t *tree;
|
||||
enum csync_replica_e type;
|
||||
int read_from_db;
|
||||
|
||||
+21
-73
@@ -56,26 +56,13 @@ static uint64_t _hash_of_file(CSYNC *ctx, const char *file) {
|
||||
|
||||
if( ctx && file ) {
|
||||
path = file;
|
||||
switch (ctx->current) {
|
||||
case LOCAL_REPLICA:
|
||||
if (ctx->current == LOCAL_REPLICA) {
|
||||
if (strlen(path) <= strlen(ctx->local.uri)) {
|
||||
return 0;
|
||||
}
|
||||
path += strlen(ctx->local.uri) + 1;
|
||||
break;
|
||||
case REMOTE_REPLICA:
|
||||
if (strlen(path) <= strlen(ctx->remote.uri)) {
|
||||
return 0;
|
||||
}
|
||||
path += strlen(ctx->remote.uri) + 1;
|
||||
break;
|
||||
default:
|
||||
path = NULL;
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
len = strlen(path);
|
||||
|
||||
h = c_jhash64((uint8_t *) path, len, 0);
|
||||
}
|
||||
return h;
|
||||
@@ -188,25 +175,12 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
}
|
||||
|
||||
path = file;
|
||||
switch (ctx->current) {
|
||||
case LOCAL_REPLICA:
|
||||
if (ctx->current == LOCAL_REPLICA) {
|
||||
if (strlen(path) <= strlen(ctx->local.uri)) {
|
||||
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
path += strlen(ctx->local.uri) + 1;
|
||||
break;
|
||||
case REMOTE_REPLICA:
|
||||
if (strlen(path) <= strlen(ctx->remote.uri)) {
|
||||
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
path += strlen(ctx->remote.uri) + 1;
|
||||
break;
|
||||
default:
|
||||
path = NULL;
|
||||
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = strlen(path);
|
||||
@@ -629,16 +603,7 @@ int csync_walker(CSYNC *ctx, const char *file, const csync_vio_file_stat_t *fs,
|
||||
|
||||
static bool fill_tree_from_db(CSYNC *ctx, const char *uri)
|
||||
{
|
||||
const char *path = NULL;
|
||||
|
||||
if( strlen(uri) < strlen(ctx->remote.uri)+1) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "name does not contain remote uri!");
|
||||
return false;
|
||||
}
|
||||
|
||||
path = uri + strlen(ctx->remote.uri)+1;
|
||||
|
||||
if( csync_statedb_get_below_path(ctx, path) < 0 ) {
|
||||
if( csync_statedb_get_below_path(ctx, uri) < 0 ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "StateDB could not be read!");
|
||||
return false;
|
||||
}
|
||||
@@ -680,12 +645,6 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
|
||||
bool do_read_from_db = (ctx->current == REMOTE_REPLICA && ctx->remote.read_from_db);
|
||||
|
||||
if (uri[0] == '\0') {
|
||||
errno = ENOENT;
|
||||
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
read_from_db = ctx->remote.read_from_db;
|
||||
|
||||
// if the etag of this dir is still the same, its content is restored from the
|
||||
@@ -699,16 +658,7 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
goto done;
|
||||
}
|
||||
|
||||
const char *uri_for_vio = uri;
|
||||
if (ctx->current == REMOTE_REPLICA) {
|
||||
uri_for_vio += strlen(ctx->remote.uri);
|
||||
if (strlen(uri_for_vio) > 0 && uri_for_vio[0] == '/') {
|
||||
uri_for_vio++; // cut leading slash
|
||||
}
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "URI without fuzz for %s is \"%s\"", uri, uri_for_vio);
|
||||
}
|
||||
|
||||
if ((dh = csync_vio_opendir(ctx, uri_for_vio)) == NULL) {
|
||||
if ((dh = csync_vio_opendir(ctx, uri)) == NULL) {
|
||||
if (ctx->abort) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Aborted!");
|
||||
ctx->status_code = CSYNC_STATUS_ABORTED;
|
||||
@@ -781,34 +731,32 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
continue;
|
||||
}
|
||||
|
||||
flen = asprintf(&filename, "%s/%s", uri, d_name);
|
||||
if (flen < 0) {
|
||||
if (uri[0] == '\0') {
|
||||
filename = c_strdup(d_name);
|
||||
flen = strlen(d_name);
|
||||
} else {
|
||||
flen = asprintf(&filename, "%s/%s", uri, d_name);
|
||||
}
|
||||
if (flen < 0 || !filename) {
|
||||
csync_vio_file_stat_destroy(dirent);
|
||||
dirent = NULL;
|
||||
ctx->status_code = CSYNC_STATUS_MEMORY_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Create relative path */
|
||||
switch (ctx->current) {
|
||||
case LOCAL_REPLICA:
|
||||
/* Create relative path: For local replica, we need to remove the base path. */
|
||||
path = filename;
|
||||
if (ctx->current == LOCAL_REPLICA) {
|
||||
ulen = strlen(ctx->local.uri) + 1;
|
||||
break;
|
||||
case REMOTE_REPLICA:
|
||||
ulen = strlen(ctx->remote.uri) + 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (((size_t)flen) < ulen) {
|
||||
csync_vio_file_stat_destroy(dirent);
|
||||
dirent = NULL;
|
||||
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||
goto error;
|
||||
}
|
||||
path += ulen;
|
||||
}
|
||||
|
||||
if (((size_t)flen) < ulen) {
|
||||
csync_vio_file_stat_destroy(dirent);
|
||||
dirent = NULL;
|
||||
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
path = filename + ulen;
|
||||
|
||||
/* skip ".csync_journal.db" and ".csync_journal.db.ctmp" */
|
||||
/* Isn't this done via csync_exclude already? */
|
||||
|
||||
@@ -30,10 +30,7 @@ static void setup(void **state) {
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
*state = csync;
|
||||
}
|
||||
@@ -45,10 +42,7 @@ static void setup_module(void **state) {
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1", "dummy://foo/bar");
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
csync_init(csync);
|
||||
*state = csync;
|
||||
@@ -66,9 +60,6 @@ static void teardown(void **state) {
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("rm -rf /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ static void check_csync_create(void **state)
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
csync_create(&csync, "/tmp/csync1", "/tmp/csync2");
|
||||
csync_create(&csync, "/tmp/csync1");
|
||||
|
||||
rc = csync_destroy(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
static void setup(void **state) {
|
||||
CSYNC *csync;
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
*state = csync;
|
||||
}
|
||||
@@ -41,7 +41,7 @@ static void setup_init(void **state) {
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
rc = csync_exclude_load(EXCLUDE_LIST_FILE, &(csync->excludes));
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
@@ -30,10 +30,7 @@ static void setup(void **state) {
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
*state = csync;
|
||||
}
|
||||
@@ -45,10 +42,7 @@ static void setup_module(void **state) {
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1", "dummy://foo/bar");
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
*state = csync;
|
||||
}
|
||||
@@ -65,9 +59,6 @@ static void teardown(void **state) {
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("rm -rf /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,10 +33,7 @@ static void setup(void **state) {
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
*state = csync;
|
||||
}
|
||||
@@ -53,9 +50,6 @@ static void teardown(void **state) {
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("rm -rf /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ static void setup(void **state) {
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
csync->statedb.file = c_strdup( TESTDB );
|
||||
*state = csync;
|
||||
|
||||
@@ -34,15 +34,11 @@ static void setup(void **state)
|
||||
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("rm -rf /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
csync_init(csync);
|
||||
|
||||
sqlite3 *db = NULL;
|
||||
@@ -106,8 +102,6 @@ static void teardown(void **state) {
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("rm -rf /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = NULL;
|
||||
}
|
||||
|
||||
@@ -91,9 +91,7 @@ static void setup(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
csync_init(csync);
|
||||
|
||||
/* Create a new db with metadata */
|
||||
@@ -122,9 +120,7 @@ static void setup_ftw(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp", "/tmp");
|
||||
csync_create(&csync, "/tmp");
|
||||
csync_init(csync);
|
||||
|
||||
sqlite3 *db = NULL;
|
||||
@@ -162,8 +158,6 @@ static void teardown_rm(void **state) {
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("rm -rf /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
/* create a file stat, caller must free memory */
|
||||
|
||||
@@ -48,7 +48,7 @@ static void setup(void **state)
|
||||
rc = system("rm -rf /tmp/csync_test");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/csync1", "/tmp/csync2");
|
||||
csync_create(&csync, "/tmp/csync1");
|
||||
|
||||
csync->replica = LOCAL_REPLICA;
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ static void setup_testenv(void **state) {
|
||||
statevar *mystate = malloc( sizeof(statevar) );
|
||||
mystate->result = NULL;
|
||||
|
||||
csync_create(&(mystate->csync), "/tmp/csync1", "/tmp/csync2");
|
||||
csync_create(&(mystate->csync), "/tmp/csync1");
|
||||
|
||||
mystate->csync->replica = LOCAL_REPLICA;
|
||||
|
||||
|
||||
+13
-1
@@ -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::
|
||||
@@ -100,7 +108,7 @@ To set up your build environment for development using HomeBrew_:
|
||||
its Common Name as a third parameter (use quotes) to have the package
|
||||
signed automatically.
|
||||
|
||||
.. note:: Contrary to earlier versions, ownCloud 1.7 and later are packaged
|
||||
.. note:: Contrary to earlier versions, ownCloud 1.7 and later are packaged
|
||||
as a ``pkg`` installer. Do not call "make package" at any time when
|
||||
compiling for OS X, as this will build a disk image, and will not
|
||||
work correctly.
|
||||
@@ -249,6 +257,10 @@ To build the most up-to-date version of the client:
|
||||
|
||||
.. note:: Example:: cmake -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5 -DCMAKE_INSTALL_PREFIX=/Users/path/to/client/install/ -D_OPENSSL_LIBDIR=/usr/local/opt/openssl/lib/ -D_OPENSSL_INCLUDEDIR=/usr/local/opt/openssl/include/ -DOPENSSL_INCLUDE_DIR=/usr/local/opt/openssl/include/ -DNO_SHIBBOLETH=1
|
||||
|
||||
.. note:: Example:: cmake -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5 -DCMAKE_INSTALL_PREFIX=/Users/path/to/client/install/ -D_OPENSSL_LIBDIR=/usr/local/opt/openssl/lib/ -D_OPENSSL_INCLUDEDIR=/usr/local/opt/openssl/include/ -D_OPENSSL_VERSION=1.0.2a -DOPENSSL_INCLUDE_DIR=/usr/local/opt/openssl/include/ -DNO_SHIBBOLETH=1
|
||||
|
||||
qtkeychain must be compiled with the same prefix e.g CMAKE_INSTALL_PREFIX=/Users/path/to/client/install/ .
|
||||
|
||||
4. Call ``make``.
|
||||
|
||||
The owncloud binary will appear in the ``bin`` directory.
|
||||
|
||||
@@ -12,7 +12,7 @@ Desktop Sync client enables you to:
|
||||
Your files are always automatically synchronized between your ownCloud server
|
||||
and local PC.
|
||||
|
||||
Because of various technical issues, desktop sync clients older than 1.7 will
|
||||
Because of various technical issues, desktop sync clients older than 2.2.1 will
|
||||
not allowed to connect and sync with the ownCloud 8.1+ server. It is highly
|
||||
recommended to keep your client updated.
|
||||
|
||||
|
||||
@@ -502,6 +502,51 @@ X-GNOME-Autostart-Delay=3
|
||||
# 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
|
||||
|
||||
@@ -49,5 +49,6 @@ target_link_libraries(${OWNCLOUDDOLPHINOVERLAYPLUGIN} KF5::CoreAddons KF5::KIOCo
|
||||
set(OWNCLOUDDOLPHINACTIONPLUGIN ${APPLICATION_EXECUTABLE}dolphinactionplugin)
|
||||
add_library(${OWNCLOUDDOLPHINACTIONPLUGIN} MODULE ownclouddolphinactionplugin.cpp)
|
||||
target_link_libraries(${OWNCLOUDDOLPHINACTIONPLUGIN} KF5::CoreAddons KF5::KIOCore KF5::KIOWidgets ${OWNCLOUDDOLPHINHELPER})
|
||||
install(FILES ownclouddolphinactionplugin.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} RENAME ${OWNCLOUDDOLPHINACTIONPLUGIN}.desktop)
|
||||
configure_file(ownclouddolphinactionplugin.desktop.in ${OWNCLOUDDOLPHINACTIONPLUGIN}.desktop ESCAPE_QUOTES @ONLY)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${OWNCLOUDDOLPHINACTIONPLUGIN}.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR})
|
||||
install(TARGETS ${OWNCLOUDDOLPHINACTIONPLUGIN} DESTINATION ${KDE_INSTALL_PLUGINDIR})
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Type=Service
|
||||
Name=OwncloudAction
|
||||
Name=@APPLICATION_NAME@Action
|
||||
ServiceTypes=KFileItemAction/Plugin
|
||||
MimeType=application/octet-stream;inode/directory;
|
||||
X-KDE-Library=ownclouddolphinactionplugin
|
||||
X-KDE-Library=@APPLICATION_EXECUTABLE@dolphinactionplugin
|
||||
+2
-11
@@ -329,8 +329,7 @@ int main(int argc, char **argv) {
|
||||
if( !options.target_url.contains( account->davPath() )) {
|
||||
options.target_url.append(account->davPath());
|
||||
}
|
||||
if (options.target_url.startsWith("http"))
|
||||
options.target_url.replace(0, 4, "owncloud");
|
||||
|
||||
QUrl url = QUrl::fromUserInput(options.target_url);
|
||||
|
||||
// Order of retrieval attempt (later attempts override earlier ones):
|
||||
@@ -371,14 +370,6 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
// ### ensure URL is free of credentials
|
||||
if (url.userName().isEmpty()) {
|
||||
url.setUserName(user);
|
||||
}
|
||||
if (url.password().isEmpty()) {
|
||||
url.setPassword(password);
|
||||
}
|
||||
|
||||
// take the unmodified url to pass to csync_create()
|
||||
QByteArray remUrl = options.target_url.toUtf8();
|
||||
|
||||
@@ -475,7 +466,7 @@ restart_sync:
|
||||
selectiveSyncFixup(&db, selectiveSyncList);
|
||||
}
|
||||
|
||||
SyncEngine engine(account, options.source_dir, QUrl(options.target_url), folder, &db);
|
||||
SyncEngine engine(account, options.source_dir, folder, &db);
|
||||
engine.setIgnoreHiddenFiles(options.ignoreHiddenFiles);
|
||||
QObject::connect(&engine, SIGNAL(finished(bool)), &app, SLOT(quit()));
|
||||
QObject::connect(&engine, SIGNAL(transmissionProgress(ProgressInfo)), &cmd, SLOT(transmissionProgressSlot()));
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "owncloudsetupwizard.h"
|
||||
#include "creds/abstractcredentials.h"
|
||||
#include "tooltipupdater.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@@ -110,7 +111,7 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent) :
|
||||
|
||||
QAction *syncNowAction = new QAction(this);
|
||||
syncNowAction->setShortcut(QKeySequence(Qt::Key_F6));
|
||||
connect(syncNowAction, SIGNAL(triggered()), SLOT(slotSyncCurrentFolderNow()));
|
||||
connect(syncNowAction, SIGNAL(triggered()), SLOT(slotScheduleCurrentFolder()));
|
||||
addAction(syncNowAction);
|
||||
|
||||
connect(ui->_folderList, SIGNAL(clicked(const QModelIndex &)),
|
||||
@@ -228,6 +229,11 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
|
||||
connect(ac, SIGNAL(triggered(bool)), this, SLOT(doExpand()));
|
||||
}
|
||||
|
||||
if (!folderPaused) {
|
||||
ac = menu->addAction(tr("Force sync now"));
|
||||
connect(ac, SIGNAL(triggered(bool)), this, SLOT(slotForceSyncCurrentFolder()));
|
||||
}
|
||||
|
||||
ac = menu->addAction(folderPaused ? tr("Resume sync") : tr("Pause sync"));
|
||||
connect(ac, SIGNAL(triggered(bool)), this, SLOT(slotEnableCurrentFolder()));
|
||||
|
||||
@@ -300,8 +306,9 @@ void AccountSettings::slotFolderWizardAccepted()
|
||||
tr("<p>Could not create local folder <i>%1</i>.")
|
||||
.arg(QDir::toNativeSeparators(definition.localPath)));
|
||||
return;
|
||||
} else {
|
||||
FileSystem::setFolderMinimumPermissions(definition.localPath);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,7 +468,7 @@ void AccountSettings::slotEnableCurrentFolder()
|
||||
}
|
||||
}
|
||||
|
||||
void AccountSettings::slotSyncCurrentFolderNow()
|
||||
void AccountSettings::slotScheduleCurrentFolder()
|
||||
{
|
||||
QModelIndex selected = ui->_folderList->selectionModel()->currentIndex();
|
||||
if( !selected.isValid() )
|
||||
@@ -472,6 +479,24 @@ void AccountSettings::slotSyncCurrentFolderNow()
|
||||
folderMan->scheduleFolder(folderMan->folder(alias));
|
||||
}
|
||||
|
||||
void AccountSettings::slotForceSyncCurrentFolder()
|
||||
{
|
||||
QModelIndex selected = ui->_folderList->selectionModel()->currentIndex();
|
||||
if( !selected.isValid() )
|
||||
return;
|
||||
QString alias = _model->data( selected, FolderStatusDelegate::FolderAliasRole ).toString();
|
||||
FolderMan *folderMan = FolderMan::instance();
|
||||
|
||||
// Terminate and reschedule any running sync
|
||||
if (Folder* current = folderMan->currentSyncFolder()) {
|
||||
folderMan->terminateSyncProcess();
|
||||
folderMan->scheduleFolder(current);
|
||||
}
|
||||
|
||||
// Insert the selected folder at the front of the queue
|
||||
folderMan->scheduleFolderNext(folderMan->folder(alias));
|
||||
}
|
||||
|
||||
void AccountSettings::slotOpenOC()
|
||||
{
|
||||
if( _OCUrl.isValid() )
|
||||
|
||||
@@ -71,7 +71,8 @@ public slots:
|
||||
protected slots:
|
||||
void slotAddFolder();
|
||||
void slotEnableCurrentFolder();
|
||||
void slotSyncCurrentFolderNow();
|
||||
void slotScheduleCurrentFolder();
|
||||
void slotForceSyncCurrentFolder();
|
||||
void slotRemoveCurrentFolder();
|
||||
void slotOpenCurrentFolder();
|
||||
void slotFolderWizardAccepted();
|
||||
|
||||
@@ -617,7 +617,7 @@ void ActivitySettings::slotCopyToClipboard()
|
||||
message = tr("The sync activity list has been copied to the clipboard.");
|
||||
} else if(idx == 2 ) {
|
||||
// issues Widget
|
||||
message = tr("The list of unsynched items has been copied to the clipboard.");
|
||||
message = tr("The list of unsynced items has been copied to the clipboard.");
|
||||
_protocolWidget->storeSyncIssues(ts);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ Folder::Folder(const FolderDefinition& definition,
|
||||
|
||||
_syncResult.setFolder(_definition.alias);
|
||||
|
||||
_engine.reset(new SyncEngine(_accountState->account(), path(), remoteUrl(), remotePath(), &_journal));
|
||||
_engine.reset(new SyncEngine(_accountState->account(), path(), remotePath(), &_journal));
|
||||
// pass the setting if hidden files are to be ignored, will be read in csync_update
|
||||
_engine->setIgnoreHiddenFiles(_definition.ignoreHiddenFiles);
|
||||
|
||||
@@ -808,6 +808,9 @@ void Folder::slotSyncFinished(bool success)
|
||||
} else if( _syncResult.warnCount() > 0 ) {
|
||||
// there have been warnings on the way.
|
||||
_syncResult.setStatus(SyncResult::Problem);
|
||||
} else if( _definition.paused ) {
|
||||
// Maybe the sync was terminated because the user paused the folder
|
||||
_syncResult.setStatus(SyncResult::Paused);
|
||||
} else {
|
||||
_syncResult.setStatus(SyncResult::Success);
|
||||
}
|
||||
|
||||
+27
-8
@@ -520,6 +520,26 @@ void FolderMan::scheduleFolder( Folder *f )
|
||||
startScheduledSyncSoon();
|
||||
}
|
||||
|
||||
void FolderMan::scheduleFolderNext(Folder* f)
|
||||
{
|
||||
auto alias = f->alias();
|
||||
qDebug() << "Schedule folder " << alias << " to sync! Front-of-queue.";
|
||||
|
||||
if( !f->canSync() ) {
|
||||
qDebug() << "Folder is not ready to sync, not scheduled!";
|
||||
return;
|
||||
}
|
||||
|
||||
_scheduledFolders.removeAll(f);
|
||||
|
||||
f->prepareToSync();
|
||||
emit folderSyncStateChange(f);
|
||||
_scheduledFolders.prepend(f);
|
||||
emit scheduleQueueChanged();
|
||||
|
||||
startScheduledSyncSoon();
|
||||
}
|
||||
|
||||
void FolderMan::slotScheduleETagJob(const QString &/*alias*/, RequestEtagJob *job)
|
||||
{
|
||||
QObject::connect(job, SIGNAL(destroyed(QObject*)), this, SLOT(slotEtagJobDestroyed(QObject*)));
|
||||
@@ -673,12 +693,11 @@ void FolderMan::slotStartScheduledFolderSync()
|
||||
}
|
||||
|
||||
// Find the first folder in the queue that can be synced.
|
||||
Folder* f = 0;
|
||||
Folder* folder = 0;
|
||||
while( !_scheduledFolders.isEmpty() ) {
|
||||
f = _scheduledFolders.dequeue();
|
||||
Q_ASSERT(f);
|
||||
|
||||
if( f->canSync() ) {
|
||||
Folder* g = _scheduledFolders.dequeue();
|
||||
if( g->canSync() ) {
|
||||
folder = g;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -686,9 +705,9 @@ void FolderMan::slotStartScheduledFolderSync()
|
||||
emit scheduleQueueChanged();
|
||||
|
||||
// Start syncing this folder!
|
||||
if( f ) {
|
||||
_currentSyncFolder = f;
|
||||
f->startSync( QStringList() );
|
||||
if( folder ) {
|
||||
_currentSyncFolder = folder;
|
||||
folder->startSync( QStringList() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-6
@@ -161,12 +161,22 @@ public:
|
||||
/** Queues a folder for syncing. */
|
||||
void scheduleFolder(Folder*);
|
||||
|
||||
/** Puts a folder in the very front of the queue. */
|
||||
void scheduleFolderNext(Folder*);
|
||||
|
||||
/** Queues all folders for syncing. */
|
||||
void scheduleAllFolders();
|
||||
|
||||
void setDirtyProxy(bool value = true);
|
||||
void setDirtyNetworkLimits();
|
||||
|
||||
/**
|
||||
* Terminates the current folder sync.
|
||||
*
|
||||
* It does not switch the folder to paused state.
|
||||
*/
|
||||
void terminateSyncProcess();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* signal to indicate a folder has changed its sync state.
|
||||
@@ -247,12 +257,6 @@ private slots:
|
||||
void slotScheduleFolderByTime();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Terminates the current folder sync.
|
||||
*
|
||||
* It does not switch the folder to paused state.
|
||||
*/
|
||||
void terminateSyncProcess();
|
||||
|
||||
/** Adds a new folder, does not add it to the account settings and
|
||||
* does not set an account on the new folder.
|
||||
|
||||
@@ -806,25 +806,6 @@ void FolderStatusModel::slotApplySelectiveSync()
|
||||
resetFolders();
|
||||
}
|
||||
|
||||
static QString shortenFilename( Folder *f, const QString& file )
|
||||
{
|
||||
// strip off the server prefix from the file name
|
||||
QString shortFile(file);
|
||||
if( shortFile.isEmpty() ) {
|
||||
return QString::null;
|
||||
}
|
||||
|
||||
if(shortFile.startsWith(QLatin1String("ownclouds://")) ||
|
||||
shortFile.startsWith(QLatin1String("owncloud://")) ) {
|
||||
// rip off the whole ownCloud URL.
|
||||
if( f ) {
|
||||
QString remotePathUrl = f->remoteUrl().toString();
|
||||
shortFile.remove(Utility::toCSyncScheme(remotePathUrl));
|
||||
}
|
||||
}
|
||||
return shortFile;
|
||||
}
|
||||
|
||||
void FolderStatusModel::slotSetProgress(const ProgressInfo &progress)
|
||||
{
|
||||
auto par = qobject_cast<QWidget*>(QObject::parent());
|
||||
@@ -898,7 +879,7 @@ void FolderStatusModel::slotSetProgress(const ProgressInfo &progress)
|
||||
curItemProgress = curItem._size;
|
||||
}
|
||||
|
||||
QString itemFileName = shortenFilename(f, curItem._file);
|
||||
QString itemFileName = curItem._file;
|
||||
QString kindString = Progress::asActionString(curItem);
|
||||
|
||||
QString fileProgressString;
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "sslerrordialog.h"
|
||||
#include "accountmanager.h"
|
||||
#include "clientproxy.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
#include "creds/credentialsfactory.h"
|
||||
#include "creds/abstractcredentials.h"
|
||||
@@ -202,10 +203,34 @@ void OwncloudSetupWizard::slotOwnCloudFoundAuth(const QUrl& url, const QVariantM
|
||||
|
||||
void OwncloudSetupWizard::slotNoOwnCloudFoundAuth(QNetworkReply *reply)
|
||||
{
|
||||
_ocWizard->displayError(tr("Failed to connect to %1 at %2:<br/>%3")
|
||||
.arg(Theme::instance()->appNameGUI(),
|
||||
reply->url().toString(),
|
||||
reply->errorString()), checkDowngradeAdvised(reply));
|
||||
int resultCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
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")
|
||||
.arg(Theme::instance()->appNameGUI(),
|
||||
reply->url().toString(),
|
||||
reply->errorString());
|
||||
bool isDowngradeAdvised = checkDowngradeAdvised(reply);
|
||||
|
||||
// If a client cert is needed, nginx sends:
|
||||
// 400 "<html>\r\n<head><title>400 No required SSL certificate was sent</title></head>\r\n<body bgcolor=\"white\">\r\n<center><h1>400 Bad Request</h1></center>\r\n<center>No required SSL certificate was sent</center>\r\n<hr><center>nginx/1.10.0</center>\r\n</body>\r\n</html>\r\n"
|
||||
// If the IP needs to be added as "trusted domain" in oC, oC sends:
|
||||
// https://gist.github.com/guruz/ab6d11df1873c2ad3932180de92e7d82
|
||||
if (resultCode != 200 && contentType.startsWith("text/")) {
|
||||
// FIXME: Synchronous dialogs are not so nice because of event loop recursion
|
||||
// (we already create a dialog further below)
|
||||
QString serverError = reply->peek(1024*20);
|
||||
qDebug() << serverError;
|
||||
QMessageBox messageBox(_ocWizard);
|
||||
messageBox.setText(serverError);
|
||||
messageBox.addButton(QMessageBox::Ok);
|
||||
messageBox.setTextFormat(Qt::RichText);
|
||||
messageBox.exec();
|
||||
}
|
||||
|
||||
// Displays message inside wizard and possibly also another message box
|
||||
_ocWizard->displayError(msg, isDowngradeAdvised);
|
||||
|
||||
// Allow the credentials dialog to pop up again for the same URL.
|
||||
// Maybe the user just clicked 'Cancel' by accident or changed his mind.
|
||||
@@ -340,8 +365,8 @@ void OwncloudSetupWizard::slotCreateLocalAndRemoteFolders(const QString& localFo
|
||||
} else {
|
||||
QString res = tr("Creating local sync folder %1...").arg(localFolder);
|
||||
if( fi.mkpath( localFolder ) ) {
|
||||
FileSystem::setFolderMinimumPermissions(localFolder);
|
||||
Utility::setupFavLink( localFolder );
|
||||
// FIXME: Create a local sync folder.
|
||||
res += tr("ok");
|
||||
} else {
|
||||
res += tr("failed.");
|
||||
|
||||
@@ -256,6 +256,7 @@ void OwncloudSetupPage::setErrorString( const QString& err, bool retryHTTPonly )
|
||||
|
||||
OwncloudConnectionMethodDialog dialog;
|
||||
dialog.setUrl(url);
|
||||
// FIXME: Synchronous dialogs are not so nice because of event loop recursion
|
||||
int retVal = dialog.exec();
|
||||
|
||||
switch (retVal) {
|
||||
|
||||
@@ -57,6 +57,11 @@ Account::~Account()
|
||||
|
||||
QString Account::davPath() const
|
||||
{
|
||||
if (capabilities().chunkingNg()) {
|
||||
// The chunking-ng means the server prefer to use the new webdav URL
|
||||
return QLatin1String("/remote.php/dav/files/") + davUser() + QLatin1Char('/');
|
||||
}
|
||||
|
||||
// make sure to have a trailing slash
|
||||
if( !_davPath.endsWith('/') ) {
|
||||
QString dp(_davPath);
|
||||
@@ -76,19 +81,19 @@ AccountPtr Account::sharedFromThis()
|
||||
return _sharedThis.toStrongRef();
|
||||
}
|
||||
|
||||
QString Account::user() const
|
||||
QString Account::davUser() const
|
||||
{
|
||||
return _user.isEmpty() ? _credentials->user() : _user;
|
||||
return _davUser.isEmpty() ? _credentials->user() : _davUser;
|
||||
}
|
||||
|
||||
void Account::setUser(const QString &user)
|
||||
void Account::setDavUser(const QString &newDavUser)
|
||||
{
|
||||
_user = user;
|
||||
_davUser = newDavUser;
|
||||
}
|
||||
|
||||
QString Account::displayName() const
|
||||
{
|
||||
QString dn = QString("%1@%2").arg(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(':'));
|
||||
|
||||
@@ -69,9 +69,14 @@ public:
|
||||
|
||||
AccountPtr sharedFromThis();
|
||||
|
||||
/// The user that can be used in dav url
|
||||
QString user() const;
|
||||
void setUser(const QString &user);
|
||||
/**
|
||||
* The user that can be used in dav url.
|
||||
*
|
||||
* This can very well be different frome the login user that's
|
||||
* stored in credentials()->user().
|
||||
*/
|
||||
QString davUser() const;
|
||||
void setDavUser(const QString &newDavUser);
|
||||
|
||||
/// The name of the account as shown in the toolbar
|
||||
QString displayName() const;
|
||||
@@ -203,7 +208,7 @@ private:
|
||||
|
||||
QWeakPointer<Account> _sharedThis;
|
||||
QString _id;
|
||||
QString _user;
|
||||
QString _davUser;
|
||||
QMap<QString, QVariant> _settingsMap;
|
||||
QUrl _url;
|
||||
QList<QSslCertificate> _approvedCerts;
|
||||
|
||||
@@ -110,6 +110,9 @@ QByteArray Capabilities::uploadChecksumType() const
|
||||
|
||||
bool Capabilities::chunkingNg() const
|
||||
{
|
||||
static const auto chunkng = qgetenv("OWNCLOUD_CHUNKING_NG");
|
||||
if (chunkng == "0") return false;
|
||||
if (chunkng == "1") return true;
|
||||
return _capabilities["dav"].toMap()["chunking"].toByteArray() >= "1.0";
|
||||
}
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@ void ConnectionValidator::slotUserFetched(const QVariantMap &json)
|
||||
{
|
||||
QString user = json.value("ocs").toMap().value("data").toMap().value("id").toString();
|
||||
if (!user.isEmpty()) {
|
||||
_account->setUser(user);
|
||||
_account->setDavUser(user);
|
||||
}
|
||||
reportResult(Connected);
|
||||
}
|
||||
|
||||
@@ -146,6 +146,17 @@ void FileSystem::setFileReadOnly(const QString& filename, bool readonly)
|
||||
file.setPermissions(permissions);
|
||||
}
|
||||
|
||||
void FileSystem::setFolderMinimumPermissions(const QString& filename)
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
QFile::Permissions perm = QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner;
|
||||
QFile file(filename);
|
||||
file.setPermissions(perm);
|
||||
#else
|
||||
Q_UNUSED(filename);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void FileSystem::setFileReadOnlyWeak(const QString& filename, bool readonly)
|
||||
{
|
||||
|
||||
@@ -67,6 +67,12 @@ void OWNCLOUDSYNC_EXPORT setFileReadOnly(const QString& filename, bool readonly)
|
||||
*/
|
||||
void OWNCLOUDSYNC_EXPORT setFileReadOnlyWeak(const QString& filename, bool readonly);
|
||||
|
||||
/**
|
||||
* @brief Try to set permissions so that other users on the local machine can not
|
||||
* go into the folder.
|
||||
*/
|
||||
void OWNCLOUDSYNC_EXPORT setFolderMinimumPermissions(const QString& filename);
|
||||
|
||||
/** convert a "normal" windows path into a path that can be 32k chars long. */
|
||||
QString OWNCLOUDSYNC_EXPORT longWinPath( const QString& inpath );
|
||||
|
||||
|
||||
@@ -463,7 +463,7 @@ bool CheckServerJob::finished()
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
QByteArray body = reply()->readAll();
|
||||
QByteArray body = reply()->peek(4*1024);
|
||||
int httpStatus = reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if( body.isEmpty() || httpStatus != 200) {
|
||||
qDebug() << "error: status.php replied " << httpStatus << body;
|
||||
|
||||
@@ -108,6 +108,11 @@ static bool blacklistCheck(SyncJournalDb* journal, const SyncFileItem& item)
|
||||
|
||||
if (newEntry.isValid()) {
|
||||
journal->updateErrorBlacklistEntry(newEntry);
|
||||
// Also clear upload info if any so we don't resume from the same transfer-id if there was too many failures (#5344)
|
||||
// (maybe the reason is that the state for this transfer id is broken on the server.)
|
||||
if (newEntry._retryCount > 3) {
|
||||
journal->setUploadInfo(item._file, SyncJournalDb::UploadInfo());
|
||||
}
|
||||
} else if (oldEntry.isValid()) {
|
||||
journal->wipeErrorBlacklistEntry(item._file);
|
||||
}
|
||||
@@ -271,9 +276,7 @@ PropagateItemJob* OwncloudPropagator::createJob(const SyncFileItemPtr &item) {
|
||||
return job;
|
||||
} else {
|
||||
PropagateUploadFileCommon *job = 0;
|
||||
static const auto chunkng = qgetenv("OWNCLOUD_CHUNKING_NG");
|
||||
if (item->_size > chunkSize()
|
||||
&& (account()->capabilities().chunkingNg() || chunkng == "1") && chunkng != "0") {
|
||||
if (item->_size > chunkSize() && account()->capabilities().chunkingNg()) {
|
||||
job = new PropagateUploadFileNG(this, item);
|
||||
} else {
|
||||
job = new PropagateUploadFileV1(this, item);
|
||||
@@ -314,7 +317,7 @@ void OwncloudPropagator::start(const SyncFileItemVector& items)
|
||||
|
||||
if (!removedDirectory.isEmpty() && item->_file.startsWith(removedDirectory)) {
|
||||
// this is an item in a directory which is going to be removed.
|
||||
PropagateDirectory *delDirJob = dynamic_cast<PropagateDirectory*>(directoriesToRemove.first());
|
||||
PropagateDirectory *delDirJob = qobject_cast<PropagateDirectory*>(directoriesToRemove.first());
|
||||
|
||||
if (item->_instruction == CSYNC_INSTRUCTION_REMOVE) {
|
||||
// already taken care of. (by the removal of the parent directory)
|
||||
@@ -398,9 +401,16 @@ void OwncloudPropagator::start(const SyncFileItemVector& items)
|
||||
}
|
||||
|
||||
foreach(PropagatorJob* it, directoriesToRemove) {
|
||||
// ensure that these items will go last in the root folder and append
|
||||
it->setLastOutJobPriority();
|
||||
_rootJob->append(it);
|
||||
}
|
||||
|
||||
// at this point, all priority values for items in the folders should be set
|
||||
// update priority attribute for folders containing these items
|
||||
// this will move _containerJobs to _subJobs updating their evaluation attributes
|
||||
_rootJob->updateJobPriorityAttributeValues();
|
||||
|
||||
connect(_rootJob.data(), SIGNAL(itemCompleted(const SyncFileItem &, const PropagatorJob &)),
|
||||
this, SIGNAL(itemCompleted(const SyncFileItem &, const PropagatorJob &)));
|
||||
connect(_rootJob.data(), SIGNAL(progress(const SyncFileItem &,quint64)), this, SIGNAL(progress(const SyncFileItem &,quint64)));
|
||||
@@ -412,10 +422,12 @@ void OwncloudPropagator::start(const SyncFileItemVector& items)
|
||||
QTimer::singleShot(0, this, SLOT(scheduleNextJob()));
|
||||
}
|
||||
|
||||
// ownCloud server < 7.0 did not had permissions so we need some other euristics
|
||||
// to detect wrong doing in a Shared directory
|
||||
bool OwncloudPropagator::isInSharedDirectory(const QString& file)
|
||||
{
|
||||
bool re = false;
|
||||
if( _remoteDir.contains( _account->davPath() + QLatin1String("Shared") ) ) {
|
||||
if( _remoteFolder.startsWith( QLatin1String("Shared") ) ) {
|
||||
// The Shared directory is synced as its own sync connection
|
||||
re = true;
|
||||
} else {
|
||||
@@ -569,20 +581,52 @@ OwncloudPropagator::DiskSpaceResult OwncloudPropagator::diskSpaceCheck() const
|
||||
|
||||
// ================================================================================
|
||||
|
||||
void PropagateDirectory::insertItemByPriority(PropagatorJob *subJob){
|
||||
// if job is prioritised, take priority into account, otherwise use modification time
|
||||
int priority = subJob->getJobPriorityAttributeValue();
|
||||
|
||||
if(subJob->_priority == JobPriority::NormalPriority){
|
||||
// jobs are prioritised by timestamp, thus higher timestamp, higher the priority
|
||||
// QMultiMap is sorted in increasing order, so substract from max possible quint64
|
||||
int modificationTimestamp = subJob->getJobPriorityAttributeValue();
|
||||
priority = std::numeric_limits<quint64>::max() - modificationTimestamp;
|
||||
}
|
||||
|
||||
_subJobs.insertMulti(priority, subJob);
|
||||
}
|
||||
|
||||
void PropagateDirectory::updateJobPriorityAttributeValues()
|
||||
{
|
||||
// This uses recursion to perform Depth-First Traversal of the directories with changes trees
|
||||
// If the given (this) directory contains _containerJobs, it will call updateJob on that child dir job, otherwise does nothing
|
||||
|
||||
//this will get the _container jobs within this parent directory and iterate over them
|
||||
QMutableVectorIterator<PropagatorJob *> containerJobsIterator(_containerJobs);
|
||||
while (containerJobsIterator.hasNext()) {
|
||||
//take next Container Job
|
||||
PropagatorJob * subJob = containerJobsIterator.next();
|
||||
|
||||
//ascend to its child folders to update their priorities
|
||||
subJob->updateJobPriorityAttributeValues();
|
||||
|
||||
//at this point, all child folders are updated, add job to _subJobs and remote job from _containerJobs
|
||||
insertItemByPriority(subJob);
|
||||
containerJobsIterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
PropagatorJob::JobParallelism PropagateDirectory::parallelism()
|
||||
{
|
||||
// If any of the non-finished sub jobs is not parallel, we have to wait
|
||||
|
||||
// FIXME! we should probably cache this result
|
||||
|
||||
if (_firstJob && _firstJob->_state != Finished) {
|
||||
if (_firstJob->parallelism() != FullParallelism)
|
||||
return WaitForFinished;
|
||||
}
|
||||
|
||||
// FIXME: use the cached value of finished job
|
||||
for (int i = 0; i < _subJobs.count(); ++i) {
|
||||
if (_subJobs.at(i)->_state != Finished && _subJobs.at(i)->parallelism() != FullParallelism) {
|
||||
QMapIterator<quint64, PropagatorJob *> subJobsIterator(_subJobs);
|
||||
while (subJobsIterator.hasNext()) {
|
||||
subJobsIterator.next();
|
||||
if (subJobsIterator.value()->_state != Finished && subJobsIterator.value()->parallelism() != FullParallelism) {
|
||||
return WaitForFinished;
|
||||
}
|
||||
}
|
||||
@@ -599,6 +643,11 @@ bool PropagateDirectory::scheduleNextJob()
|
||||
if (_state == NotYetStarted) {
|
||||
_state = Running;
|
||||
|
||||
// at the begining of the Directory Job, update expected number of Jobs to be synced
|
||||
_totalJobs = _subJobs.count();
|
||||
if (_firstJob)
|
||||
_totalJobs++;
|
||||
|
||||
if (!_firstJob && _subJobs.isEmpty()) {
|
||||
finalize();
|
||||
return true;
|
||||
@@ -613,30 +662,27 @@ bool PropagateDirectory::scheduleNextJob()
|
||||
return false;
|
||||
}
|
||||
|
||||
// cache the value of first unfinished subjob
|
||||
bool stopAtDirectory = false;
|
||||
int i = _firstUnfinishedSubJob;
|
||||
int subJobsCount = _subJobs.count();
|
||||
while (i < subJobsCount && _subJobs.at(i)->_state == Finished) {
|
||||
_firstUnfinishedSubJob = ++i;
|
||||
}
|
||||
|
||||
for (int i = _firstUnfinishedSubJob; i < subJobsCount; ++i) {
|
||||
if (_subJobs.at(i)->_state == Finished) {
|
||||
QMutableMapIterator<quint64, PropagatorJob *> subJobsIterator(_subJobs);
|
||||
while (subJobsIterator.hasNext()) {
|
||||
subJobsIterator.next();
|
||||
if (subJobsIterator.value()->_state == Finished) {
|
||||
subJobsIterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stopAtDirectory && qobject_cast<PropagateDirectory*>(_subJobs.at(i))) {
|
||||
if (stopAtDirectory && qobject_cast<PropagateDirectory*>(subJobsIterator.value())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (possiblyRunNextJob(_subJobs.at(i))) {
|
||||
if (possiblyRunNextJob(subJobsIterator.value())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Q_ASSERT(_subJobs.at(i)->_state == Running);
|
||||
Q_ASSERT(subJobsIterator.value()->_state == Running);
|
||||
|
||||
auto paral = _subJobs.at(i)->parallelism();
|
||||
auto paral = subJobsIterator.value()->parallelism();
|
||||
if (paral == WaitForFinished) {
|
||||
return false;
|
||||
}
|
||||
@@ -661,14 +707,9 @@ void PropagateDirectory::slotSubJobFinished(SyncFileItem::Status status)
|
||||
_runningNow--;
|
||||
_jobsFinished++;
|
||||
|
||||
int totalJobs = _subJobs.count();
|
||||
if (_firstJob) {
|
||||
totalJobs++;
|
||||
}
|
||||
|
||||
// We finished processing all the jobs
|
||||
// check if we finished
|
||||
if (_jobsFinished >= totalJobs) {
|
||||
if (_jobsFinished >= _totalJobs) {
|
||||
Q_ASSERT(!_runningNow); // how can we be finished if there are still jobs running now
|
||||
finalize();
|
||||
} else {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#ifndef OWNCLOUDPROPAGATOR_H
|
||||
#define OWNCLOUDPROPAGATOR_H
|
||||
|
||||
#include <limits>
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
@@ -24,12 +25,12 @@
|
||||
#include <QPointer>
|
||||
#include <QIODevice>
|
||||
#include <QMutex>
|
||||
#include <QDebug>
|
||||
|
||||
#include "syncfileitem.h"
|
||||
#include "syncjournaldb.h"
|
||||
#include "bandwidthmanager.h"
|
||||
#include "accountfwd.h"
|
||||
|
||||
namespace OCC {
|
||||
|
||||
/** Free disk space threshold below which syncs will abort and not even start.
|
||||
@@ -60,7 +61,32 @@ protected:
|
||||
OwncloudPropagator *_propagator;
|
||||
|
||||
public:
|
||||
explicit PropagatorJob(OwncloudPropagator* propagator) : _propagator(propagator), _state(NotYetStarted) {}
|
||||
enum JobPriority {
|
||||
/**
|
||||
* Jobs are prioritized, so that they will be executed unconditionaly first,
|
||||
* according to insertion order withing the items of the same priority
|
||||
*/
|
||||
FirstOutPriority,
|
||||
|
||||
/**
|
||||
* Jobs are prioritized, so that they will be executed unconditionaly last,
|
||||
* according to insertion order withing the items of the same priority
|
||||
*/
|
||||
LastOutPriority,
|
||||
|
||||
/** Jobs are normaly prioritized, so that they will be executed according to some evaluation attribute represented by integer*/
|
||||
NormalPriority,
|
||||
|
||||
/** To contruct predicate for this Priority, all subitem has to be classified and contenerised */
|
||||
ContainerItemsPriority,
|
||||
};
|
||||
|
||||
explicit PropagatorJob(OwncloudPropagator* propagator, JobPriority priority) : _propagator(propagator), _priority(priority), _state(NotYetStarted) {}
|
||||
|
||||
/*
|
||||
* Keeps track of the priority of the object
|
||||
*/
|
||||
JobPriority _priority;
|
||||
|
||||
enum JobState {
|
||||
NotYetStarted,
|
||||
@@ -100,6 +126,41 @@ public:
|
||||
*/
|
||||
virtual qint64 committedDiskSpace() const { return 0; }
|
||||
|
||||
/**
|
||||
* Returns job priority predicate value according to LastOut or FirstOut priority
|
||||
* or method can be overriden to return a specific priority attribute value
|
||||
*
|
||||
* FirstOut priority will return minimum value for quint64 since QMultiMap keys are sorted in increasing order
|
||||
*
|
||||
* This method returns 0 in case of error
|
||||
*/
|
||||
virtual quint64 getJobPriorityAttributeValue() const {
|
||||
if (_priority==JobPriority::FirstOutPriority) {
|
||||
return std::numeric_limits<quint64>::min();
|
||||
} else if (_priority==JobPriority::LastOutPriority){
|
||||
return std::numeric_limits<quint64>::max();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates job priorities for the given job
|
||||
*/
|
||||
virtual void updateJobPriorityAttributeValues() {}
|
||||
|
||||
/**
|
||||
* Enforces FirstOut job priority.
|
||||
* NOTE: This has to be set before item is being added to _subJobs queue to be propagated!
|
||||
*/
|
||||
virtual void setFirstOutJobPriority() { _priority = JobPriority::FirstOutPriority; }
|
||||
|
||||
/**
|
||||
* Enforces LastOut job priority
|
||||
* NOTE: This has to be set before item is being added to _subJobs queue to be propagated!
|
||||
*/
|
||||
virtual void setLastOutJobPriority() { _priority = JobPriority::LastOutPriority; }
|
||||
|
||||
public slots:
|
||||
virtual void abort() {}
|
||||
|
||||
@@ -158,14 +219,15 @@ private:
|
||||
QScopedPointer<PropagateItemJob> _restoreJob;
|
||||
|
||||
public:
|
||||
PropagateItemJob(OwncloudPropagator* propagator, const SyncFileItemPtr &item)
|
||||
: PropagatorJob(propagator), _item(item) {}
|
||||
PropagateItemJob(OwncloudPropagator* propagator, const SyncFileItemPtr &item, JobPriority priority)
|
||||
: PropagatorJob(propagator, priority), _item(item) {}
|
||||
|
||||
bool scheduleNextJob() Q_DECL_OVERRIDE {
|
||||
if (_state != NotYetStarted) {
|
||||
return false;
|
||||
}
|
||||
_state = Running;
|
||||
qDebug() << "Modification Time - Priority" << _item->_modtime << "Item" << _item->_file;
|
||||
QMetaObject::invokeMethod(this, "start"); // We could be in a different thread (neon jobs)
|
||||
return true;
|
||||
}
|
||||
@@ -187,27 +249,45 @@ public:
|
||||
// e.g: create the directory
|
||||
QScopedPointer<PropagateItemJob>_firstJob;
|
||||
|
||||
// all the sub files or sub directories.
|
||||
QVector<PropagatorJob *> _subJobs;
|
||||
/*
|
||||
* All the sub files or sub directories. This map has to be updated with _containerJobs
|
||||
* QMultiMap is ordered by the key value, or in case of equal keys (e.g 0) by insertion order.
|
||||
* <quint64 predicate, PropagatorJob * job>, where predicate is obtained by call to getJobPredicateValue()
|
||||
*/
|
||||
QMultiMap<quint64, PropagatorJob *> _subJobs;
|
||||
|
||||
/*
|
||||
* This vector is just temporary structure used to keep the "container" jobs like directory job.
|
||||
* After the updateJobPredicateValues() is called on this directories, these container jobs will be inserted
|
||||
* to _subJobs queue. Note: This has to be called after all items are added to the _subJobs for whole the sync!
|
||||
*/
|
||||
QVector<PropagatorJob *> _containerJobs;
|
||||
|
||||
SyncFileItemPtr _item;
|
||||
|
||||
int _jobsFinished; // number of jobs that have completed
|
||||
int _totalJobs; // number of jobs that will be defined to be synced
|
||||
int _runningNow; // number of subJobs running right now
|
||||
SyncFileItem::Status _hasError; // NoStatus, or NormalError / SoftError if there was an error
|
||||
int _firstUnfinishedSubJob;
|
||||
|
||||
explicit PropagateDirectory(OwncloudPropagator *propagator, const SyncFileItemPtr &item = SyncFileItemPtr(new SyncFileItem))
|
||||
: PropagatorJob(propagator)
|
||||
, _firstJob(0), _item(item), _jobsFinished(0), _runningNow(0), _hasError(SyncFileItem::NoStatus), _firstUnfinishedSubJob(0)
|
||||
: PropagatorJob(propagator, JobPriority::ContainerItemsPriority)
|
||||
, _firstJob(0), _item(item), _jobsFinished(0), _totalJobs(0), _runningNow(0), _hasError(SyncFileItem::NoStatus)
|
||||
{ }
|
||||
|
||||
virtual ~PropagateDirectory() {
|
||||
qDeleteAll(_subJobs);
|
||||
qDeleteAll(_containerJobs);
|
||||
}
|
||||
|
||||
void append(PropagatorJob *subJob) {
|
||||
_subJobs.append(subJob);
|
||||
// we do not yet have all items in all the folders, so add it temporarly to _containerJobs and move to _subJobs
|
||||
// directly before start of the sync (after updating priority attributes)
|
||||
if(subJob->_priority == JobPriority::ContainerItemsPriority){
|
||||
_containerJobs.append(subJob);
|
||||
} else {
|
||||
insertItemByPriority(subJob);
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool scheduleNextJob() Q_DECL_OVERRIDE;
|
||||
@@ -227,6 +307,21 @@ public:
|
||||
|
||||
qint64 committedDiskSpace() const Q_DECL_OVERRIDE;
|
||||
|
||||
// this item is prioritized normaly, so get priority by its sub items highest modification timestamp (most recent modification)
|
||||
// because _subJobs are already sorted, take first job priority attribute
|
||||
quint64 getJobPriorityAttributeValue() const Q_DECL_OVERRIDE {
|
||||
if (_priority == JobPriority::ContainerItemsPriority && !_subJobs.empty())
|
||||
return _subJobs.first()->getJobPriorityAttributeValue();
|
||||
|
||||
// subJobs empty or forced priority, return priority of folder itself
|
||||
return PropagatorJob::getJobPriorityAttributeValue();
|
||||
}
|
||||
|
||||
// this method should decide about prioritising single items during their insert
|
||||
void insertItemByPriority(PropagatorJob *subJob);
|
||||
|
||||
// this method should decide about prioritising container items during their insert
|
||||
void updateJobPriorityAttributeValues();
|
||||
private slots:
|
||||
bool possiblyRunNextJob(PropagatorJob *next) {
|
||||
if (next->_state == NotYetStarted) {
|
||||
@@ -252,7 +347,7 @@ class PropagateIgnoreJob : public PropagateItemJob {
|
||||
Q_OBJECT
|
||||
public:
|
||||
PropagateIgnoreJob(OwncloudPropagator* propagator,const SyncFileItemPtr& item)
|
||||
: PropagateItemJob(propagator, item) {}
|
||||
: PropagateItemJob(propagator, item, JobPriority::FirstOutPriority) {}
|
||||
void start() Q_DECL_OVERRIDE {
|
||||
SyncFileItem::Status status = _item->_status;
|
||||
done(status == SyncFileItem::NoStatus ? SyncFileItem::FileIgnored : status, _item->_errorString);
|
||||
@@ -267,8 +362,7 @@ class OwncloudPropagator : public QObject {
|
||||
|
||||
public:
|
||||
const QString _localDir; // absolute path to the local directory. ends with '/'
|
||||
const QString _remoteDir; // path to the root of the remote. ends with '/' (include WebDAV path)
|
||||
const QString _remoteFolder; // folder. (same as remoteDir but without the WebDAV path)
|
||||
const QString _remoteFolder; // remote folder, ends with '/'
|
||||
|
||||
SyncJournalDb * const _journal;
|
||||
bool _finishedEmited; // used to ensure that finished is only emitted once
|
||||
@@ -276,10 +370,8 @@ public:
|
||||
|
||||
public:
|
||||
OwncloudPropagator(AccountPtr account, const QString &localDir,
|
||||
const QString &remoteDir, const QString &remoteFolder,
|
||||
SyncJournalDb *progressDb)
|
||||
const QString &remoteFolder, SyncJournalDb *progressDb)
|
||||
: _localDir((localDir.endsWith(QChar('/'))) ? localDir : localDir+'/' )
|
||||
, _remoteDir((remoteDir.endsWith(QChar('/'))) ? remoteDir : remoteDir+'/' )
|
||||
, _remoteFolder((remoteFolder.endsWith(QChar('/'))) ? remoteFolder : remoteFolder+'/' )
|
||||
, _journal(progressDb)
|
||||
, _finishedEmited(false)
|
||||
|
||||
@@ -110,13 +110,16 @@ class PropagateDownloadFile : public PropagateItemJob {
|
||||
Q_OBJECT
|
||||
public:
|
||||
PropagateDownloadFile(OwncloudPropagator* propagator,const SyncFileItemPtr& item)
|
||||
: PropagateItemJob(propagator, item), _resumeStart(0), _downloadProgress(0), _deleteExisting(false) {}
|
||||
: PropagateItemJob(propagator, item, JobPriority::NormalPriority), _resumeStart(0), _downloadProgress(0), _deleteExisting(false) {}
|
||||
void start() Q_DECL_OVERRIDE;
|
||||
qint64 committedDiskSpace() const Q_DECL_OVERRIDE;
|
||||
|
||||
// We think it might finish quickly because it is a small file.
|
||||
bool isLikelyFinishedQuickly() Q_DECL_OVERRIDE { return _item->_size < 100*1024; }
|
||||
|
||||
// this item is prioritized normaly, so get priority by its modification time
|
||||
quint64 getJobPriorityAttributeValue() const Q_DECL_OVERRIDE { return _item->_modtime; }
|
||||
|
||||
/**
|
||||
* Whether an existing folder with the same name may be deleted before
|
||||
* the download.
|
||||
|
||||
@@ -48,7 +48,7 @@ class PropagateRemoteDelete : public PropagateItemJob {
|
||||
QPointer<DeleteJob> _job;
|
||||
public:
|
||||
PropagateRemoteDelete (OwncloudPropagator* propagator,const SyncFileItemPtr& item)
|
||||
: PropagateItemJob(propagator, item) {}
|
||||
: PropagateItemJob(propagator, item, JobPriority::LastOutPriority) {}
|
||||
void start() Q_DECL_OVERRIDE;
|
||||
void abort() Q_DECL_OVERRIDE;
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class PropagateRemoteMkdir : public PropagateItemJob {
|
||||
friend class PropagateDirectory; // So it can access the _item;
|
||||
public:
|
||||
PropagateRemoteMkdir (OwncloudPropagator* propagator,const SyncFileItemPtr& item)
|
||||
: PropagateItemJob(propagator, item), _deleteExisting(false) {}
|
||||
: PropagateItemJob(propagator, item, JobPriority::FirstOutPriority), _deleteExisting(false) {}
|
||||
void start() Q_DECL_OVERRIDE;
|
||||
void abort() Q_DECL_OVERRIDE;
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "filesystem.h"
|
||||
#include <QFile>
|
||||
#include <QStringList>
|
||||
#include <QDir>
|
||||
|
||||
namespace OCC {
|
||||
|
||||
@@ -101,10 +102,11 @@ void PropagateRemoteMove::start()
|
||||
}
|
||||
}
|
||||
|
||||
QString destination = QDir::cleanPath(_propagator->account()->url().path() + QLatin1Char('/')
|
||||
+ _propagator->account()->davPath() + _propagator->_remoteFolder + _item->_renameTarget);
|
||||
_job = new MoveJob(_propagator->account(),
|
||||
_propagator->_remoteFolder + _item->_file,
|
||||
_propagator->_remoteDir + _item->_renameTarget,
|
||||
this);
|
||||
destination, this);
|
||||
connect(_job, SIGNAL(finishedSignal()), this, SLOT(slotMoveJobFinished()));
|
||||
_propagator->_activeJobList.append(this);
|
||||
_job->start();
|
||||
|
||||
@@ -51,7 +51,7 @@ class PropagateRemoteMove : public PropagateItemJob {
|
||||
QPointer<MoveJob> _job;
|
||||
public:
|
||||
PropagateRemoteMove (OwncloudPropagator* propagator,const SyncFileItemPtr& item)
|
||||
: PropagateItemJob(propagator, item) {}
|
||||
: PropagateItemJob(propagator, item, JobPriority::FirstOutPriority) {}
|
||||
void start() Q_DECL_OVERRIDE;
|
||||
void abort() Q_DECL_OVERRIDE;
|
||||
JobParallelism parallelism() Q_DECL_OVERRIDE { return OCC::PropagatorJob::WaitForFinishedInParentDirectory; }
|
||||
|
||||
@@ -197,7 +197,7 @@ protected:
|
||||
|
||||
public:
|
||||
PropagateUploadFileCommon(OwncloudPropagator* propagator,const SyncFileItemPtr& item)
|
||||
: PropagateItemJob(propagator, item), _finished(false), _deleteExisting(false) {}
|
||||
: PropagateItemJob(propagator, item, JobPriority::NormalPriority), _finished(false), _deleteExisting(false) {}
|
||||
|
||||
/**
|
||||
* Whether an existing entity with the same name may be deleted before
|
||||
@@ -211,6 +211,9 @@ public:
|
||||
|
||||
bool isLikelyFinishedQuickly() Q_DECL_OVERRIDE { return _item->_size < 100*1024; }
|
||||
|
||||
// this item is prioritized normaly, so get priority by its modification time
|
||||
quint64 getJobPriorityAttributeValue() const Q_DECL_OVERRIDE { return _item->_modtime; }
|
||||
|
||||
private slots:
|
||||
void slotComputeContentChecksum();
|
||||
// Content checksum computed, compute the transmission checksum
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace OCC {
|
||||
QUrl PropagateUploadFileNG::chunkUrl(int chunk)
|
||||
{
|
||||
QString path = QLatin1String("remote.php/dav/uploads/")
|
||||
+ _propagator->account()->user()
|
||||
+ _propagator->account()->davUser()
|
||||
+ QLatin1Char('/') + QString::number(_transferId);
|
||||
if (chunk >= 0) {
|
||||
path += QLatin1Char('/') + QString::number(chunk);
|
||||
@@ -268,9 +268,8 @@ void PropagateUploadFileNG::startNextChunk()
|
||||
Q_ASSERT(_jobs.isEmpty()); // There should be no running job anymore
|
||||
_finished = true;
|
||||
// Finish with a MOVE
|
||||
QString destination = _propagator->account()->url().path()
|
||||
+ QLatin1String("/remote.php/dav/files/") + _propagator->account()->user()
|
||||
+ _propagator->_remoteFolder + _item->_file;
|
||||
QString destination = QDir::cleanPath(_propagator->account()->url().path() + QLatin1Char('/')
|
||||
+ _propagator->account()->davPath() + _propagator->_remoteFolder + _item->_file);
|
||||
auto headers = PropagateUploadFileCommon::headers();
|
||||
|
||||
// "If-Match applies to the source, but we are interested in comparing the etag of the destination
|
||||
|
||||
@@ -40,7 +40,8 @@ static const char checkSumAdlerC[] = "Adler32";
|
||||
class PropagateLocalRemove : public PropagateItemJob {
|
||||
Q_OBJECT
|
||||
public:
|
||||
PropagateLocalRemove (OwncloudPropagator* propagator,const SyncFileItemPtr& item) : PropagateItemJob(propagator, item) {}
|
||||
PropagateLocalRemove (OwncloudPropagator* propagator,const SyncFileItemPtr& item)
|
||||
: PropagateItemJob(propagator, item, JobPriority::FirstOutPriority) {}
|
||||
void start() Q_DECL_OVERRIDE;
|
||||
private:
|
||||
bool removeRecursively(const QString &path);
|
||||
@@ -55,7 +56,7 @@ class PropagateLocalMkdir : public PropagateItemJob {
|
||||
Q_OBJECT
|
||||
public:
|
||||
PropagateLocalMkdir (OwncloudPropagator* propagator,const SyncFileItemPtr& item)
|
||||
: PropagateItemJob(propagator, item), _deleteExistingFile(false) {}
|
||||
: PropagateItemJob(propagator, item, JobPriority::FirstOutPriority), _deleteExistingFile(false) {}
|
||||
void start() Q_DECL_OVERRIDE;
|
||||
|
||||
/**
|
||||
@@ -77,7 +78,8 @@ private:
|
||||
class PropagateLocalRename : public PropagateItemJob {
|
||||
Q_OBJECT
|
||||
public:
|
||||
PropagateLocalRename (OwncloudPropagator* propagator,const SyncFileItemPtr& item) : PropagateItemJob(propagator, item) {}
|
||||
PropagateLocalRename (OwncloudPropagator* propagator,const SyncFileItemPtr& item)
|
||||
: PropagateItemJob(propagator, item, JobPriority::FirstOutPriority) {}
|
||||
void start() Q_DECL_OVERRIDE;
|
||||
JobParallelism parallelism() Q_DECL_OVERRIDE { return WaitForFinishedInParentDirectory; }
|
||||
};
|
||||
|
||||
@@ -57,12 +57,11 @@ bool SyncEngine::s_anySyncRunning = false;
|
||||
qint64 SyncEngine::minimumFileAgeForUpload = 2000;
|
||||
|
||||
SyncEngine::SyncEngine(AccountPtr account, const QString& localPath,
|
||||
const QUrl& remoteURL, const QString& remotePath, OCC::SyncJournalDb* journal)
|
||||
const QString& remotePath, OCC::SyncJournalDb* journal)
|
||||
: _account(account)
|
||||
, _needsUpdate(false)
|
||||
, _syncRunning(false)
|
||||
, _localPath(localPath)
|
||||
, _remoteUrl(remoteURL)
|
||||
, _remotePath(remotePath)
|
||||
, _journal(journal)
|
||||
, _progressInfo(new ProgressInfo)
|
||||
@@ -83,18 +82,7 @@ SyncEngine::SyncEngine(AccountPtr account, const QString& localPath,
|
||||
// Everything in the SyncEngine expects a trailing slash for the localPath.
|
||||
Q_ASSERT(localPath.endsWith(QLatin1Char('/')));
|
||||
|
||||
// We need to reconstruct the url because the path needs to be fully decoded, as csync will re-encode the path:
|
||||
// Remember that csync will just append the filename to the path and pass it to the vio plugin.
|
||||
// csync_owncloud will then re-encode everything.
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
QString url_string = _remoteUrl.scheme() + QLatin1String("://") + _remoteUrl.authority(QUrl::EncodeDelimiters) + _remoteUrl.path(QUrl::FullyDecoded);
|
||||
#else
|
||||
// Qt4 was broken anyway as it did not encode the '#' as it should have done (it was actually a problem when parsing the path from QUrl::setPath
|
||||
QString url_string = _remoteUrl.toString();
|
||||
#endif
|
||||
url_string = Utility::toCSyncScheme(url_string);
|
||||
|
||||
csync_create(&_csync_ctx, localPath.toUtf8().data(), url_string.toUtf8().data());
|
||||
csync_create(&_csync_ctx, localPath.toUtf8().data());
|
||||
csync_init(_csync_ctx);
|
||||
_excludedFiles.reset(new ExcludedFiles(&_csync_ctx->excludes));
|
||||
_syncFileStatusTracker.reset(new SyncFileStatusTracker(this));
|
||||
@@ -831,7 +819,6 @@ void SyncEngine::startSync()
|
||||
|
||||
// This is used for the DiscoveryJob to be able to request the main thread/
|
||||
// to read in directory contents.
|
||||
qDebug() << Q_FUNC_INFO << _remotePath << _remoteUrl;
|
||||
_discoveryMainThread->setupHooks( discoveryJob, _remotePath);
|
||||
|
||||
// Starts the update in a seperate thread
|
||||
@@ -983,7 +970,7 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult)
|
||||
_journal->commit("post treewalk");
|
||||
|
||||
_propagator = QSharedPointer<OwncloudPropagator>(
|
||||
new OwncloudPropagator (_account, _localPath, _remoteUrl.path(), _remotePath, _journal));
|
||||
new OwncloudPropagator (_account, _localPath, _remotePath, _journal));
|
||||
connect(_propagator.data(), SIGNAL(itemCompleted(const SyncFileItem &, const PropagatorJob &)),
|
||||
this, SLOT(slotItemCompleted(const SyncFileItem &, const PropagatorJob &)));
|
||||
connect(_propagator.data(), SIGNAL(progress(const SyncFileItem &,quint64)),
|
||||
|
||||
@@ -58,7 +58,7 @@ class OWNCLOUDSYNC_EXPORT SyncEngine : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
SyncEngine(AccountPtr account, const QString &localPath,
|
||||
const QUrl &remoteURL, const QString &remotePath, SyncJournalDb *journal);
|
||||
const QString &remotePath, SyncJournalDb *journal);
|
||||
~SyncEngine();
|
||||
|
||||
static QString csyncErrorToString( CSYNC_STATUS);
|
||||
@@ -196,7 +196,6 @@ private:
|
||||
bool _needsUpdate;
|
||||
bool _syncRunning;
|
||||
QString _localPath;
|
||||
QUrl _remoteUrl;
|
||||
QString _remotePath;
|
||||
QString _remoteRootEtag;
|
||||
SyncJournalDb *_journal;
|
||||
|
||||
@@ -243,19 +243,6 @@ QString Utility::compactFormatDouble(double value, int prec, const QString& unit
|
||||
return str;
|
||||
}
|
||||
|
||||
QString Utility::toCSyncScheme(const QString &urlStr)
|
||||
{
|
||||
|
||||
QUrl url( urlStr );
|
||||
if( url.scheme() == QLatin1String("http") ) {
|
||||
url.setScheme( QLatin1String("owncloud") );
|
||||
} else {
|
||||
// connect SSL!
|
||||
url.setScheme( QLatin1String("ownclouds") );
|
||||
}
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
QString Utility::escape(const QString &in)
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
||||
|
||||
@@ -44,7 +44,6 @@ namespace Utility
|
||||
OWNCLOUDSYNC_EXPORT bool hasLaunchOnStartup(const QString &appName);
|
||||
OWNCLOUDSYNC_EXPORT void setLaunchOnStartup(const QString &appName, const QString& guiName, bool launch);
|
||||
OWNCLOUDSYNC_EXPORT qint64 freeDiskSpace(const QString &path);
|
||||
OWNCLOUDSYNC_EXPORT QString toCSyncScheme(const QString &urlStr);
|
||||
|
||||
/**
|
||||
* @brief compactFormatDouble - formats a double value human readable.
|
||||
|
||||
@@ -21,6 +21,6 @@ macro(owncloud_add_test test_class additional_cpp)
|
||||
)
|
||||
|
||||
add_definitions(-DOWNCLOUD_TEST)
|
||||
add_definitions(-DOWNCLOUD_BIN_PATH="${CMAKE_BINARY_DIR}/bin")
|
||||
add_definitions(-DOWNCLOUD_BIN_PATH=${CMAKE_BINARY_DIR}/bin)
|
||||
add_test(NAME ${OWNCLOUD_TEST_CLASS}Test COMMAND ${OWNCLOUD_TEST_CLASS}Test)
|
||||
endmacro()
|
||||
|
||||
@@ -738,7 +738,7 @@ public:
|
||||
_account->setCredentials(new FakeCredentials{_fakeQnam});
|
||||
|
||||
_journalDb.reset(new OCC::SyncJournalDb(localPath()));
|
||||
_syncEngine.reset(new OCC::SyncEngine(_account, localPath(), sRootUrl, "", _journalDb.get()));
|
||||
_syncEngine.reset(new OCC::SyncEngine(_account, localPath(), "", _journalDb.get()));
|
||||
|
||||
// A new folder will update the local file state database on first sync.
|
||||
// To have a state matching what users will encounter, we have to a sync
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
|
||||
using namespace OCC;
|
||||
|
||||
#define STR_(X) #X
|
||||
#define STR(X) STR_(X)
|
||||
#define BIN_PATH STR(OWNCLOUD_BIN_PATH)
|
||||
|
||||
class TestExcludedFiles: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -27,7 +31,7 @@ private slots:
|
||||
QVERIFY(!excluded.isExcluded("/a/.b", "/a", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/.b", "/a", excludeHidden));
|
||||
|
||||
QString path(OWNCLOUD_BIN_PATH);
|
||||
QString path(BIN_PATH);
|
||||
path.append("/sync-exclude.lst");
|
||||
excluded.addExcludeFilePath(path);
|
||||
excluded.reloadExcludes();
|
||||
@@ -35,9 +39,9 @@ private slots:
|
||||
QVERIFY(!excluded.isExcluded("/a/b", "/a", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/b~", "/a", keepHidden));
|
||||
QVERIFY(!excluded.isExcluded("/a/.b", "/a", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/.b", "/a", excludeHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/.Trashes", "/a", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/foo_conflict-bar", "/a", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/.b", "/a", excludeHidden));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
|
||||
#include "utility.h"
|
||||
|
||||
#define STR_(X) #X
|
||||
#define STR(X) STR_(X)
|
||||
#define BIN_PATH STR(OWNCLOUD_BIN_PATH)
|
||||
|
||||
using namespace OCC::Utility;
|
||||
|
||||
class TestUtility : public QObject
|
||||
@@ -60,14 +64,6 @@ private slots:
|
||||
QVERIFY(hasLaunchOnStartup(appName) == false);
|
||||
}
|
||||
|
||||
void testToCSyncScheme()
|
||||
{
|
||||
QVERIFY(toCSyncScheme("http://example.com/owncloud/") ==
|
||||
"owncloud://example.com/owncloud/");
|
||||
QVERIFY(toCSyncScheme("https://example.com/owncloud/") ==
|
||||
"ownclouds://example.com/owncloud/");
|
||||
}
|
||||
|
||||
void testDurationToDescriptiveString()
|
||||
{
|
||||
QLocale::setDefault(QLocale("C"));
|
||||
@@ -119,7 +115,7 @@ private slots:
|
||||
}
|
||||
// pass the binary name owncloud to the next call. This brakes branding,
|
||||
// but branding is not supposed to work with this.
|
||||
QString ver = versionOfInstalledBinary(OWNCLOUD_BIN_PATH+QLatin1String("/owncloud"));
|
||||
QString ver = versionOfInstalledBinary(BIN_PATH+QLatin1String("/owncloud"));
|
||||
qDebug() << "Version of installed ownCloud Binary: " << ver;
|
||||
QVERIFY( !ver.isEmpty());
|
||||
|
||||
|
||||
+203
-198
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+204
-199
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+207
-202
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+203
-198
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+202
-197
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+204
-199
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+202
-197
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+202
-197
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+202
-197
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+202
-197
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+210
-205
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+203
-198
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+202
-197
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+203
-198
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+206
-201
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+222
-217
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+225
-218
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+207
-202
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+203
-198
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+208
-203
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+203
-198
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+241
-236
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+203
-198
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+206
-201
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+202
-197
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+203
-198
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+208
-203
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+203
-198
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+202
-197
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+203
-198
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+224
-219
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
Referência em uma Nova Issue
Bloquear um usuário