diff --git a/modules/csync_owncloud.c b/modules/csync_owncloud.c index b49eb3a7ac..555cb3bc74 100644 --- a/modules/csync_owncloud.c +++ b/modules/csync_owncloud.c @@ -52,7 +52,7 @@ #include "csync_log.h" #if 1 || defined(NDEBUG) -#define DEBUG_WEBDAV(...) { printf(__VA_ARGS__); printf("\n"); } +#define DEBUG_WEBDAV(...) #else // FIXME: can't use CSYNC_LOG here because there is no ctx #define DEBUG_WEBDAV(...) CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, __VA_ARGS__) #endif @@ -153,6 +153,8 @@ int _connected = 0; /* flag to indicate if a connection exists csync_vio_file_stat_t _fs; csync_auth_callback _authcb; +csync_progress_callback _progresscb; + #define PUT_BUFFER_SIZE 1024*5 @@ -559,6 +561,17 @@ static void request_created_hook(ne_request *req, void *userdata, } +static void ne_notify_status_cb (void *userdata, ne_session_status status, + const ne_session_status_info *info) +{ + struct transfer_context *tc = (struct transfer_context*) userdata; +// printf("ne_notify_status %i %s %ld %ld\n", status, tc->clean_uri, info->sr.progress, info->sr.total); + + if (_progresscb && (status == ne_status_sending || status == ne_status_recving)) + _progresscb(tc->clean_uri, CSYNC_NOTIFY_PROGRESS, info->sr.progress, info->sr.total, dav_session.userdata); +} + + /* * Connect to a DAV server * This function sets the flag _connected if the connection is established @@ -1527,11 +1540,15 @@ static int owncloud_sendfile(csync_vio_method_handle_t *src, csync_vio_method_ha /* Attach the request to the file descriptor */ ne_set_request_body_fd(request, fd, 0, sb.st_size ); + if (_progresscb) { + ne_set_notifier(dav_session.ctx, ne_notify_status_cb, write_ctx); + _progresscb(write_ctx->clean_uri, CSYNC_NOTIFY_START_UPLOAD, 0 , 0, dav_session.userdata); + } + /* Start the request. */ rc = ne_request_dispatch( write_ctx->req ); if( rc != NE_OK ) { set_errno_from_neon_errcode( rc ); - return rc; } else { status = ne_get_status( request ); if( status->klass != 2 ) { @@ -1542,6 +1559,11 @@ static int owncloud_sendfile(csync_vio_method_handle_t *src, csync_vio_method_ha DEBUG_WEBDAV("http request all cool, result code %d", status->code); } } + if (_progresscb) { + ne_set_notifier(dav_session.ctx, 0, 0); + _progresscb(write_ctx->clean_uri, rc != NE_OK ? CSYNC_NOTFY_ERROR : CSYNC_NOTIFY_FINISHED, + 0, 0, dav_session.userdata); + } } else { DEBUG_WEBDAV("Could not stat file descriptor"); } @@ -1552,6 +1574,10 @@ static int owncloud_sendfile(csync_vio_method_handle_t *src, csync_vio_method_ha /* GET a file to the file descriptor */ /* actually do the request */ write_ctx->fd = fd; + if (_progresscb) { + ne_set_notifier(dav_session.ctx, ne_notify_status_cb, write_ctx); + _progresscb(write_ctx->clean_uri, CSYNC_NOTIFY_START_UPLOAD, 0 , 0, dav_session.userdata); + } rc = ne_request_dispatch(write_ctx->req ); /* possible return codes are: * NE_OK, NE_AUTH, NE_CONNECT, NE_TIMEOUT, NE_ERROR (from ne_request.h) @@ -1572,6 +1598,11 @@ static int owncloud_sendfile(csync_vio_method_handle_t *src, csync_vio_method_ha if( write_ctx->decompress ) { ne_decompress_destroy( write_ctx->decompress ); } + if (_progresscb) { + ne_set_notifier(dav_session.ctx, 0, 0); + _progresscb(write_ctx->clean_uri, (rc != NE_OK) ? CSYNC_NOTFY_ERROR : CSYNC_NOTIFY_FINISHED, + 0,0, dav_session.userdata); + } } else { DEBUG_WEBDAV("Unknown method!"); } @@ -1915,6 +1946,10 @@ int owncloud_set_property(const char *key, void *data) { dav_session.proxy_port = *(int*)(data); return 0; } + if (c_streq(key, "progress_callback")) { + _progresscb = *(csync_progress_callback*)(data); + return 0; + } return -1; } diff --git a/src/csync.c b/src/csync.c index 65c8b14ca6..bfa0429270 100644 --- a/src/csync.c +++ b/src/csync.c @@ -322,6 +322,9 @@ retry_vio_init: } } + if (ctx->callbacks.progresscb) + csync_set_module_property(ctx, "progress_callback", &ctx->callbacks.progresscb); + if (c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp) < 0) { ctx->error_code = CSYNC_ERR_TREE; rc = -1; @@ -1011,4 +1014,23 @@ int csync_set_module_property(CSYNC* ctx, const char* key, void* value) return csync_vio_set_property(ctx, key, value); } +int csync_set_progress_callback(CSYNC* ctx, csync_progress_callback cb) +{ + if (ctx == NULL || cb == NULL) { + ctx->error_code = CSYNC_ERR_PARAM; + return -1; + } + ctx->error_code = CSYNC_ERR_NONE; + ctx->callbacks.progresscb = cb; + + if (ctx->status & CSYNC_STATUS_INIT) { + fprintf(stderr, "This function must be called before initialization."); + ctx->error_code = CSYNC_ERR_UNSPEC; + return -1; + } + + return 0; + +} + /* vim: set ts=8 sw=2 et cindent: */ diff --git a/src/csync.h b/src/csync.h index 452660cd66..e2f858e92e 100644 --- a/src/csync.h +++ b/src/csync.h @@ -487,6 +487,23 @@ bool csync_file_known( char *statedb_file, const char* url ); */ int csync_set_module_property(CSYNC *ctx, const char *key, void *value); + +enum csync_notify_type_e { CSYNC_NOTIFY_START_DOWNLOAD, CSYNC_NOTIFY_START_UPLOAD, CSYNC_NOTIFY_PROGRESS, + CSYNC_NOTIFY_FINISHED, CSYNC_NOTFY_ERROR }; + +typedef void (*csync_progress_callback) (const char *remote_url, enum csync_notify_type_e kind, + long long o1, long long o2, void *userdata); +/** + * @brief Set a progress callback + * + * @param ctx The csync context. + * + * @param cb The callback + */ +int csync_set_progress_callback(CSYNC *ctx, csync_progress_callback cb); + + + #ifdef __cplusplus } #endif diff --git a/src/csync_private.h b/src/csync_private.h index 78986119b8..f0bb9d7ff4 100644 --- a/src/csync_private.h +++ b/src/csync_private.h @@ -82,6 +82,7 @@ struct csync_s { struct { csync_auth_callback auth_function; csync_log_callback log_function; + csync_progress_callback progresscb; void *userdata; } callbacks; c_strlist_t *excludes;