mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-26 15:06:08 +03:00
CSync: Use context instead of global variable
This commit is contained in:
parent
0dcc9be5c1
commit
8a55f831f4
8 changed files with 429 additions and 388 deletions
|
@ -191,7 +191,7 @@ int csync_init(CSYNC *ctx) {
|
|||
ctx->local.type = LOCAL_REPLICA;
|
||||
|
||||
if ( !ctx->options.local_only_mode) {
|
||||
owncloud_init(csync_get_userdata(ctx));
|
||||
owncloud_init(ctx);
|
||||
ctx->remote.type = REMOTE_REPLICA;
|
||||
} else {
|
||||
ctx->remote.type = LOCAL_REPLICA;
|
||||
|
@ -679,6 +679,8 @@ int csync_destroy(CSYNC *ctx) {
|
|||
SAFE_FREE(ctx->options.config_dir);
|
||||
SAFE_FREE(ctx->error_string);
|
||||
|
||||
owncloud_destroy(ctx);
|
||||
|
||||
#ifdef WITH_ICONV
|
||||
c_close_iconv();
|
||||
#endif
|
||||
|
|
|
@ -20,60 +20,10 @@
|
|||
*/
|
||||
|
||||
#include "csync_owncloud.h"
|
||||
#include "csync_owncloud_private.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
/*
|
||||
* free the fetchCtx
|
||||
*/
|
||||
static void free_fetchCtx( struct listdir_context *ctx )
|
||||
{
|
||||
struct resource *newres, *res;
|
||||
if( ! ctx ) return;
|
||||
newres = ctx->list;
|
||||
res = newres;
|
||||
|
||||
ctx->ref--;
|
||||
if (ctx->ref > 0) return;
|
||||
|
||||
SAFE_FREE(ctx->target);
|
||||
|
||||
while( res ) {
|
||||
SAFE_FREE(res->uri);
|
||||
SAFE_FREE(res->name);
|
||||
SAFE_FREE(res->md5);
|
||||
memset( res->file_id, 0, FILE_ID_BUF_SIZE+1 );
|
||||
|
||||
newres = res->next;
|
||||
SAFE_FREE(res);
|
||||
res = newres;
|
||||
}
|
||||
SAFE_FREE(ctx);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* local variables.
|
||||
*/
|
||||
|
||||
struct dav_session_s dav_session; /* The DAV Session, initialised in dav_connect */
|
||||
int _connected = 0; /* flag to indicate if a connection exists, ie.
|
||||
the dav_session is valid */
|
||||
|
||||
|
||||
void *_userdata;
|
||||
|
||||
struct listdir_context *propfind_cache = 0;
|
||||
|
||||
bool is_first_propfind = true;
|
||||
|
||||
static void clean_caches() {
|
||||
clear_propfind_recursive_cache();
|
||||
|
||||
free_fetchCtx(propfind_cache);
|
||||
propfind_cache = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* helper method to build up a user text for SSL problems, called from the
|
||||
|
@ -105,8 +55,8 @@ static int verify_sslcert(void *userdata, int failures,
|
|||
int ret = -1;
|
||||
const ne_ssl_certificate *cert = certificate;
|
||||
csync_auth_callback authcb = NULL;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
|
||||
(void) userdata;
|
||||
memset( problem, 0, LEN );
|
||||
|
||||
while( cert ) {
|
||||
|
@ -142,14 +92,14 @@ static int verify_sslcert(void *userdata, int failures,
|
|||
}
|
||||
addSSLWarning( problem, "Do you want to accept the certificate chain anyway?\nAnswer yes to do so and take the risk: ", LEN );
|
||||
|
||||
if( dav_session.csync_ctx ) {
|
||||
authcb = csync_get_auth_callback( dav_session.csync_ctx );
|
||||
if( ctx->csync_ctx ) {
|
||||
authcb = csync_get_auth_callback( ctx->csync_ctx );
|
||||
}
|
||||
if( authcb ){
|
||||
/* call the csync callback */
|
||||
DEBUG_WEBDAV("Call the csync callback for SSL problems");
|
||||
memset( buf, 0, NE_ABUFSIZ );
|
||||
(*authcb) ( problem, buf, NE_ABUFSIZ-1, 1, 0, _userdata );
|
||||
(*authcb) ( problem, buf, NE_ABUFSIZ-1, 1, 0, csync_get_userdata(ctx->csync_ctx) );
|
||||
if( buf[0] == 'y' || buf[0] == 'Y') {
|
||||
ret = 0;
|
||||
} else {
|
||||
|
@ -171,35 +121,35 @@ static int ne_auth( void *userdata, const char *realm, int attempt,
|
|||
char buf[NE_ABUFSIZ];
|
||||
csync_auth_callback authcb = NULL;
|
||||
int re = attempt;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
|
||||
(void) userdata;
|
||||
(void) realm;
|
||||
|
||||
/* DEBUG_WEBDAV( "Authentication required %s", realm ); */
|
||||
if( username && password ) {
|
||||
DEBUG_WEBDAV( "Authentication required %s", username );
|
||||
if( dav_session.user ) {
|
||||
if( ctx->dav_session.user ) {
|
||||
/* allow user without password */
|
||||
if( strlen( dav_session.user ) < NE_ABUFSIZ ) {
|
||||
strcpy( username, dav_session.user );
|
||||
if( strlen( ctx->dav_session.user ) < NE_ABUFSIZ ) {
|
||||
strcpy( username, ctx->dav_session.user );
|
||||
}
|
||||
if( dav_session.pwd && strlen( dav_session.pwd ) < NE_ABUFSIZ ) {
|
||||
strcpy( password, dav_session.pwd );
|
||||
if( ctx->dav_session.pwd && strlen( ctx->dav_session.pwd ) < NE_ABUFSIZ ) {
|
||||
strcpy( password, ctx->dav_session.pwd );
|
||||
}
|
||||
} else {
|
||||
if( dav_session.csync_ctx ) {
|
||||
authcb = csync_get_auth_callback( dav_session.csync_ctx );
|
||||
if( ctx->dav_session.csync_ctx ) {
|
||||
authcb = csync_get_auth_callback( ctx->dav_session.csync_ctx );
|
||||
}
|
||||
if( authcb != NULL ){
|
||||
/* call the csync callback */
|
||||
DEBUG_WEBDAV("Call the csync callback for %s", realm );
|
||||
memset( buf, 0, NE_ABUFSIZ );
|
||||
(*authcb) ("Enter your username: ", buf, NE_ABUFSIZ-1, 1, 0, _userdata );
|
||||
(*authcb) ("Enter your username: ", buf, NE_ABUFSIZ-1, 1, 0, csync_get_userdata(ctx->csync_ctx) );
|
||||
if( strlen(buf) < NE_ABUFSIZ ) {
|
||||
strcpy( username, buf );
|
||||
}
|
||||
memset( buf, 0, NE_ABUFSIZ );
|
||||
(*authcb) ("Enter your password: ", buf, NE_ABUFSIZ-1, 0, 0, _userdata );
|
||||
(*authcb) ("Enter your password: ", buf, NE_ABUFSIZ-1, 0, 0, csync_get_userdata(ctx->csync_ctx) );
|
||||
if( strlen(buf) < NE_ABUFSIZ) {
|
||||
strcpy( password, buf );
|
||||
}
|
||||
|
@ -219,12 +169,12 @@ static int ne_auth( void *userdata, const char *realm, int attempt,
|
|||
static int ne_proxy_auth( void *userdata, const char *realm, int attempt,
|
||||
char *username, char *password)
|
||||
{
|
||||
(void) userdata;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
(void) realm;
|
||||
if( dav_session.proxy_user && strlen( dav_session.proxy_user ) < NE_ABUFSIZ) {
|
||||
strcpy( username, dav_session.proxy_user );
|
||||
if( dav_session.proxy_pwd && strlen( dav_session.proxy_pwd ) < NE_ABUFSIZ) {
|
||||
strcpy( password, dav_session.proxy_pwd );
|
||||
if( ctx->dav_session.proxy_user && strlen( ctx->dav_session.proxy_user ) < NE_ABUFSIZ) {
|
||||
strcpy( username, ctx->dav_session.proxy_user );
|
||||
if( ctx->dav_session.proxy_pwd && strlen( ctx->dav_session.proxy_pwd ) < NE_ABUFSIZ) {
|
||||
strcpy( password, ctx->dav_session.proxy_pwd );
|
||||
}
|
||||
}
|
||||
/* NTLM needs several attempts */
|
||||
|
@ -232,42 +182,42 @@ static int ne_proxy_auth( void *userdata, const char *realm, int attempt,
|
|||
}
|
||||
|
||||
/* Configure the proxy depending on the variables */
|
||||
static int configureProxy( ne_session *session )
|
||||
static int configureProxy( csync_owncloud_ctx_t *ctx, ne_session *session )
|
||||
{
|
||||
int port = 8080;
|
||||
int re = -1;
|
||||
|
||||
if( ! session ) return -1;
|
||||
if( ! dav_session.proxy_type ) return 0; /* Go by NoProxy per default */
|
||||
if( ! ctx->dav_session.proxy_type ) return 0; /* Go by NoProxy per default */
|
||||
|
||||
if( dav_session.proxy_port > 0 ) {
|
||||
port = dav_session.proxy_port;
|
||||
if( ctx->dav_session.proxy_port > 0 ) {
|
||||
port = ctx->dav_session.proxy_port;
|
||||
}
|
||||
|
||||
if( c_streq(dav_session.proxy_type, "NoProxy" )) {
|
||||
if( c_streq(ctx->dav_session.proxy_type, "NoProxy" )) {
|
||||
DEBUG_WEBDAV("No proxy configured.");
|
||||
re = 0;
|
||||
} else if( c_streq(dav_session.proxy_type, "DefaultProxy") ||
|
||||
c_streq(dav_session.proxy_type, "HttpProxy") ||
|
||||
c_streq(dav_session.proxy_type, "HttpCachingProxy") ||
|
||||
c_streq(dav_session.proxy_type, "Socks5Proxy")) {
|
||||
} else if( c_streq(ctx->dav_session.proxy_type, "DefaultProxy") ||
|
||||
c_streq(ctx->dav_session.proxy_type, "HttpProxy") ||
|
||||
c_streq(ctx->dav_session.proxy_type, "HttpCachingProxy") ||
|
||||
c_streq(ctx->dav_session.proxy_type, "Socks5Proxy")) {
|
||||
|
||||
if( dav_session.proxy_host ) {
|
||||
DEBUG_WEBDAV("%s at %s:%d", dav_session.proxy_type, dav_session.proxy_host, port );
|
||||
if (c_streq(dav_session.proxy_type, "Socks5Proxy")) {
|
||||
ne_session_socks_proxy(session, NE_SOCK_SOCKSV5, dav_session.proxy_host, port,
|
||||
dav_session.proxy_user, dav_session.proxy_pwd);
|
||||
if( ctx->dav_session.proxy_host ) {
|
||||
DEBUG_WEBDAV("%s at %s:%d", ctx->dav_session.proxy_type, ctx->dav_session.proxy_host, port );
|
||||
if (c_streq(ctx->dav_session.proxy_type, "Socks5Proxy")) {
|
||||
ne_session_socks_proxy(session, NE_SOCK_SOCKSV5, ctx->dav_session.proxy_host, port,
|
||||
ctx->dav_session.proxy_user, ctx->dav_session.proxy_pwd);
|
||||
} else {
|
||||
ne_session_proxy(session, dav_session.proxy_host, port );
|
||||
ne_session_proxy(session, ctx->dav_session.proxy_host, port );
|
||||
}
|
||||
re = 2;
|
||||
} else {
|
||||
DEBUG_WEBDAV("%s requested but no proxy host defined.", dav_session.proxy_type );
|
||||
DEBUG_WEBDAV("%s requested but no proxy host defined.", ctx->dav_session.proxy_type );
|
||||
/* we used to try ne_system_session_proxy here, but we should rather err out
|
||||
to behave exactly like the caller. */
|
||||
}
|
||||
} else {
|
||||
DEBUG_WEBDAV( "Unsupported Proxy: %s", dav_session.proxy_type );
|
||||
DEBUG_WEBDAV( "Unsupported Proxy: %s", ctx->dav_session.proxy_type );
|
||||
}
|
||||
|
||||
return re;
|
||||
|
@ -284,9 +234,9 @@ static void post_request_hook(ne_request *req, void *userdata, const ne_status *
|
|||
const char *sc = NULL;
|
||||
char *key = NULL;
|
||||
|
||||
(void) userdata;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
|
||||
if (dav_session.session_key)
|
||||
if (ctx->dav_session.session_key)
|
||||
return; /* We already have a session cookie, and we should ignore other ones */
|
||||
|
||||
if(!(status && req)) return;
|
||||
|
@ -354,8 +304,8 @@ static void post_request_hook(ne_request *req, void *userdata, const ne_status *
|
|||
}
|
||||
if( key ) {
|
||||
DEBUG_WEBDAV("----> Session-key: %s", key);
|
||||
SAFE_FREE(dav_session.session_key);
|
||||
dav_session.session_key = key;
|
||||
SAFE_FREE(ctx->dav_session.session_key);
|
||||
ctx->dav_session.session_key = key;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,13 +316,14 @@ static void post_request_hook(ne_request *req, void *userdata, const ne_status *
|
|||
static void request_created_hook(ne_request *req, void *userdata,
|
||||
const char *method, const char *requri)
|
||||
{
|
||||
(void) userdata;
|
||||
// FIXME Can possibly be merged with pre_send_hook
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t *) userdata;
|
||||
(void) method;
|
||||
(void) requri;
|
||||
|
||||
if( !req ) return;
|
||||
|
||||
if(dav_session.proxy_type) {
|
||||
if(ctx->dav_session.proxy_type) {
|
||||
/* required for NTLM */
|
||||
ne_add_request_header(req, "Proxy-Connection", "Keep-Alive");
|
||||
}
|
||||
|
@ -385,12 +336,12 @@ static void request_created_hook(ne_request *req, void *userdata,
|
|||
static void pre_send_hook(ne_request *req, void *userdata,
|
||||
ne_buffer *header)
|
||||
{
|
||||
(void) userdata;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t *) userdata;
|
||||
|
||||
if( !req ) return;
|
||||
|
||||
if(dav_session.session_key) {
|
||||
ne_buffer_concat(header, "Cookie: ", dav_session.session_key, "\r\n", NULL);
|
||||
if(ctx->dav_session.session_key) {
|
||||
ne_buffer_concat(header, "Cookie: ", ctx->dav_session.session_key, "\r\n", NULL);
|
||||
} else {
|
||||
DEBUG_WEBDAV("csync pre_send_hook We don't have a Auth Cookie (session_key), this is wrong!");
|
||||
}
|
||||
|
@ -400,16 +351,15 @@ static int post_send_hook(ne_request *req, void *userdata,
|
|||
const ne_status *status)
|
||||
{
|
||||
const char *location;
|
||||
|
||||
(void) userdata;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t *) userdata;
|
||||
(void) status;
|
||||
|
||||
location = ne_get_response_header(req, "Location");
|
||||
|
||||
if( !location ) return NE_OK;
|
||||
|
||||
if( dav_session.redir_callback ) {
|
||||
if( dav_session.redir_callback( dav_session.csync_ctx, location ) ) {
|
||||
if( ctx->dav_session.redir_callback ) {
|
||||
if( ctx->dav_session.redir_callback( ctx->dav_session.csync_ctx, location ) ) {
|
||||
return NE_REDIRECT;
|
||||
} else {
|
||||
return NE_RETRY;
|
||||
|
@ -449,7 +399,7 @@ static const char* get_platform() {
|
|||
* This function sets the flag _connected if the connection is established
|
||||
* and returns if the flag is set, so calling it frequently is save.
|
||||
*/
|
||||
static int dav_connect(const char *base_url) {
|
||||
static int dav_connect(csync_owncloud_ctx_t *ctx, const char *base_url) {
|
||||
int useSSL = 0;
|
||||
int rc;
|
||||
char protocol[6] = {'\0'};
|
||||
|
@ -460,11 +410,14 @@ static int dav_connect(const char *base_url) {
|
|||
unsigned int port = 0;
|
||||
int proxystate = -1;
|
||||
|
||||
if (_connected) {
|
||||
if (ctx->_connected) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = c_parse_uri( base_url, &scheme, &dav_session.user, &dav_session.pwd, &host, &port, &path );
|
||||
rc = c_parse_uri( base_url, &scheme,
|
||||
&ctx->dav_session.user,
|
||||
&ctx->dav_session.pwd,
|
||||
&host, &port, &path );
|
||||
if( rc < 0 ) {
|
||||
DEBUG_WEBDAV("Failed to parse uri %s", base_url );
|
||||
goto out;
|
||||
|
@ -486,29 +439,29 @@ static int dav_connect(const char *base_url) {
|
|||
goto out;
|
||||
}
|
||||
|
||||
DEBUG_WEBDAV("* user %s", dav_session.user ? dav_session.user : "");
|
||||
DEBUG_WEBDAV("* user %s", ctx->dav_session.user ? ctx->dav_session.user : "");
|
||||
|
||||
if (port == 0) {
|
||||
port = ne_uri_defaultport(protocol);
|
||||
}
|
||||
|
||||
dav_session.ctx = ne_session_create( protocol, host, port);
|
||||
ctx->dav_session.ctx = ne_session_create( protocol, host, port);
|
||||
|
||||
if (dav_session.ctx == NULL) {
|
||||
if (ctx->dav_session.ctx == NULL) {
|
||||
DEBUG_WEBDAV("Session create with protocol %s failed", protocol );
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dav_session.read_timeout != 0) {
|
||||
ne_set_read_timeout(dav_session.ctx, dav_session.read_timeout);
|
||||
DEBUG_WEBDAV("Timeout set to %u seconds", dav_session.read_timeout );
|
||||
if (ctx->dav_session.read_timeout != 0) {
|
||||
ne_set_read_timeout(ctx->dav_session.ctx, ctx->dav_session.read_timeout);
|
||||
DEBUG_WEBDAV("Timeout set to %u seconds", ctx->dav_session.read_timeout );
|
||||
}
|
||||
|
||||
snprintf( uaBuf, sizeof(uaBuf), "Mozilla/5.0 (%s) csyncoC/%s",
|
||||
get_platform(), CSYNC_STRINGIFY( LIBCSYNC_VERSION ));
|
||||
ne_set_useragent( dav_session.ctx, uaBuf);
|
||||
ne_set_server_auth(dav_session.ctx, ne_auth, 0 );
|
||||
ne_set_useragent( ctx->dav_session.ctx, uaBuf);
|
||||
ne_set_server_auth(ctx->dav_session.ctx, ne_auth, ctx);
|
||||
|
||||
if( useSSL ) {
|
||||
if (!ne_has_support(NE_FEATURE_SSL)) {
|
||||
|
@ -517,28 +470,28 @@ static int dav_connect(const char *base_url) {
|
|||
goto out;
|
||||
}
|
||||
|
||||
ne_ssl_trust_default_ca( dav_session.ctx );
|
||||
ne_ssl_set_verify( dav_session.ctx, verify_sslcert, 0 );
|
||||
ne_ssl_trust_default_ca( ctx->dav_session.ctx );
|
||||
ne_ssl_set_verify( ctx->dav_session.ctx, verify_sslcert, ctx);
|
||||
}
|
||||
|
||||
/* Hook called when a request is created. It sets the proxy connection header. */
|
||||
ne_hook_create_request( dav_session.ctx, request_created_hook, NULL );
|
||||
ne_hook_create_request( ctx->dav_session.ctx, request_created_hook, ctx );
|
||||
/* Hook called after response headers are read. It gets the Session ID. */
|
||||
ne_hook_post_headers( dav_session.ctx, post_request_hook, NULL );
|
||||
ne_hook_post_headers( ctx->dav_session.ctx, post_request_hook, ctx );
|
||||
/* Hook called before a request is sent. It sets the cookies. */
|
||||
ne_hook_pre_send( dav_session.ctx, pre_send_hook, NULL );
|
||||
ne_hook_pre_send( ctx->dav_session.ctx, pre_send_hook, ctx );
|
||||
/* Hook called after request is dispatched. Used for handling possible redirections. */
|
||||
ne_hook_post_send( dav_session.ctx, post_send_hook, NULL );
|
||||
ne_hook_post_send( ctx->dav_session.ctx, post_send_hook, ctx );
|
||||
|
||||
/* Proxy support */
|
||||
proxystate = configureProxy( dav_session.ctx );
|
||||
proxystate = configureProxy( ctx, ctx->dav_session.ctx );
|
||||
if( proxystate < 0 ) {
|
||||
DEBUG_WEBDAV("Error: Proxy-Configuration failed.");
|
||||
} else if( proxystate > 0 ) {
|
||||
ne_set_proxy_auth( dav_session.ctx, ne_proxy_auth, 0 );
|
||||
ne_set_proxy_auth( ctx->dav_session.ctx, ne_proxy_auth, 0 );
|
||||
}
|
||||
|
||||
_connected = 1;
|
||||
ctx->_connected = 1;
|
||||
rc = 0;
|
||||
out:
|
||||
SAFE_FREE(path);
|
||||
|
@ -624,7 +577,7 @@ static void results(void *userdata,
|
|||
/*
|
||||
* fetches a resource list from the WebDAV server. This is equivalent to list dir.
|
||||
*/
|
||||
static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
||||
static struct listdir_context *fetch_resource_list(csync_owncloud_ctx_t *ctx, const char *uri, int depth)
|
||||
{
|
||||
struct listdir_context *fetchCtx;
|
||||
int ret = 0;
|
||||
|
@ -638,12 +591,12 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
|||
|
||||
/* The old legacy one-level PROPFIND cache. Also gets filled
|
||||
by the recursive cache if 'infinity' did not suceed. */
|
||||
if (propfind_cache) {
|
||||
if (c_streq(curi, propfind_cache->target)) {
|
||||
if (ctx->propfind_cache) {
|
||||
if (c_streq(curi, ctx->propfind_cache->target)) {
|
||||
DEBUG_WEBDAV("fetch_resource_list Using simple PROPFIND cache %s", curi);
|
||||
propfind_cache->ref++;
|
||||
ctx->propfind_cache->ref++;
|
||||
SAFE_FREE(curi);
|
||||
return propfind_cache;
|
||||
return ctx->propfind_cache;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -659,7 +612,7 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
|||
fetchCtx->ref = 1;
|
||||
|
||||
/* do a propfind request and parse the results in the results function, set as callback */
|
||||
hdl = ne_propfind_create(dav_session.ctx, curi, depth);
|
||||
hdl = ne_propfind_create(ctx->dav_session.ctx, curi, depth);
|
||||
|
||||
if(hdl) {
|
||||
ret = ne_propfind_named(hdl, ls_props, results, fetchCtx);
|
||||
|
@ -675,14 +628,14 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
|||
DEBUG_WEBDAV("ERROR: Request failed: status %d (%s)", req_status->code,
|
||||
req_status->reason_phrase);
|
||||
ret = NE_CONNECT;
|
||||
set_error_message(req_status->reason_phrase);
|
||||
set_error_message(ctx, req_status->reason_phrase);
|
||||
}
|
||||
DEBUG_WEBDAV("Simple propfind result code %d.", req_status->code);
|
||||
} else {
|
||||
if( ret == NE_ERROR && req_status->code == 404) {
|
||||
errno = ENOENT;
|
||||
} else {
|
||||
set_errno_from_neon_errcode(ret);
|
||||
set_errno_from_neon_errcode(ctx, ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -697,18 +650,18 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
|||
DEBUG_WEBDAV("ERROR: Content type of propfind request not XML: %s.",
|
||||
content_type ? content_type: "<empty>");
|
||||
errno = ERRNO_WRONG_CONTENT;
|
||||
set_error_message("Server error: PROPFIND reply is not XML formatted!");
|
||||
set_error_message(ctx, "Server error: PROPFIND reply is not XML formatted!");
|
||||
ret = NE_CONNECT;
|
||||
}
|
||||
}
|
||||
|
||||
if( ret != NE_OK ) {
|
||||
const char *err = NULL;
|
||||
set_errno_from_neon_errcode(ret);
|
||||
set_errno_from_neon_errcode(ctx, ret);
|
||||
|
||||
err = ne_get_error( dav_session.ctx );
|
||||
err = ne_get_error( ctx->dav_session.ctx );
|
||||
if(err) {
|
||||
set_error_message(err);
|
||||
set_error_message(ctx, err);
|
||||
}
|
||||
DEBUG_WEBDAV("WRN: propfind named failed with %d, request error: %s", ret, err ? err : "<nil>");
|
||||
}
|
||||
|
@ -721,19 +674,19 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
free_fetchCtx(propfind_cache);
|
||||
propfind_cache = fetchCtx;
|
||||
propfind_cache->ref++;
|
||||
free_fetchCtx(ctx->propfind_cache);
|
||||
ctx->propfind_cache = fetchCtx;
|
||||
ctx->propfind_cache->ref++;
|
||||
return fetchCtx;
|
||||
}
|
||||
|
||||
static struct listdir_context *fetch_resource_list_attempts(const char *uri, int depth)
|
||||
static struct listdir_context *fetch_resource_list_attempts(csync_owncloud_ctx_t *ctx, const char *uri, int depth)
|
||||
{
|
||||
int i;
|
||||
|
||||
struct listdir_context *fetchCtx = NULL;
|
||||
for(i = 0; i < 10; ++i) {
|
||||
fetchCtx = fetch_resource_list(uri, depth);
|
||||
fetchCtx = fetch_resource_list(ctx, uri, depth);
|
||||
if(fetchCtx) break;
|
||||
/* only loop in case the content is not XML formatted. Otherwise for every
|
||||
* non successful stat (for non existing directories) its tried 10 times. */
|
||||
|
@ -749,35 +702,35 @@ static struct listdir_context *fetch_resource_list_attempts(const char *uri, int
|
|||
/*
|
||||
* directory functions
|
||||
*/
|
||||
csync_vio_handle_t *owncloud_opendir(const char *uri) {
|
||||
csync_vio_handle_t *owncloud_opendir(CSYNC *ctx, const char *uri) {
|
||||
struct listdir_context *fetchCtx = NULL;
|
||||
char *curi = NULL;
|
||||
|
||||
DEBUG_WEBDAV("opendir method called on %s", uri );
|
||||
|
||||
if (dav_connect( uri ) < 0) {
|
||||
if (dav_connect( ctx->owncloud_context, uri ) < 0) {
|
||||
DEBUG_WEBDAV("connection failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
curi = _cleanPath( uri );
|
||||
if (is_first_propfind && !dav_session.no_recursive_propfind) {
|
||||
is_first_propfind = false;
|
||||
if (ctx->owncloud_context->is_first_propfind && !ctx->owncloud_context->dav_session.no_recursive_propfind) {
|
||||
ctx->owncloud_context->is_first_propfind = false;
|
||||
// Try to fill it
|
||||
fill_recursive_propfind_cache(uri, curi);
|
||||
fill_recursive_propfind_cache(ctx->owncloud_context, uri, curi);
|
||||
}
|
||||
if (propfind_recursive_cache) {
|
||||
if (ctx->owncloud_context->propfind_recursive_cache) {
|
||||
// Try to fetch from recursive cache (if we have one)
|
||||
fetchCtx = get_listdir_context_from_recursive_cache(curi);
|
||||
fetchCtx = get_listdir_context_from_recursive_cache(ctx->owncloud_context, curi);
|
||||
}
|
||||
SAFE_FREE(curi);
|
||||
is_first_propfind = false;
|
||||
ctx->owncloud_context->is_first_propfind = false;
|
||||
if (fetchCtx) {
|
||||
return fetchCtx;
|
||||
}
|
||||
|
||||
/* fetchCtx = fetch_resource_list( uri, NE_DEPTH_ONE ); */
|
||||
fetchCtx = fetch_resource_list_attempts( uri, NE_DEPTH_ONE);
|
||||
fetchCtx = fetch_resource_list_attempts( ctx->owncloud_context, uri, NE_DEPTH_ONE);
|
||||
if( !fetchCtx ) {
|
||||
/* errno is set properly in fetch_resource_list */
|
||||
DEBUG_WEBDAV("Errno set to %d", errno);
|
||||
|
@ -790,7 +743,8 @@ csync_vio_handle_t *owncloud_opendir(const char *uri) {
|
|||
/* no freeing of curi because its part of the fetchCtx and gets freed later */
|
||||
}
|
||||
|
||||
int owncloud_closedir(csync_vio_handle_t *dhandle) {
|
||||
int owncloud_closedir(CSYNC *ctx, csync_vio_handle_t *dhandle) {
|
||||
(void)ctx;
|
||||
|
||||
struct listdir_context *fetchCtx = dhandle;
|
||||
|
||||
|
@ -799,7 +753,8 @@ int owncloud_closedir(csync_vio_handle_t *dhandle) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
csync_vio_file_stat_t *owncloud_readdir(csync_vio_handle_t *dhandle) {
|
||||
csync_vio_file_stat_t *owncloud_readdir(CSYNC *ctx, csync_vio_handle_t *dhandle) {
|
||||
(void)ctx;
|
||||
struct listdir_context *fetchCtx = dhandle;
|
||||
|
||||
// DEBUG_WEBDAV("owncloud_readdir" );
|
||||
|
@ -841,39 +796,51 @@ csync_vio_file_stat_t *owncloud_readdir(csync_vio_handle_t *dhandle) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
char *owncloud_error_string(void)
|
||||
char *owncloud_error_string(CSYNC* ctx)
|
||||
{
|
||||
return dav_session.error_string;
|
||||
return ctx->owncloud_context->dav_session.error_string;
|
||||
}
|
||||
|
||||
int owncloud_commit(void) {
|
||||
int owncloud_commit(CSYNC* ctx) {
|
||||
clear_propfind_recursive_cache(ctx->owncloud_context);
|
||||
|
||||
clean_caches();
|
||||
free_fetchCtx(ctx->owncloud_context->propfind_cache);
|
||||
ctx->owncloud_context->propfind_cache = NULL;
|
||||
|
||||
if( dav_session.ctx ) {
|
||||
ne_forget_auth(dav_session.ctx);
|
||||
ne_session_destroy( dav_session.ctx );
|
||||
}
|
||||
if( ctx->owncloud_context->dav_session.ctx ) {
|
||||
ne_forget_auth(ctx->owncloud_context->dav_session.ctx);
|
||||
ne_session_destroy(ctx->owncloud_context->dav_session.ctx );
|
||||
ctx->owncloud_context->dav_session.ctx = 0;
|
||||
}
|
||||
|
||||
ctx->owncloud_context->is_first_propfind = true;
|
||||
/* DEBUG_WEBDAV( "********** vio_module_shutdown" ); */
|
||||
|
||||
dav_session.ctx = 0;
|
||||
ctx->owncloud_context->dav_session.ctx = 0;
|
||||
|
||||
// ne_sock_exit();
|
||||
_connected = 0; /* triggers dav_connect to go through the whole neon setup */
|
||||
ctx->owncloud_context->_connected = 0; /* triggers dav_connect to go through the whole neon setup */
|
||||
|
||||
SAFE_FREE( dav_session.user );
|
||||
SAFE_FREE( dav_session.pwd );
|
||||
SAFE_FREE( dav_session.session_key);
|
||||
SAFE_FREE( dav_session.error_string );
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.user );
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.pwd );
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.session_key);
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.error_string );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int owncloud_set_property(const char *key, void *data) {
|
||||
void owncloud_destroy(CSYNC* ctx)
|
||||
{
|
||||
owncloud_commit(ctx);
|
||||
SAFE_FREE(ctx->owncloud_context);
|
||||
ctx->owncloud_context = 0;
|
||||
}
|
||||
|
||||
int owncloud_set_property(CSYNC* ctx, const char *key, void *data) {
|
||||
#define READ_STRING_PROPERTY(P) \
|
||||
if (c_streq(key, #P)) { \
|
||||
SAFE_FREE(dav_session.P); \
|
||||
dav_session.P = c_strdup((const char*)data); \
|
||||
SAFE_FREE(ctx->owncloud_context->dav_session.P); \
|
||||
ctx->owncloud_context->dav_session.P = c_strdup((const char*)data); \
|
||||
return 0; \
|
||||
}
|
||||
READ_STRING_PROPERTY(session_key)
|
||||
|
@ -884,48 +851,47 @@ int owncloud_set_property(const char *key, void *data) {
|
|||
#undef READ_STRING_PROPERTY
|
||||
|
||||
if (c_streq(key, "proxy_port")) {
|
||||
dav_session.proxy_port = *(int*)(data);
|
||||
ctx->owncloud_context->dav_session.proxy_port = *(int*)(data);
|
||||
return 0;
|
||||
}
|
||||
if (c_streq(key, "read_timeout") || c_streq(key, "timeout")) {
|
||||
dav_session.read_timeout = *(int*)(data);
|
||||
ctx->owncloud_context->dav_session.read_timeout = *(int*)(data);
|
||||
return 0;
|
||||
}
|
||||
if( c_streq(key, "csync_context")) {
|
||||
dav_session.csync_ctx = data;
|
||||
ctx->owncloud_context->dav_session.csync_ctx = data;
|
||||
return 0;
|
||||
}
|
||||
if( c_streq(key, "get_dav_session")) {
|
||||
/* Give the ne_session to the caller */
|
||||
*(ne_session**)data = dav_session.ctx;
|
||||
*(ne_session**)data = ctx->owncloud_context->dav_session.ctx;
|
||||
return 0;
|
||||
}
|
||||
if( c_streq(key, "no_recursive_propfind")) {
|
||||
dav_session.no_recursive_propfind = *(bool*)(data);
|
||||
ctx->owncloud_context->dav_session.no_recursive_propfind = *(bool*)(data);
|
||||
return 0;
|
||||
}
|
||||
if( c_streq(key, "redirect_callback")) {
|
||||
if (data) {
|
||||
csync_owncloud_redirect_callback_t* cb_wrapper = data;
|
||||
|
||||
dav_session.redir_callback = *cb_wrapper;
|
||||
ctx->owncloud_context->dav_session.redir_callback = *cb_wrapper;
|
||||
} else {
|
||||
dav_session.redir_callback = NULL;
|
||||
ctx->owncloud_context->dav_session.redir_callback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void owncloud_init(void *userdata) {
|
||||
void owncloud_init(CSYNC* ctx) {
|
||||
|
||||
_userdata = userdata;
|
||||
_connected = 0; /* triggers dav_connect to go through the whole neon setup */
|
||||
|
||||
memset(&dav_session, 0, sizeof(dav_session));
|
||||
ctx->owncloud_context = c_malloc( sizeof( struct csync_owncloud_ctx_s ));
|
||||
ctx->owncloud_context->csync_ctx = ctx; // back reference
|
||||
ctx->owncloud_context->is_first_propfind = true;
|
||||
|
||||
/* Disable it, Mirall can enable it for the first sync (= no DB)*/
|
||||
dav_session.no_recursive_propfind = true;
|
||||
ctx->owncloud_context->dav_session.no_recursive_propfind = true;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et cindent: */
|
||||
|
|
|
@ -21,160 +21,18 @@
|
|||
#ifndef CSYNC_OWNCLOUD_H
|
||||
#define CSYNC_OWNCLOUD_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "config_csync.h"
|
||||
#ifdef NEON_WITH_LFS /* Switch on LFS in libneon. Never remove the NE_LFS! */
|
||||
#define NE_LFS
|
||||
#endif
|
||||
|
||||
#include <neon/ne_basic.h>
|
||||
#include <neon/ne_socket.h>
|
||||
#include <neon/ne_session.h>
|
||||
#include <neon/ne_request.h>
|
||||
#include <neon/ne_props.h>
|
||||
#include <neon/ne_auth.h>
|
||||
#include <neon/ne_dates.h>
|
||||
#include <neon/ne_compress.h>
|
||||
#include <neon/ne_redirect.h>
|
||||
|
||||
|
||||
#include "c_rbtree.h"
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "csync.h"
|
||||
#include "csync_misc.h"
|
||||
#include "csync_macros.h"
|
||||
#include "c_private.h"
|
||||
#include "httpbf.h"
|
||||
|
||||
#include "vio/csync_vio_file_stat.h"
|
||||
#include "vio/csync_vio.h"
|
||||
|
||||
#include "csync_log.h"
|
||||
|
||||
|
||||
#define DEBUG_WEBDAV(...) csync_log( 9, "oc_module", __VA_ARGS__);
|
||||
|
||||
enum resource_type {
|
||||
resr_normal = 0,
|
||||
resr_collection,
|
||||
resr_reference,
|
||||
resr_error
|
||||
};
|
||||
|
||||
/* Struct to store data for each resource found during an opendir operation.
|
||||
* It represents a single file entry.
|
||||
*/
|
||||
|
||||
typedef struct resource {
|
||||
char *uri; /* The complete uri */
|
||||
char *name; /* The filename only */
|
||||
|
||||
enum resource_type type;
|
||||
int64_t size;
|
||||
time_t modtime;
|
||||
char* md5;
|
||||
char file_id[FILE_ID_BUF_SIZE+1];
|
||||
|
||||
struct resource *next;
|
||||
} resource;
|
||||
|
||||
/* Struct to hold the context of a WebDAV PropFind operation to fetch
|
||||
* a directory listing from the server.
|
||||
*/
|
||||
struct listdir_context {
|
||||
struct resource *list; /* The list of result resources */
|
||||
struct resource *currResource; /* A pointer to the current resource */
|
||||
char *target; /* Request-URI of the PROPFIND */
|
||||
unsigned int result_count; /* number of elements stored in list */
|
||||
int ref; /* reference count, only destroy when it reaches 0 */
|
||||
};
|
||||
|
||||
|
||||
/* Our cache, key is a char* */
|
||||
extern c_rbtree_t *propfind_recursive_cache;
|
||||
/* Values are propfind_recursive_element: */
|
||||
struct propfind_recursive_element {
|
||||
struct resource *self;
|
||||
struct resource *children;
|
||||
struct propfind_recursive_element *parent;
|
||||
};
|
||||
typedef struct propfind_recursive_element propfind_recursive_element_t;
|
||||
void clear_propfind_recursive_cache(void);
|
||||
struct listdir_context *get_listdir_context_from_recursive_cache(const char *curi);
|
||||
void fill_recursive_propfind_cache(const char *uri, const char *curi);
|
||||
struct listdir_context *get_listdir_context_from_cache(const char *curi);
|
||||
void fetch_resource_list_recursive(const char *uri, const char *curi);
|
||||
|
||||
typedef int (*csync_owncloud_redirect_callback_t)(CSYNC* ctx, const char* uri);
|
||||
|
||||
/* Struct with the WebDAV session */
|
||||
struct dav_session_s {
|
||||
ne_session *ctx;
|
||||
char *user;
|
||||
char *pwd;
|
||||
|
||||
char *proxy_type;
|
||||
char *proxy_host;
|
||||
int proxy_port;
|
||||
char *proxy_user;
|
||||
char *proxy_pwd;
|
||||
|
||||
char *session_key;
|
||||
|
||||
char *error_string;
|
||||
|
||||
int read_timeout;
|
||||
|
||||
CSYNC *csync_ctx;
|
||||
|
||||
bool no_recursive_propfind;
|
||||
|
||||
csync_owncloud_redirect_callback_t redir_callback;
|
||||
};
|
||||
extern struct dav_session_s dav_session;
|
||||
|
||||
/* The list of properties that is fetched in PropFind on a collection */
|
||||
static const ne_propname ls_props[] = {
|
||||
{ "DAV:", "getlastmodified" },
|
||||
{ "DAV:", "getcontentlength" },
|
||||
{ "DAV:", "resourcetype" },
|
||||
{ "DAV:", "getetag"},
|
||||
{ "http://owncloud.org/ns", "id"},
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
void set_errno_from_http_errcode( int err );
|
||||
void set_error_message( const char *msg );
|
||||
void set_errno_from_neon_errcode( int neon_code );
|
||||
int http_result_code_from_session(void);
|
||||
void set_errno_from_session(void);
|
||||
|
||||
time_t oc_httpdate_parse( const char *date );
|
||||
|
||||
char *_cleanPath( const char* uri );
|
||||
|
||||
int _stat_perms( int type );
|
||||
void resourceToFileStat( csync_vio_file_stat_t *lfs, struct resource *res );
|
||||
void resource_free(struct resource* o);
|
||||
struct resource* resource_dup(struct resource* o);
|
||||
|
||||
// Public API from vio
|
||||
csync_vio_handle_t *owncloud_opendir(const char *uri);
|
||||
csync_vio_file_stat_t *owncloud_readdir(csync_vio_handle_t *dhandle);
|
||||
int owncloud_closedir(csync_vio_handle_t *dhandle);
|
||||
int owncloud_commit(void);
|
||||
char *owncloud_error_string(void);
|
||||
void owncloud_init(void *userdata);
|
||||
int owncloud_set_property(const char *key, void *data);
|
||||
// Public API used by csync
|
||||
csync_vio_handle_t *owncloud_opendir(CSYNC* ctx, const char *uri);
|
||||
csync_vio_file_stat_t *owncloud_readdir(CSYNC* ctx, csync_vio_handle_t *dhandle);
|
||||
int owncloud_closedir(CSYNC* ctx, csync_vio_handle_t *dhandle);
|
||||
int owncloud_commit(CSYNC* ctx);
|
||||
void owncloud_destroy(CSYNC* ctx);
|
||||
char *owncloud_error_string(CSYNC* ctx);
|
||||
void owncloud_init(CSYNC* ctx);
|
||||
int owncloud_set_property(CSYNC* ctx, const char *key, void *data);
|
||||
|
||||
#endif /* CSYNC_OWNCLOUD_H */
|
||||
|
|
193
csync/src/csync_owncloud_private.h
Normal file
193
csync/src/csync_owncloud_private.h
Normal file
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2011 by Andreas Schneider <asn@cryptomilk.org>
|
||||
* Copyright (c) 2012 by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef CSYNC_OWNCLOUD_PRIVATE_H
|
||||
#define CSYNC_OWNCLOUD_PRIVATE_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "config_csync.h"
|
||||
#ifdef NEON_WITH_LFS /* Switch on LFS in libneon. Never remove the NE_LFS! */
|
||||
#define NE_LFS
|
||||
#endif
|
||||
|
||||
#include <neon/ne_basic.h>
|
||||
#include <neon/ne_socket.h>
|
||||
#include <neon/ne_session.h>
|
||||
#include <neon/ne_request.h>
|
||||
#include <neon/ne_props.h>
|
||||
#include <neon/ne_auth.h>
|
||||
#include <neon/ne_dates.h>
|
||||
#include <neon/ne_compress.h>
|
||||
#include <neon/ne_redirect.h>
|
||||
|
||||
|
||||
#include "c_rbtree.h"
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "csync.h"
|
||||
#include "csync_misc.h"
|
||||
#include "csync_macros.h"
|
||||
#include "c_private.h"
|
||||
#include "httpbf.h"
|
||||
|
||||
#include "vio/csync_vio_file_stat.h"
|
||||
#include "vio/csync_vio.h"
|
||||
|
||||
#include "csync_log.h"
|
||||
|
||||
#include "csync_owncloud.h"
|
||||
|
||||
|
||||
#define DEBUG_WEBDAV(...) csync_log( 9, "oc_module", __VA_ARGS__);
|
||||
|
||||
typedef int (*csync_owncloud_redirect_callback_t)(CSYNC* ctx, const char* uri);
|
||||
|
||||
/* Struct with the WebDAV session */
|
||||
struct dav_session_s {
|
||||
ne_session *ctx;
|
||||
char *user;
|
||||
char *pwd;
|
||||
|
||||
char *proxy_type;
|
||||
char *proxy_host;
|
||||
int proxy_port;
|
||||
char *proxy_user;
|
||||
char *proxy_pwd;
|
||||
|
||||
char *session_key;
|
||||
|
||||
char *error_string;
|
||||
|
||||
int read_timeout;
|
||||
|
||||
CSYNC *csync_ctx;
|
||||
|
||||
bool no_recursive_propfind;
|
||||
|
||||
csync_owncloud_redirect_callback_t redir_callback;
|
||||
};
|
||||
|
||||
struct csync_owncloud_ctx_s {
|
||||
CSYNC *csync_ctx;
|
||||
|
||||
// For the PROPFIND results
|
||||
bool is_first_propfind;
|
||||
struct listdir_context *propfind_cache;
|
||||
c_rbtree_t *propfind_recursive_cache;
|
||||
int propfind_recursive_cache_depth;
|
||||
int propfind_recursive_cache_file_count;
|
||||
int propfind_recursive_cache_folder_count;
|
||||
|
||||
// For the WebDAV connection
|
||||
struct dav_session_s dav_session; /* The DAV Session, initialised in dav_connect */
|
||||
int _connected; /* flag to indicate if a connection exists, ie.
|
||||
the dav_session is valid */
|
||||
};
|
||||
typedef struct csync_owncloud_ctx_s csync_owncloud_ctx_t;
|
||||
//typedef csync_owncloud_ctx_t* csync_owncloud_ctx_p;
|
||||
|
||||
enum resource_type {
|
||||
resr_normal = 0,
|
||||
resr_collection,
|
||||
resr_reference,
|
||||
resr_error
|
||||
};
|
||||
|
||||
/* The list of properties that is fetched in PropFind on a collection */
|
||||
static const ne_propname ls_props[] = {
|
||||
{ "DAV:", "getlastmodified" },
|
||||
{ "DAV:", "getcontentlength" },
|
||||
{ "DAV:", "resourcetype" },
|
||||
{ "DAV:", "getetag"},
|
||||
{ "http://owncloud.org/ns", "id"},
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* Struct to store data for each resource found during an opendir operation.
|
||||
* It represents a single file entry.
|
||||
*/
|
||||
typedef struct resource {
|
||||
char *uri; /* The complete uri */
|
||||
char *name; /* The filename only */
|
||||
|
||||
enum resource_type type;
|
||||
int64_t size;
|
||||
time_t modtime;
|
||||
char* md5;
|
||||
char file_id[FILE_ID_BUF_SIZE+1];
|
||||
|
||||
struct resource *next;
|
||||
} resource;
|
||||
|
||||
/* Struct to hold the context of a WebDAV PropFind operation to fetch
|
||||
* a directory listing from the server.
|
||||
*/
|
||||
struct listdir_context {
|
||||
struct resource *list; /* The list of result resources */
|
||||
struct resource *currResource; /* A pointer to the current resource */
|
||||
char *target; /* Request-URI of the PROPFIND */
|
||||
unsigned int result_count; /* number of elements stored in list */
|
||||
int ref; /* reference count, only destroy when it reaches 0 */
|
||||
};
|
||||
|
||||
|
||||
/* Values are propfind_recursive_element: */
|
||||
struct propfind_recursive_element {
|
||||
struct resource *self;
|
||||
struct resource *children;
|
||||
struct propfind_recursive_element *parent;
|
||||
};
|
||||
typedef struct propfind_recursive_element propfind_recursive_element_t;
|
||||
|
||||
void clear_propfind_recursive_cache(csync_owncloud_ctx_t *ctx);
|
||||
struct listdir_context *get_listdir_context_from_recursive_cache(csync_owncloud_ctx_t *ctx, const char *curi);
|
||||
void fill_recursive_propfind_cache(csync_owncloud_ctx_t *ctx, const char *uri, const char *curi);
|
||||
struct listdir_context *get_listdir_context_from_cache(csync_owncloud_ctx_t *ctx, const char *curi);
|
||||
void fetch_resource_list_recursive(csync_owncloud_ctx_t *ctx, const char *uri, const char *curi);
|
||||
|
||||
void set_errno_from_http_errcode( int err );
|
||||
void set_error_message( csync_owncloud_ctx_t *ctx, const char *msg );
|
||||
void set_errno_from_neon_errcode(csync_owncloud_ctx_t *ctx, int neon_code );
|
||||
int http_result_code_from_session(csync_owncloud_ctx_t *ctx);
|
||||
void set_errno_from_session(csync_owncloud_ctx_t *ctx);
|
||||
|
||||
time_t oc_httpdate_parse( const char *date );
|
||||
|
||||
char *_cleanPath( const char* uri );
|
||||
|
||||
int _stat_perms( int type );
|
||||
void resourceToFileStat( csync_vio_file_stat_t *lfs, struct resource *res );
|
||||
void resource_free(struct resource* o);
|
||||
struct resource* resource_dup(struct resource* o);
|
||||
void free_fetchCtx( struct listdir_context *ctx );
|
||||
|
||||
|
||||
|
||||
#endif // CSYNC_OWNCLOUD_PRIVATE_H
|
|
@ -20,14 +20,7 @@
|
|||
*/
|
||||
|
||||
#include "csync_owncloud.h"
|
||||
|
||||
c_rbtree_t *propfind_recursive_cache = NULL;
|
||||
int propfind_recursive_cache_depth = 0;
|
||||
int propfind_recursive_cache_file_count = 0;
|
||||
int propfind_recursive_cache_folder_count = 0;
|
||||
|
||||
|
||||
|
||||
#include "csync_owncloud_private.h"
|
||||
|
||||
static void _tree_destructor(void *data) {
|
||||
propfind_recursive_element_t *element = data;
|
||||
|
@ -36,27 +29,27 @@ static void _tree_destructor(void *data) {
|
|||
SAFE_FREE(element);
|
||||
}
|
||||
|
||||
void clear_propfind_recursive_cache(void)
|
||||
void clear_propfind_recursive_cache(csync_owncloud_ctx_t *ctx)
|
||||
{
|
||||
if (propfind_recursive_cache) {
|
||||
if (ctx->propfind_recursive_cache) {
|
||||
DEBUG_WEBDAV("clear_propfind_recursive_cache Invalidating..");
|
||||
c_rbtree_destroy(propfind_recursive_cache, _tree_destructor);
|
||||
propfind_recursive_cache = NULL;
|
||||
c_rbtree_destroy(ctx->propfind_recursive_cache, _tree_destructor);
|
||||
ctx->propfind_recursive_cache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct listdir_context *get_listdir_context_from_recursive_cache(const char *curi)
|
||||
struct listdir_context *get_listdir_context_from_recursive_cache(csync_owncloud_ctx_t *ctx, const char *curi)
|
||||
{
|
||||
propfind_recursive_element_t *element = NULL;
|
||||
struct listdir_context *fetchCtx = NULL;
|
||||
struct resource *iterator, *r;
|
||||
|
||||
if (!propfind_recursive_cache) {
|
||||
if (!ctx->propfind_recursive_cache) {
|
||||
DEBUG_WEBDAV("get_listdir_context_from_recursive_cache No cache");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
element = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache, curi));
|
||||
element = c_rbtree_node_data(c_rbtree_find(ctx->propfind_recursive_cache, curi));
|
||||
if (!element) {
|
||||
DEBUG_WEBDAV("get_listdir_context_from_recursive_cache No element %s in cache found", curi);
|
||||
return NULL;
|
||||
|
@ -111,16 +104,15 @@ static void propfind_results_recursive(void *userdata,
|
|||
const ne_status *status = NULL;
|
||||
char *path = ne_path_unescape( uri->path );
|
||||
char *parentPath;
|
||||
char *propfindRootUri = (char*) userdata;
|
||||
propfind_recursive_element_t *element = NULL;
|
||||
propfind_recursive_element_t *pElement = NULL;
|
||||
int depth = 0;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
|
||||
(void) status;
|
||||
(void) propfindRootUri;
|
||||
|
||||
if (!propfind_recursive_cache) {
|
||||
c_rbtree_create(&propfind_recursive_cache, _key_cmp, _data_cmp);
|
||||
if (!ctx->propfind_recursive_cache) {
|
||||
c_rbtree_create(&ctx->propfind_recursive_cache, _key_cmp, _data_cmp);
|
||||
}
|
||||
|
||||
/* Fill the resource structure with the data about the file */
|
||||
|
@ -139,10 +131,10 @@ static void propfind_results_recursive(void *userdata,
|
|||
newres->type = resr_normal;
|
||||
if( resourcetype && strncmp( resourcetype, "<DAV:collection>", 16 ) == 0) {
|
||||
newres->type = resr_collection;
|
||||
propfind_recursive_cache_folder_count++;
|
||||
ctx->propfind_recursive_cache_folder_count++;
|
||||
} else {
|
||||
/* DEBUG_WEBDAV("propfind_results_recursive %s [%d]", newres->uri, newres->type); */
|
||||
propfind_recursive_cache_file_count++;
|
||||
ctx->propfind_recursive_cache_file_count++;
|
||||
}
|
||||
|
||||
if (modtime) {
|
||||
|
@ -169,7 +161,7 @@ static void propfind_results_recursive(void *userdata,
|
|||
if (newres->type == resr_collection) {
|
||||
DEBUG_WEBDAV("propfind_results_recursive %s is a folder", newres->uri);
|
||||
/* Check if in rb tree */
|
||||
element = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache,uri->path));
|
||||
element = c_rbtree_node_data(c_rbtree_find(ctx->propfind_recursive_cache,uri->path));
|
||||
/* If not, create a new item and insert it */
|
||||
if (!element) {
|
||||
element = c_malloc(sizeof(propfind_recursive_element_t));
|
||||
|
@ -177,7 +169,7 @@ static void propfind_results_recursive(void *userdata,
|
|||
element->self->next = 0;
|
||||
element->children = NULL;
|
||||
element->parent = NULL;
|
||||
c_rbtree_insert(propfind_recursive_cache, element);
|
||||
c_rbtree_insert(ctx->propfind_recursive_cache, element);
|
||||
/* DEBUG_WEBDAV("results_recursive Added collection %s", newres->uri); */
|
||||
}
|
||||
}
|
||||
|
@ -187,7 +179,7 @@ static void propfind_results_recursive(void *userdata,
|
|||
if (parentPath) {
|
||||
propfind_recursive_element_t *parentElement = NULL;
|
||||
|
||||
parentElement = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache,parentPath));
|
||||
parentElement = c_rbtree_node_data(c_rbtree_find(ctx->propfind_recursive_cache,parentPath));
|
||||
free(parentPath);
|
||||
|
||||
if (parentElement) {
|
||||
|
@ -203,9 +195,9 @@ static void propfind_results_recursive(void *userdata,
|
|||
depth++;
|
||||
pElement = pElement->parent;
|
||||
}
|
||||
if (depth > propfind_recursive_cache_depth) {
|
||||
if (depth > ctx->propfind_recursive_cache_depth) {
|
||||
DEBUG_WEBDAV("propfind_results_recursive %s new maximum tree depth %d", newres->uri, depth);
|
||||
propfind_recursive_cache_depth = depth;
|
||||
ctx->propfind_recursive_cache_depth = depth;
|
||||
}
|
||||
|
||||
/* DEBUG_WEBDAV("results_recursive Added child %s to collection %s", newres->uri, element->self->uri); */
|
||||
|
@ -218,7 +210,7 @@ static void propfind_results_recursive(void *userdata,
|
|||
|
||||
}
|
||||
|
||||
void fetch_resource_list_recursive(const char *uri, const char *curi)
|
||||
void fetch_resource_list_recursive(csync_owncloud_ctx_t *ctx, const char *uri, const char *curi)
|
||||
{
|
||||
int ret = 0;
|
||||
ne_propfind_handler *hdl = NULL;
|
||||
|
@ -230,10 +222,10 @@ void fetch_resource_list_recursive(const char *uri, const char *curi)
|
|||
DEBUG_WEBDAV("fetch_resource_list_recursive Starting recursive propfind %s %s", uri, curi);
|
||||
|
||||
/* do a propfind request and parse the results in the results function, set as callback */
|
||||
hdl = ne_propfind_create(dav_session.ctx, curi, depth);
|
||||
hdl = ne_propfind_create(ctx->dav_session.ctx, curi, depth);
|
||||
|
||||
if(hdl) {
|
||||
ret = ne_propfind_named(hdl, ls_props, propfind_results_recursive, (void*)curi);
|
||||
ret = ne_propfind_named(hdl, ls_props, propfind_results_recursive, ctx);
|
||||
request = ne_propfind_get_request( hdl );
|
||||
req_status = ne_get_status( request );
|
||||
}
|
||||
|
@ -245,14 +237,14 @@ void fetch_resource_list_recursive(const char *uri, const char *curi)
|
|||
DEBUG_WEBDAV("ERROR: Request failed: status %d (%s)", req_status->code,
|
||||
req_status->reason_phrase);
|
||||
ret = NE_CONNECT;
|
||||
set_error_message(req_status->reason_phrase);
|
||||
set_error_message(ctx, req_status->reason_phrase);
|
||||
}
|
||||
DEBUG_WEBDAV("Recursive propfind result code %d.", req_status ? req_status->code : 0);
|
||||
} else {
|
||||
if( ret == NE_ERROR && req_status->code == 404) {
|
||||
errno = ENOENT;
|
||||
} else {
|
||||
set_errno_from_neon_errcode(ret);
|
||||
set_errno_from_neon_errcode(ctx, ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,7 +259,7 @@ void fetch_resource_list_recursive(const char *uri, const char *curi)
|
|||
DEBUG_WEBDAV("ERROR: Content type of propfind request not XML: %s.",
|
||||
content_type ? content_type: "<empty>");
|
||||
errno = ERRNO_WRONG_CONTENT;
|
||||
set_error_message("Server error: PROPFIND reply is not XML formatted!");
|
||||
set_error_message(ctx, "Server error: PROPFIND reply is not XML formatted!");
|
||||
ret = NE_CONNECT;
|
||||
}
|
||||
}
|
||||
|
@ -275,7 +267,7 @@ void fetch_resource_list_recursive(const char *uri, const char *curi)
|
|||
if( ret != NE_OK ) {
|
||||
const char *err = NULL;
|
||||
|
||||
err = ne_get_error( dav_session.ctx );
|
||||
err = ne_get_error( ctx->dav_session.ctx );
|
||||
DEBUG_WEBDAV("WRN: propfind named failed with %d, request error: %s", ret, err ? err : "<nil>");
|
||||
}
|
||||
|
||||
|
@ -290,22 +282,21 @@ void fetch_resource_list_recursive(const char *uri, const char *curi)
|
|||
}
|
||||
|
||||
/* Called by owncloud_opendir()->fetch_resource_list() to fill the cache */
|
||||
extern struct listdir_context *propfind_cache;
|
||||
void fill_recursive_propfind_cache(const char *uri, const char *curi) {
|
||||
fetch_resource_list_recursive(uri, curi);
|
||||
void fill_recursive_propfind_cache(csync_owncloud_ctx_t *ctx, const char *uri, const char *curi) {
|
||||
fetch_resource_list_recursive(ctx, uri, curi);
|
||||
|
||||
if (propfind_recursive_cache_depth <= 2) {
|
||||
if (ctx->propfind_recursive_cache_depth <= 2) {
|
||||
DEBUG_WEBDAV("fill_recursive_propfind_cache %s Server maybe did not give us an 'infinity' depth result", curi);
|
||||
/* transform the cache to the normal cache in propfind_cache */
|
||||
propfind_cache = get_listdir_context_from_recursive_cache(curi);
|
||||
ctx->propfind_cache = get_listdir_context_from_recursive_cache(ctx, curi);
|
||||
/* clear the cache, it is bogus since the server returned only results for Depth 1 */
|
||||
clear_propfind_recursive_cache();
|
||||
clear_propfind_recursive_cache(ctx);
|
||||
} else {
|
||||
DEBUG_WEBDAV("fill_recursive_propfind_cache %s We received %d elements deep for 'infinity' depth (%d folders, %d files)",
|
||||
curi,
|
||||
propfind_recursive_cache_depth,
|
||||
propfind_recursive_cache_folder_count,
|
||||
propfind_recursive_cache_file_count);
|
||||
ctx->propfind_recursive_cache_depth,
|
||||
ctx->propfind_recursive_cache_folder_count,
|
||||
ctx->propfind_recursive_cache_file_count);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,13 +20,15 @@
|
|||
*/
|
||||
|
||||
#include "csync_owncloud.h"
|
||||
#include "csync_owncloud_private.h"
|
||||
|
||||
#include "csync_misc.h"
|
||||
|
||||
void set_error_message( const char *msg )
|
||||
void set_error_message( csync_owncloud_ctx_t *ctx, const char *msg )
|
||||
{
|
||||
SAFE_FREE(dav_session.error_string);
|
||||
SAFE_FREE(ctx->dav_session.error_string);
|
||||
if( msg )
|
||||
dav_session.error_string = c_strdup(msg);
|
||||
ctx->dav_session.error_string = c_strdup(msg);
|
||||
}
|
||||
|
||||
void set_errno_from_http_errcode( int err ) {
|
||||
|
@ -104,12 +106,12 @@ void set_errno_from_http_errcode( int err ) {
|
|||
errno = new_errno;
|
||||
}
|
||||
|
||||
int http_result_code_from_session() {
|
||||
const char *p = ne_get_error( dav_session.ctx );
|
||||
int http_result_code_from_session(csync_owncloud_ctx_t *ctx) {
|
||||
const char *p = ne_get_error( ctx->dav_session.ctx );
|
||||
char *q;
|
||||
int err;
|
||||
|
||||
set_error_message(p); /* remember the error message */
|
||||
set_error_message(ctx, p); /* remember the error message */
|
||||
|
||||
err = strtol(p, &q, 10);
|
||||
if (p == q) {
|
||||
|
@ -118,8 +120,8 @@ int http_result_code_from_session() {
|
|||
return err;
|
||||
}
|
||||
|
||||
void set_errno_from_session() {
|
||||
int err = http_result_code_from_session();
|
||||
void set_errno_from_session(csync_owncloud_ctx_t *ctx) {
|
||||
int err = http_result_code_from_session(ctx);
|
||||
|
||||
if( err == EIO || err == ERRNO_ERROR_STRING) {
|
||||
errno = err;
|
||||
|
@ -128,7 +130,7 @@ void set_errno_from_session() {
|
|||
}
|
||||
}
|
||||
|
||||
void set_errno_from_neon_errcode( int neon_code ) {
|
||||
void set_errno_from_neon_errcode(csync_owncloud_ctx_t *ctx, int neon_code ) {
|
||||
|
||||
if( neon_code != NE_OK ) {
|
||||
DEBUG_WEBDAV("Neon error code was %d", neon_code);
|
||||
|
@ -137,7 +139,7 @@ void set_errno_from_neon_errcode( int neon_code ) {
|
|||
switch(neon_code) {
|
||||
case NE_OK: /* Success, but still the possiblity of problems */
|
||||
case NE_ERROR: /* Generic error; use ne_get_error(session) for message */
|
||||
set_errno_from_session(); /* Something wrong with http communication */
|
||||
set_errno_from_session(ctx); /* Something wrong with http communication */
|
||||
break;
|
||||
case NE_LOOKUP: /* Server or proxy hostname lookup failed */
|
||||
errno = ERRNO_LOOKUP_ERROR;
|
||||
|
@ -361,3 +363,28 @@ void resource_free(struct resource* o) {
|
|||
SAFE_FREE(old);
|
||||
}
|
||||
}
|
||||
|
||||
void free_fetchCtx( struct listdir_context *ctx )
|
||||
{
|
||||
struct resource *newres, *res;
|
||||
if( ! ctx ) return;
|
||||
newres = ctx->list;
|
||||
res = newres;
|
||||
|
||||
ctx->ref--;
|
||||
if (ctx->ref > 0) return;
|
||||
|
||||
SAFE_FREE(ctx->target);
|
||||
|
||||
while( res ) {
|
||||
SAFE_FREE(res->uri);
|
||||
SAFE_FREE(res->name);
|
||||
SAFE_FREE(res->md5);
|
||||
memset( res->file_id, 0, FILE_ID_BUF_SIZE+1 );
|
||||
|
||||
newres = res->next;
|
||||
SAFE_FREE(res);
|
||||
res = newres;
|
||||
}
|
||||
SAFE_FREE(ctx);
|
||||
}
|
||||
|
|
|
@ -90,6 +90,8 @@ enum csync_replica_e {
|
|||
|
||||
typedef struct csync_file_stat_s csync_file_stat_t;
|
||||
|
||||
struct csync_owncloud_ctx_s; // csync_owncloud.c
|
||||
|
||||
/**
|
||||
* @brief csync public structure
|
||||
*/
|
||||
|
@ -162,6 +164,8 @@ struct csync_s {
|
|||
volatile int abort;
|
||||
void *rename_info;
|
||||
int read_from_db_disabled;
|
||||
|
||||
struct csync_owncloud_ctx_s *owncloud_context;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ csync_vio_handle_t *csync_vio_opendir(CSYNC *ctx, const char *name) {
|
|||
if(ctx->remote.read_from_db) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Read from db flag is true, should not!" );
|
||||
}
|
||||
return owncloud_opendir(name);
|
||||
return owncloud_opendir(ctx, name);
|
||||
break;
|
||||
case LOCAL_REPLICA:
|
||||
return csync_vio_local_opendir(name);
|
||||
|
@ -69,7 +69,7 @@ int csync_vio_closedir(CSYNC *ctx, csync_vio_handle_t *dhandle) {
|
|||
if( ctx->remote.read_from_db ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Remote ReadFromDb is true, should not!");
|
||||
}
|
||||
rc = owncloud_closedir(dhandle);
|
||||
rc = owncloud_closedir(ctx, dhandle);
|
||||
break;
|
||||
case LOCAL_REPLICA:
|
||||
rc = csync_vio_local_closedir(dhandle);
|
||||
|
@ -87,7 +87,7 @@ csync_vio_file_stat_t *csync_vio_readdir(CSYNC *ctx, csync_vio_handle_t *dhandle
|
|||
if( ctx->remote.read_from_db ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Remote readfromdb is true, should not!");
|
||||
}
|
||||
return owncloud_readdir(dhandle);
|
||||
return owncloud_readdir(ctx, dhandle);
|
||||
break;
|
||||
case LOCAL_REPLICA:
|
||||
return csync_vio_local_readdir(dhandle);
|
||||
|
@ -127,15 +127,15 @@ char *csync_vio_get_status_string(CSYNC *ctx) {
|
|||
if(ctx->error_string) {
|
||||
return ctx->error_string;
|
||||
}
|
||||
return owncloud_error_string();
|
||||
return owncloud_error_string(ctx);
|
||||
}
|
||||
|
||||
int csync_vio_set_property(CSYNC* ctx, const char* key, void* data) {
|
||||
(void) ctx;
|
||||
return owncloud_set_property(key, data);
|
||||
return owncloud_set_property(ctx, key, data);
|
||||
}
|
||||
|
||||
int csync_vio_commit(CSYNC *ctx) {
|
||||
(void) ctx;
|
||||
return owncloud_commit();
|
||||
return owncloud_commit(ctx);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue