diff options
45 files changed, 30 insertions, 3941 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index f52aca6e1..853be4eb0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -133,13 +133,9 @@ endif() #endif() -set(USE_NEON TRUE) if(HAVE_QT5) - message(STATUS "Using Qt ${Qt5Core_VERSION_MAJOR}.${Qt5Core_VERSION_MINOR}.x") if (${Qt5Core_VERSION_MAJOR} EQUAL "5") if (${Qt5Core_VERSION_MINOR} EQUAL "4" OR ${Qt5Core_VERSION_MINOR} GREATER 4) - message(STATUS "We do not require Neon in this setup, compile without!") - set(USE_NEON FALSE) else() message(STATUS "If possible compile me with Qt 5.4 or higher.") endif() @@ -148,9 +144,6 @@ else() message(STATUS "If possible compile me with Qt 5.4 or higher.") endif() -if (USE_NEON) - find_package(Neon REQUIRED) -endif(USE_NEON) find_package(OpenSSL 1.0.0 REQUIRED) if(NOT TOKEN_AUTH_ONLY) diff --git a/admin/win/Toolchain-mingw32-openSUSE.cmake b/admin/win/Toolchain-mingw32-openSUSE.cmake index 54c4f5039..3877ca1d4 100644 --- a/admin/win/Toolchain-mingw32-openSUSE.cmake +++ b/admin/win/Toolchain-mingw32-openSUSE.cmake @@ -32,7 +32,3 @@ SET(QT_MOC_EXECUTABLE ${MINGW_PREFIX}-moc) SET(QT_RCC_EXECUTABLE ${MINGW_PREFIX}-rcc) SET(QT_UIC_EXECUTABLE ${MINGW_PREFIX}-uic) SET(QT_LRELEASE_EXECUTABLE ${MINGW_PREFIX}-lrelease) - -# neon config -SET(NEON_CONFIG_EXECUTABLE ${CMAKE_FIND_ROOT_PATH}/bin/neon-config) -# /usr/i686-w64-mingw32/sys-root/mingw/bin/neon-config diff --git a/cmake/modules/FindNeon.cmake b/cmake/modules/FindNeon.cmake deleted file mode 100644 index f8bd1ee14..000000000 --- a/cmake/modules/FindNeon.cmake +++ /dev/null @@ -1,73 +0,0 @@ -# - Try to find Neon -# Once done this will define -# -# NEON_FOUND - system has Neon -# NEON_INCLUDE_DIRS - the Neon include directory -# NEON_LIBRARIES - Link these to use Neon -# NEON_DEFINITIONS - Compiler switches required for using Neon -# -# Copyright (c) 2011-2013 Andreas Schneider <asn@cryptomilk.org> -# -# Redistribution and use is allowed according to the terms of the New -# BSD license. -# For details see the accompanying COPYING-CMAKE-SCRIPTS file. -# - - -find_package(PkgConfig) -if (PKG_CONFIG_FOUND) - pkg_check_modules(_NEON neon) -endif (PKG_CONFIG_FOUND) - -include(GNUInstallDirs) - -find_path(NEON_INCLUDE_DIRS -NAMES - neon/ne_basic.h -HINTS - ${_NEON_INCLUDEDIR} - ${CMAKE_INSTALL_INCLUDEDIR} -) - -find_library(NEON_LIBRARIES -NAMES - neon neon-27 -HINTS - ${_NEON_LIBDIR} - ${CMAKE_INSTALL_LIBDIR} - ${CMAKE_INSTALL_PREFIX}/lib - ${CMAKE_INSTALL_PREFIX}/lib64 -) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Neon DEFAULT_MSG NEON_LIBRARIES NEON_INCLUDE_DIRS) - -# show the NEON_INCLUDE_DIRS and NEON_LIBRARIES variables only in the advanced view -mark_as_advanced(NEON_INCLUDE_DIRS NEON_LIBRARIES) - -# Check if neon was compiled with LFS support, if so, the NE_LFS variable has to -# be defined in the owncloud module. -# If neon was not compiled with LFS its also ok since the underlying system -# than probably supports large files anyway. -IF( CMAKE_FIND_ROOT_PATH ) - FIND_PROGRAM( NEON_CONFIG_EXECUTABLE NAMES neon-config HINTS ${CMAKE_FIND_ROOT_PATH}/bin ) -ELSE( CMAKE_FIND_ROOT_PATH ) - FIND_PROGRAM( NEON_CONFIG_EXECUTABLE NAMES neon-config ) -ENDIF( CMAKE_FIND_ROOT_PATH ) - -IF ( NEON_CONFIG_EXECUTABLE ) - MESSAGE(STATUS "neon-config executable: ${NEON_CONFIG_EXECUTABLE}") - # neon-config --support lfs - EXECUTE_PROCESS( COMMAND ${NEON_CONFIG_EXECUTABLE} "--support" "lfs" - RESULT_VARIABLE LFS - OUTPUT_STRIP_TRAILING_WHITESPACE ) - - IF (LFS EQUAL 0) - MESSAGE(STATUS "libneon has been compiled with LFS support") - SET(NEON_WITH_LFS 1) - ELSE (LFS EQUAL 0) - MESSAGE(STATUS "libneon has not been compiled with LFS support, rely on OS") - ENDIF (LFS EQUAL 0) -ELSE ( NEON_CONFIG_EXECUTABLE ) - MESSAGE(STATUS, "neon-config could not be found.") -ENDIF ( NEON_CONFIG_EXECUTABLE ) diff --git a/cmake/modules/QtVersionAbstraction.cmake b/cmake/modules/QtVersionAbstraction.cmake index 760e9ed3a..d7cbde33a 100644 --- a/cmake/modules/QtVersionAbstraction.cmake +++ b/cmake/modules/QtVersionAbstraction.cmake @@ -31,7 +31,9 @@ if( Qt5Core_FOUND ) else( Qt5Core_FOUND ) if(WIN32 OR APPLE) + if (NOT BUILD_WITH_QT4) message(FATAL_ERROR "Qt 5 not found, but application depends on Qt5 on Windows and Mac OS X") + endif () endif(WIN32 OR APPLE) endif( Qt5Core_FOUND ) diff --git a/config.h.in b/config.h.in index 4633c16c4..06a0a62c0 100644 --- a/config.h.in +++ b/config.h.in @@ -23,8 +23,4 @@ #cmakedefine SYSCONFDIR "@SYSCONFDIR@" #cmakedefine SHAREDIR "@SHAREDIR@" -#ifndef NEON_WITH_LFS -#cmakedefine NEON_WITH_LFS "@NEON_WITH_LFS@" -#endif - #endif diff --git a/csync/config_csync.h.cmake b/csync/config_csync.h.cmake index a11f9ebe6..907fea661 100644 --- a/csync/config_csync.h.cmake +++ b/csync/config_csync.h.cmake @@ -24,10 +24,6 @@ #cmakedefine HAVE_ICONV 1 #cmakedefine HAVE_ICONV_CONST 1 -#ifndef NEON_WITH_LFS -#cmakedefine NEON_WITH_LFS 1 -#endif - #cmakedefine HAVE___MINGW_ASPRINTF 1 #cmakedefine HAVE_ASPRINTF 1 diff --git a/csync/src/CMakeLists.txt b/csync/src/CMakeLists.txt index 42db3d504..2e1d361b4 100644 --- a/csync/src/CMakeLists.txt +++ b/csync/src/CMakeLists.txt @@ -1,9 +1,6 @@ project(libcsync) add_subdirectory(std) -if(USE_NEON) - add_subdirectory(httpbf) -endif() # Statically include sqlite @@ -71,19 +68,6 @@ else() endif() -if(USE_NEON) - list(APPEND csync_SRCS - csync_owncloud.c - csync_owncloud_util.c - ) - list(APPEND CSYNC_LINK_LIBRARIES - ${NEON_LIBRARIES} - ) - include_directories(${NEON_INCLUDE_DIRS}) - add_definitions(-DUSE_NEON) -endif(USE_NEON) - - configure_file(csync_version.h.in ${CMAKE_CURRENT_BINARY_DIR}/csync_version.h) set(csync_HDRS diff --git a/csync/src/csync.c b/csync/src/csync.c index 908612d47..fe6704846 100644 --- a/csync/src/csync.c +++ b/csync/src/csync.c @@ -58,12 +58,6 @@ #include "csync_rename.h" #include "c_jhash.h" - -#ifdef USE_NEON -// Breaking the abstraction for fun and profit. -#include "csync_owncloud.h" -#endif - static int _key_cmp(const void *key, const void *data) { uint64_t a; csync_file_stat_t *b; @@ -154,9 +148,6 @@ int csync_init(CSYNC *ctx) { ctx->local.type = LOCAL_REPLICA; -#ifdef USE_NEON - owncloud_init(ctx); -#endif ctx->remote.type = REMOTE_REPLICA; if (c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp) < 0) { @@ -216,14 +207,6 @@ int csync_update(CSYNC *ctx) { CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "No exclude file loaded or defined!"); } -#ifdef USE_NEON - /* This is not actually connecting, just setting the info for neon. The legacy propagator can use it.. */ - if (dav_connect( ctx, ctx->remote.uri ) < 0) { - ctx->status_code = CSYNC_STATUS_CONNECT_ERROR; - return -1; - } -#endif - /* update detection for local replica */ csync_gettime(&start); ctx->current = LOCAL_REPLICA; @@ -646,10 +629,6 @@ int csync_destroy(CSYNC *ctx) { SAFE_FREE(ctx->remote.uri); SAFE_FREE(ctx->error_string); -#ifdef USE_NEON - owncloud_destroy(ctx); -#endif - #ifdef WITH_ICONV c_close_iconv(); #endif @@ -672,21 +651,6 @@ void csync_clear_exclude_list(CSYNC *ctx) csync_exclude_clear(ctx); } -int csync_set_auth_callback(CSYNC *ctx, csync_auth_callback cb) { - if (ctx == NULL || cb == NULL) { - return -1; - } - - if (ctx->status & CSYNC_STATUS_INIT) { - ctx->status_code = CSYNC_STATUS_CSYNC_STATUS_ERROR; - fprintf(stderr, "This function must be called before initialization."); - return -1; - } - ctx->callbacks.auth_function = cb; - - return 0; -} - void *csync_get_userdata(CSYNC *ctx) { if (ctx == NULL) { return NULL; @@ -781,14 +745,3 @@ void csync_file_stat_free(csync_file_stat_t *st) SAFE_FREE(st); } } - -int csync_set_module_property(CSYNC* ctx, const char* key, void* value) -{ -#ifdef USE_NEON - return owncloud_set_property(ctx, key, value); -#else - (void)ctx, (void)key, (void)value; - return 0; -#endif -} - diff --git a/csync/src/csync.h b/csync/src/csync.h index c2e1afa6b..947729ba9 100644 --- a/csync/src/csync.h +++ b/csync/src/csync.h @@ -520,19 +520,6 @@ int csync_set_iconv_codec(const char *from); #endif /** - * @brief Set a property to module - * - * @param ctx The csync context. - * - * @param key The property key - * - * @param value An opaque pointer to the data. - * - * @return 0 on success, less than 0 if an error occured. - */ -int csync_set_module_property(CSYNC *ctx, const char *key, void *value); - -/** * @brief Aborts the current sync run as soon as possible. Can be called from another thread. * * @param ctx The csync context. diff --git a/csync/src/csync_owncloud.c b/csync/src/csync_owncloud.c deleted file mode 100644 index 0a34024c3..000000000 --- a/csync/src/csync_owncloud.c +++ /dev/null @@ -1,617 +0,0 @@ -/* - * 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 - */ - -#include "csync_owncloud.h" -#include "csync_owncloud_private.h" - -#include <inttypes.h> - -#include "csync_private.h" - -#include "csync_version.h" - - -/* - * helper method to build up a user text for SSL problems, called from the - * verify_sslcert callback. - */ -static void addSSLWarning( char *ptr, const char *warn, int len ) -{ - char *concatHere = ptr; - int remainingLen = 0; - - if( ! (warn && ptr )) return; - remainingLen = len - strlen(ptr); - if( remainingLen <= 0 ) return; - concatHere = ptr + strlen(ptr); /* put the write pointer to the end. */ - strncpy( concatHere, warn, remainingLen ); -} - -/* - * Callback to verify the SSL certificate, called from libneon. - * It analyzes the SSL problem, creates a user information text and passes - * it to the csync callback to ask the user. - */ -#define LEN 4096 -static int ssl_callback_by_neon(void *userdata, int failures, - const ne_ssl_certificate *certificate) -{ - char problem[LEN]; - char buf[MAX(NE_SSL_DIGESTLEN, NE_ABUFSIZ)]; - int ret = -1; - const ne_ssl_certificate *cert = certificate; - csync_auth_callback authcb = NULL; - csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata; - - memset( problem, 0, LEN ); - - while( cert ) { - - addSSLWarning( problem, "There are problems with the SSL certificate:\n", LEN ); - if( failures & NE_SSL_NOTYETVALID ) { - addSSLWarning( problem, " * The certificate is not yet valid.\n", LEN ); - } - if( failures & NE_SSL_EXPIRED ) { - addSSLWarning( problem, " * The certificate has expired.\n", LEN ); - } - - if( failures & NE_SSL_UNTRUSTED ) { - addSSLWarning( problem, " * The certificate is not trusted!\n", LEN ); - } - if( failures & NE_SSL_IDMISMATCH ) { - addSSLWarning( problem, " * The hostname for which the certificate was " - "issued does not match the hostname of the server\n", LEN ); - } - if( failures & NE_SSL_BADCHAIN ) { - addSSLWarning( problem, " * The certificate chain contained a certificate other than the server cert\n", LEN ); - } - if( failures & NE_SSL_REVOKED ) { - addSSLWarning( problem, " * The server certificate has been revoked by the issuing authority.\n", LEN ); - } - - if (ne_ssl_cert_digest(cert, buf) == 0) { - addSSLWarning( problem, "Certificate fingerprint: ", LEN ); - addSSLWarning( problem, buf, LEN ); - addSSLWarning( problem, "\n", LEN ); - } - cert = ne_ssl_cert_signedby( cert ); - } - addSSLWarning( problem, "Do you want to accept the certificate chain anyway?\nAnswer yes to do so and take the risk: ", LEN ); - - 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, csync_get_userdata(ctx->csync_ctx) ); - if( buf[0] == 'y' || buf[0] == 'Y') { - ret = 0; - } else { - DEBUG_WEBDAV("Authentication callback replied %s", buf ); - - } - } - DEBUG_WEBDAV("## VERIFY_SSL CERT: %d", ret ); - return ret; -} - -/* - * Authentication callback. Is set by ne_set_server_auth to be called - * from the neon lib to authenticate a request. - */ -static int authentication_callback_by_neon( void *userdata, const char *realm, int attempt, - char *username, char *password) -{ - char buf[NE_ABUFSIZ]; - csync_auth_callback authcb = NULL; - int re = attempt; - csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata; - - (void) realm; - - /* DEBUG_WEBDAV( "Authentication required %s", realm ); */ - if( username && password ) { - DEBUG_WEBDAV( "Authentication required %s", username ); - if( ctx->dav_session.user ) { - /* allow user without password */ - if( strlen( ctx->dav_session.user ) < NE_ABUFSIZ ) { - strcpy( username, ctx->dav_session.user ); - } - if( ctx->dav_session.pwd && strlen( ctx->dav_session.pwd ) < NE_ABUFSIZ ) { - strcpy( password, ctx->dav_session.pwd ); - } - } else { - authcb = csync_get_auth_callback( ctx->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, 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, csync_get_userdata(ctx->csync_ctx) ); - if( strlen(buf) < NE_ABUFSIZ) { - strcpy( password, buf ); - } - } else { - re = 1; - } - } - } - return re; -} - -/* - * Authentication callback. Is set by ne_set_proxy_auth to be called - * from the neon lib to authenticate against a proxy. The data to authenticate - * against comes from mirall throught vio_module_init function. - */ -static int proxy_authentication_callback_by_neon( void *userdata, const char *realm, int attempt, - char *username, char *password) -{ - csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata; - (void) realm; - 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 */ - return (attempt < 3) ? 0 : -1; -} - -/* Configure the proxy depending on the variables */ -static int configureProxy( csync_owncloud_ctx_t *ctx, ne_session *session ) -{ - int port = 8080; - int re = -1; - - if( ! session ) return -1; - if( ! ctx->dav_session.proxy_type ) return 0; /* Go by NoProxy per default */ - - if( ctx->dav_session.proxy_port > 0 ) { - port = ctx->dav_session.proxy_port; - } - - if( c_streq(ctx->dav_session.proxy_type, "NoProxy" )) { - DEBUG_WEBDAV("No proxy configured."); - re = 0; - } 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( 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, ctx->dav_session.proxy_host, port ); - } - re = 2; - } else { - 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", ctx->dav_session.proxy_type ); - } - - return re; -} - -/* - * This hook is called for with the response of a request. Here its checked - * if a Set-Cookie header is there for the PHPSESSID. The key is stored into - * the webdav session to be added to subsequent requests. - */ -static void post_request_hook(ne_request *req, void *userdata, const ne_status *status) -{ - const char *set_cookie_header = NULL; - const char *sc = NULL; - char *key = NULL; - - csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata; - - if (ctx->dav_session.session_key) - return; /* We already have a session cookie, and we should ignore other ones */ - - if(!(status && req)) return; - if( status->klass == 2 || status->code == 401 ) { - /* successful request */ - set_cookie_header = ne_get_response_header( req, "Set-Cookie" ); - if( set_cookie_header ) { - DEBUG_WEBDAV(" Set-Cookie found: %s", set_cookie_header); - /* try to find a ', ' sequence which is the separator of neon if multiple Set-Cookie - * headers are there. - * The following code parses a string like this: - * Set-Cookie: 50ace6bd8a669=p537brtt048jh8srlp2tuep7em95nh9u98mj992fbqc47d1aecp1; - */ - sc = set_cookie_header; - while(sc) { - const char *sc_val = sc; - const char *sc_end = sc_val; - int cnt = 0; - int len = strlen(sc_val); /* The length of the rest of the header string. */ - - while( cnt < len && *sc_end != ';' && *sc_end != ',') { - cnt++; - sc_end++; - } - if( cnt == len ) { - /* exit: We are at the end. */ - sc = NULL; - } else if( *sc_end == ';' ) { - /* We are at the end of the session key. */ - int keylen = sc_end-sc_val; - if( key ) { - int oldlen = strlen(key); - key = c_realloc(key, oldlen + 2 + keylen+1); - strcpy(key + oldlen, "; "); - strncpy(key + oldlen + 2, sc_val, keylen); - key[oldlen + 2 + keylen] = '\0'; - } else { - key = c_malloc(keylen+1); - strncpy( key, sc_val, keylen ); - key[keylen] = '\0'; - } - - /* now search for a ',' to find a potential other header entry */ - while(cnt < len && *sc_end != ',') { - cnt++; - sc_end++; - } - if( cnt < len ) - sc = sc_end+2; /* mind the space after the comma */ - else - sc = NULL; - } else if( *sc_end == ',' ) { - /* A new entry is to check. */ - if( *(sc_end + 1) == ' ') { - sc = sc_end+2; - } else { - /* error condition */ - sc = NULL; - } - } - } - } - } else { - DEBUG_WEBDAV("Request failed, don't take session header."); - } - if( key ) { - DEBUG_WEBDAV("----> Session-key: %s", key); - SAFE_FREE(ctx->dav_session.session_key); - ctx->dav_session.session_key = key; - } -} - -/* - * this hook is called just after a request has been created, before its sent. - * Here it is used to set the proxy connection header if available. - */ -static void request_created_hook(ne_request *req, void *userdata, - const char *method, const char *requri) -{ - // 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(ctx->dav_session.proxy_type) { - /* required for NTLM */ - ne_add_request_header(req, "Proxy-Connection", "Keep-Alive"); - } -} - -/* - * this hook is called just before a request has been sent. - * Here it is used to set the session cookie if available. - */ -static void pre_send_hook(ne_request *req, void *userdata, - ne_buffer *header) -{ - csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t *) userdata; - - if( !req ) return; - - 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!"); - } -} - -static int post_send_hook(ne_request *req, void *userdata, - const ne_status *status) -{ - const char *location; - 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( ctx->dav_session.redir_callback ) { - if( ctx->dav_session.redir_callback( ctx->csync_ctx, location ) ) { - return NE_REDIRECT; - } else { - return NE_RETRY; - } - } - - return NE_REDIRECT; -} - -/* - * Connect to a DAV server - * This function sets the flag _connected if the connection is established - * and returns if the flag is set, so calling it frequently is save. - */ -int dav_connect(CSYNC *csyncCtx, const char *base_url) { - int useSSL = 0; - int rc; - char protocol[6] = {'\0'}; - char uaBuf[256]; - char *path = NULL; - char *scheme = NULL; - char *host = NULL; - unsigned int port = 0; - int proxystate = -1; - csync_owncloud_ctx_t *ctx = csyncCtx->owncloud_context; - struct csync_client_certs_s* clientCerts = csyncCtx->clientCerts; - - if (ctx->_connected) { - return 0; - } - - 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; - } - - DEBUG_WEBDAV("* scheme %s", scheme ); - DEBUG_WEBDAV("* host %s", host ); - DEBUG_WEBDAV("* port %u", port ); - DEBUG_WEBDAV("* path %s", path ); - - if( strcmp( scheme, "owncloud" ) == 0 || strcmp( scheme, "http" ) == 0 ) { - strcpy( protocol, "http"); - } else if( strcmp( scheme, "ownclouds" ) == 0 || strcmp( scheme, "https") == 0 ) { - strcpy( protocol, "https"); - useSSL = 1; - } else { - DEBUG_WEBDAV("Invalid scheme %s, go out here!", scheme ); - rc = -1; - goto out; - } - - DEBUG_WEBDAV("* user %s", ctx->dav_session.user ? ctx->dav_session.user : ""); - - if (port == 0) { - port = ne_uri_defaultport(protocol); - } - - ctx->dav_session.ctx = ne_session_create( protocol, host, port); - - if (ctx->dav_session.ctx == NULL) { - DEBUG_WEBDAV("Session create with protocol %s failed", protocol ); - rc = -1; - goto out; - } - - 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 ); - } - // Should never take more than some seconds, 30 is really a max. - ne_set_connect_timeout(ctx->dav_session.ctx, 30); - - snprintf( uaBuf, sizeof(uaBuf), "Mozilla/5.0 (%s) mirall/%s (csyncoC)", - CSYNC_STRINGIFY( MIRALL_VERSION ), csync_owncloud_get_platform() ); - ne_set_useragent( ctx->dav_session.ctx, uaBuf); - ne_set_server_auth(ctx->dav_session.ctx, authentication_callback_by_neon, ctx); - - if( useSSL ) { - if (!ne_has_support(NE_FEATURE_SSL)) { - DEBUG_WEBDAV("Error: SSL is not enabled."); - rc = -1; - goto out; - } - - if(clientCerts != NULL) { - ne_ssl_client_cert *clicert; - - DEBUG_WEBDAV("dav_connect: certificatePath and certificatePasswd are set, so we use it" ); - DEBUG_WEBDAV(" with certificatePath: %s", clientCerts->certificatePath ); - DEBUG_WEBDAV(" with certificatePasswd: %s", clientCerts->certificatePasswd ); - clicert = ne_ssl_clicert_read ( clientCerts->certificatePath ); - if ( clicert == NULL ) { - DEBUG_WEBDAV ( "Error read certificate : %s", ne_get_error ( ctx->dav_session.ctx ) ); - } else { - if ( ne_ssl_clicert_encrypted ( clicert ) ) { - int rtn = ne_ssl_clicert_decrypt ( clicert, clientCerts->certificatePasswd ); - if ( !rtn ) { - DEBUG_WEBDAV ( "Certificate was deciphered successfully." ); - ne_ssl_set_clicert ( ctx->dav_session.ctx, clicert ); - } else { - DEBUG_WEBDAV ( "Errors while deciphering certificate: %s", ne_get_error ( ctx->dav_session.ctx ) ); - } - } - } - } else { - DEBUG_WEBDAV("dav_connect: error with csync_client_certs_s* clientCerts"); - } - ne_ssl_trust_default_ca( ctx->dav_session.ctx ); - ne_ssl_set_verify( ctx->dav_session.ctx, ssl_callback_by_neon, ctx); - } - - /* Hook called when a request is created. It sets the proxy connection header. */ - 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( ctx->dav_session.ctx, post_request_hook, ctx ); - /* Hook called before a request is sent. It sets the cookies. */ - 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( ctx->dav_session.ctx, post_send_hook, ctx ); - - /* Proxy support */ - proxystate = configureProxy( ctx, ctx->dav_session.ctx ); - if( proxystate < 0 ) { - DEBUG_WEBDAV("Error: Proxy-Configuration failed."); - } else if( proxystate > 0 ) { - ne_set_proxy_auth( ctx->dav_session.ctx, proxy_authentication_callback_by_neon, ctx ); - } - - ctx->_connected = 1; - rc = 0; -out: - SAFE_FREE(path); - SAFE_FREE(host); - SAFE_FREE(scheme); - return rc; -} - - -char *owncloud_error_string(CSYNC* ctx) -{ - return ctx->owncloud_context->dav_session.error_string; -} - -int owncloud_commit(CSYNC* ctx) { - if (!ctx->owncloud_context) { - return 0; - } - - 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; - } - - /* DEBUG_WEBDAV( "********** vio_module_shutdown" ); */ - - ctx->owncloud_context->dav_session.ctx = 0; - - // ne_sock_exit(); - ctx->owncloud_context->_connected = 0; /* triggers dav_connect to go through the whole neon setup */ - - 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; -} - -void owncloud_destroy(CSYNC* ctx) -{ - owncloud_commit(ctx); - SAFE_FREE(ctx->owncloud_context); - - if (ctx->clientCerts) { - SAFE_FREE(ctx->clientCerts->certificatePasswd); - SAFE_FREE(ctx->clientCerts->certificatePath); - SAFE_FREE(ctx->clientCerts); - } - ne_sock_exit(); -} - -int owncloud_set_property(CSYNC* ctx, const char *key, void *data) { -#define READ_STRING_PROPERTY(P) \ - if (c_streq(key, #P)) { \ - 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) - READ_STRING_PROPERTY(proxy_type) - READ_STRING_PROPERTY(proxy_host) - READ_STRING_PROPERTY(proxy_user) - READ_STRING_PROPERTY(proxy_pwd) -#undef READ_STRING_PROPERTY - - if (c_streq(key, "proxy_port")) { - ctx->owncloud_context->dav_session.proxy_port = *(int*)(data); - return 0; - } - if (c_streq(key, "read_timeout") || c_streq(key, "timeout")) { - ctx->owncloud_context->dav_session.read_timeout = *(int*)(data); - return 0; - } - if( c_streq(key, "get_dav_session")) { - /* Give the ne_session to the caller */ - *(ne_session**)data = ctx->owncloud_context->dav_session.ctx; - return 0; - } - if( c_streq(key, "redirect_callback")) { - if (data) { - csync_owncloud_redirect_callback_t* cb_wrapper = data; - ctx->owncloud_context->dav_session.redir_callback = *cb_wrapper; - } else { - ctx->owncloud_context->dav_session.redir_callback = NULL; - } - } - if( c_streq(key, "SSLClientCerts")) { - if(ctx->clientCerts != NULL) { - SAFE_FREE(ctx->clientCerts->certificatePasswd); - SAFE_FREE(ctx->clientCerts->certificatePath); - SAFE_FREE(ctx->clientCerts); - ctx->clientCerts = NULL; - } - if (data) { - struct csync_client_certs_s* clientCerts = (struct csync_client_certs_s*) data; - struct csync_client_certs_s* newCerts = c_malloc(sizeof(struct csync_client_certs_s)); - newCerts->certificatePath = c_strdup(clientCerts->certificatePath); - newCerts->certificatePasswd = c_strdup(clientCerts->certificatePasswd); - ctx->clientCerts = newCerts; - } else { - DEBUG_WEBDAV("error: in owncloud_set_property for 'SSLClientCerts'" ); - } - } - - return -1; -} - -void owncloud_init(CSYNC* ctx) { - - ne_sock_init(); - - ctx->owncloud_context = c_malloc( sizeof( struct csync_owncloud_ctx_s )); - ctx->owncloud_context->csync_ctx = ctx; // back reference - -} - -/* vim: set ts=4 sw=4 et cindent: */ - diff --git a/csync/src/csync_owncloud.h b/csync/src/csync_owncloud.h deleted file mode 100644 index e198242e7..000000000 --- a/csync/src/csync_owncloud.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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_H -#define CSYNC_OWNCLOUD_H - -#include "csync.h" -#include "vio/csync_vio.h" - -// Public API used by csync -int owncloud_commit(CSYNC* ctx); -void owncloud_destroy(CSYNC* ctx); -char *owncloud_error_string(CSYNC* ctx); -int owncloud_set_property(CSYNC* ctx, const char *key, void *data); -void owncloud_init(CSYNC* ctx); - -int dav_connect(CSYNC* ctx, const char *base_url); - -#endif /* CSYNC_OWNCLOUD_H */ diff --git a/csync/src/csync_owncloud_private.h b/csync/src/csync_owncloud_private.h deleted file mode 100644 index 03cd73a8e..000000000 --- a/csync/src/csync_owncloud_private.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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 "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_owncloud_redirect_callback_t redir_callback; -}; - -struct csync_owncloud_ctx_s { - CSYNC *csync_ctx; - - // 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; - -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 ); - -const char* csync_owncloud_get_platform(void); - -char *_cleanPath( const char* uri ); - -#endif // CSYNC_OWNCLOUD_PRIVATE_H diff --git a/csync/src/csync_owncloud_util.c b/csync/src/csync_owncloud_util.c deleted file mode 100644 index ca71b60a8..000000000 --- a/csync/src/csync_owncloud_util.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * 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 - */ - -#include "csync_owncloud.h" -#include "csync_owncloud_private.h" - -#include "csync_misc.h" - -void set_errno_from_http_errcode( int err ) { - int new_errno = 0; - - switch(err) { - case 200: /* OK */ - case 201: /* Created */ - case 202: /* Accepted */ - case 203: /* Non-Authoritative Information */ - case 204: /* No Content */ - case 205: /* Reset Content */ - case 207: /* Multi-Status */ - case 304: /* Not Modified */ - new_errno = 0; - break; - case 401: /* Unauthorized */ - case 402: /* Payment Required */ - case 407: /* Proxy Authentication Required */ - case 405: - new_errno = EPERM; - break; - case 301: /* Moved Permanently */ - case 303: /* See Other */ - case 404: /* Not Found */ - case 410: /* Gone */ - new_errno = ENOENT; - break; - case 408: /* Request Timeout */ - case 504: /* Gateway Timeout */ - new_errno = EAGAIN; - break; - case 423: /* Locked */ - new_errno = EACCES; - break; - case 400: /* Bad Request */ - case 403: /* Forbidden */ - case 409: /* Conflict */ - case 411: /* Length Required */ - case 412: /* Precondition Failed */ - case 414: /* Request-URI Too Long */ - case 415: /* Unsupported Media Type */ - case 424: /* Failed Dependency */ - case 501: /* Not Implemented */ - new_errno = EINVAL; - break; - case 507: /* Insufficient Storage */ - new_errno = ENOSPC; - break; - case 206: /* Partial Content */ - case 300: /* Multiple Choices */ - case 302: /* Found */ - case 305: /* Use Proxy */ - case 306: /* (Unused) */ - case 307: /* Temporary Redirect */ - case 406: /* Not Acceptable */ - case 416: /* Requested Range Not Satisfiable */ - case 417: /* Expectation Failed */ - case 422: /* Unprocessable Entity */ - case 500: /* Internal Server Error */ - case 502: /* Bad Gateway */ - case 505: /* HTTP Version Not Supported */ - new_errno = EIO; - break; - case 503: /* Service Unavailable */ - new_errno = ERRNO_SERVICE_UNAVAILABLE; - break; - case 413: /* Request Entity too Large */ - new_errno = EFBIG; - break; - default: - new_errno = EIO; - } - - errno = new_errno; -} - -// as per http://sourceforge.net/p/predef/wiki/OperatingSystems/ -// extend as required -const char* csync_owncloud_get_platform() { -#if defined (_WIN32) - return "Windows"; -#elif defined(__APPLE__) - return "Macintosh"; -#elif defined(__gnu_linux__) - return "Linux"; -#elif defined(__DragonFly__) - /* might also define __FreeBSD__ */ - return "DragonFlyBSD"; -#elif defined(__FreeBSD__) - return "FreeBSD"; -#elif defined(__NetBSD__) - return "NetBSD"; -#elif defined(__OpenBSD__) - return "OpenBSD"; -#elif defined(sun) || defined(__sun) - return "Solaris"; -#else - return "Unknown OS"; -#endif -} diff --git a/csync/src/csync_private.h b/csync/src/csync_private.h index f201a7017..e8f7c4b93 100644 --- a/csync/src/csync_private.h +++ b/csync/src/csync_private.h @@ -77,9 +77,6 @@ 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 */ @@ -169,9 +166,6 @@ struct csync_s { bool db_is_empty; bool ignore_hidden_files; - - struct csync_owncloud_ctx_s *owncloud_context; - }; diff --git a/csync/src/httpbf/CMakeLists.txt b/csync/src/httpbf/CMakeLists.txt deleted file mode 100644 index 4d084c9dd..000000000 --- a/csync/src/httpbf/CMakeLists.txt +++ /dev/null @@ -1,57 +0,0 @@ -project(httpbflib C) - -find_package(Neon) - - -set(HTTPBF_PUBLIC_INCLUDE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR}/src - ${NEON_INCLUDE_DIRS} - CACHE INTERNAL "httpbflib public include directories" -) - -set(HTTPBF_LIBRARY - httpbf - CACHE INTERNAL "httpbf library" -) - -set(HTTPBF_LINK_LIBRARIES - ${HTTPBF_LIBRARY} -) - -set(httpbf_SRCS - src/httpbf.c -) -set(httpbf_HEADERS - src/httpbf.h -) - -include_directories( - ${HTTPBF_PUBLIC_INCLUDE_DIRS} -) - -add_library(${HTTPBF_LIBRARY} STATIC ${httpbf_SRCS}) -target_link_libraries(${HTTPBF_LIBRARY} ${NEON_LIBRARIES}) - -if(NOT WIN32) - add_definitions( -fPIC ) -endif() - -INSTALL( - TARGETS - ${HTTPBF_LIBRARY} - LIBRARY DESTINATION - ${LIB_INSTALL_DIR} - ARCHIVE DESTINATION - ${LIB_INSTALL_DIR} - RUNTIME DESTINATION - ${BIN_INSTALL_DIR} -) - -if (NOT APPLE) - INSTALL( - FILES - ${httpbf_HEADERS} - DESTINATION - ${CMAKE_INSTALL_INCLUDEDIR} - ) -endif (NOT APPLE) diff --git a/csync/src/httpbf/README b/csync/src/httpbf/README deleted file mode 100644 index 31201ae6d..000000000 --- a/csync/src/httpbf/README +++ /dev/null @@ -1,29 +0,0 @@ -This is a little code that does ownCloud file chunking. - -Basically to put a local file to an url: -(Also see the client example code in client dir.) - -/* Initialize the transfer, get a transfer struct. */ -hbf_transfer_t *trans = hbf_init_transfer( url ); - -Hbf_State state; -if( trans ) { - int fd = open_local_file( file ); - - /* create a neon session to use for the transfer */ - ne_session *session = create_neon_session(uri); - - if( session && fd > -1 ) { - /* Prepare the list of chunks, ie. calculate chunks and write back to trans. */ - state = hbf_splitlist(trans, fd); - - if( state == HBF_SUCCESS ) { - /* Transfer all the chunks through the HTTP session using PUT. */ - state = hbf_transfer( session, trans, "PUT" ); - } - } -} - -GET a large file: -Do GET Range requests. - diff --git a/csync/src/httpbf/client/CMakeLists.txt b/csync/src/httpbf/client/CMakeLists.txt deleted file mode 100644 index ea371acb9..000000000 --- a/csync/src/httpbf/client/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -project(client C) - -set(CLIENT_EXECUTABLE httpbfclient CACHE INTERNAL "httpbf client") - -set(CLIENT_LINK_LIBRARIES ${NEON_LIBRARIES} ${HBF_LIBRARY}) - -set(HTTPBF_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/src}) - -if(NOT LINUX) - list(APPEND CLIENT_LINK_LIBRARIES ${ARGP_LIBRARIES}) -endif() - -set(client_SRCS - httpbf_client.c -) - -include_directories( - ${HTTPBF_INCLUDE_DIR} - ${HTTPBF_PUBLIC_INCLUDE_DIRS} -) - -add_executable(${CLIENT_EXECUTABLE} ${client_SRCS}) - -target_link_libraries(${CLIENT_EXECUTABLE} ${CLIENT_LINK_LIBRARIES}) - -set_target_properties( - ${CLIENT_EXECUTABLE} - PROPERTIES - OUTPUT_NAME - httpbf -) - -# install( TARGETS ${CLIENT_EXECUTABLE} DESTINATION ${BIN_INSTALL_DIR} ) -install(TARGETS ${CLIENT_EXECUTABLE} DESTINATION bin) - - diff --git a/csync/src/httpbf/client/httpbf_client.c b/csync/src/httpbf/client/httpbf_client.c deleted file mode 100644 index 36c7bebee..000000000 --- a/csync/src/httpbf/client/httpbf_client.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * httpbf - send big files via http - * - * Copyright (c) 2012 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 _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <stdbool.h> -#include <unistd.h> -#include <getopt.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#include <neon/ne_auth.h> - -#include "httpbf.h" - -/* Program documentation. */ -static char doc[] = "Usage: httpbf [OPTION...] LOCAL REMOTEDIR\n\ -httpbf - command line client to upload big files via http.\n\ -\n\ -Transfer a big file to a remote directory on ownCloud.\n\ -\n\ --?, --help Give this help list\n\ - --usage Give a short usage message\n\ --V, --version Print program version\n\ -"; - -static char _user[NE_ABUFSIZ]; -static char _pwd[NE_ABUFSIZ]; - -/* The options we understand. */ -static const struct option long_options[] = -{ - {"version", no_argument, 0, 'V' }, - {"usage", no_argument, 0, 'h' }, - {0, 0, 0, 0} -}; - -static const char* httpbf_version = "0.1"; - -static void print_version() -{ - printf( "%s\n", httpbf_version ); - exit(0); -} - -static void print_help() -{ - printf( "%s\n", doc ); - exit(0); -} - -static int ne_auth( void *userdata, const char *realm, int attempt, - char *username, char *password) -{ - (void) userdata; - (void) realm; - - if( username && password ) { - if( _user ) { - /* allow user without password */ - if( strlen( _user ) < NE_ABUFSIZ ) { - strcpy( username, _user ); - } - if( _pwd && strlen( _pwd ) < NE_ABUFSIZ ) { - strcpy( password, _pwd ); - } - } - } - return attempt; -} - - -static int parse_args(int argc, char **argv) -{ - while(optind < argc) { - int c = -1; - struct option *opt = NULL; - int result = getopt_long( argc, argv, "Vh", long_options, &c ); - - if( result == -1 ) { - break; - } - - switch(result) { - case 'V': - print_version(); - break; - case 'h': - print_help(); - break; - case 0: - opt = (struct option*)&(long_options[c]); - if(strcmp(opt->name, "no-name-yet")) { - - } else { - fprintf(stderr, "Argument: No idea what!\n"); - } - break; - default: - break; - } - } - return optind; -} - -static ne_session* create_neon_session( const char *url ) -{ - ne_uri uri; - ne_session *sess = NULL; - - memset( _user, 0, NE_ABUFSIZ ); - memset( _pwd, 0, NE_ABUFSIZ ); - - if( ne_uri_parse( url, &uri ) == 0 ) { - unsigned int port = ne_uri_defaultport(uri.scheme); - if( uri.userinfo ) { - char *slash = NULL; - strcpy( _user, uri.userinfo ); - slash = strchr( _user, ':'); - if( slash ) { - strcpy( _pwd, slash+1); - *slash = 0; - } - } - sess = ne_session_create(uri.scheme, uri.host, port); - ne_set_server_auth(sess, ne_auth, 0 ); - - ne_uri_free(&uri); - } - return sess; -} - -static int open_local_file( const char *file ) -{ - int fd = -1; - - if( !file ) return -1; - - fd = open(file, O_RDONLY); - return fd; -} - -static void transfer( const char* local, const char* uri ) -{ - if( !(local && uri )) return; - char *whole_url; - int len; - char *filename = basename(local); - if( ! filename ) { - return; - } - - len = strlen(filename)+strlen(uri)+2; - whole_url = malloc( len ); - strcpy(whole_url, uri); - strcat(whole_url, "/"); - strcat(whole_url, filename); - - hbf_transfer_t *trans = hbf_init_transfer( whole_url ); - Hbf_State state; - - if( trans ) { - ne_session *session = create_neon_session(uri); - if( session ) { - int fd = open_local_file( local ); - if( fd > -1 ) { - state = hbf_splitlist(trans, fd ); - if( state == HBF_SUCCESS ) { - state = hbf_transfer( session, trans, "PUT" ); - } - } - ne_session_destroy(session); - } - } - - if( state != HBF_SUCCESS ) { - printf("Upload failed: %s\n", hbf_error_string(state)); - printf(" HTTP result %d, Server Error: %s\n", - trans->status_code, trans->error_string ? trans->error_string : "<empty>" ); - } - /* Print the result of the recent transfer */ - hbf_free_transfer( trans ); - free(whole_url); -} - -int main(int argc, char **argv) { - int rc = 0; - char errbuf[256] = {0}; - - parse_args(argc, argv); - /* two options must remain as source and target */ - /* printf("ARGC: %d -> optind: %d\n", argc, optind ); */ - if( argc - optind < 2 ) { - print_help(); - } - - transfer( argv[optind], argv[optind+1]); - -} - -/* vim: set ts=8 sw=2 et cindent: */ diff --git a/csync/src/httpbf/src/CMakeLists.txt b/csync/src/httpbf/src/CMakeLists.txt deleted file mode 100644 index dc57ab14c..000000000 --- a/csync/src/httpbf/src/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -project(httpbf C) - -# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked - -set(HTTPBF_PUBLIC_INCLUDE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR} - CACHE INTERNAL "httpbf public include directories" -) - -set(HTTPBFLIB_PRIVATE_INCLUDE_DIRS -) - -set(HBF_LIBRARY - httpbf - CACHE INTERNAL "httpbflib library" -) - -set(HTTPBFLIB_LINK_LIBRARIES - ${HBF_LIBRARY} -) - -set(httpbflib_SRCS - httpbf.c -) - -include_directories( - ${NEON_INCLUDE_DIRS} - ${GLIB2_INCLUDE_DIRS} -) - -if(NOT WIN32) - add_definitions( -fPIC ) -endif() - -add_library(${HBF_LIBRARY} SHARED ${httpbflib_SRCS} ) - -target_link_libraries(${HBF_LIBRARY} ${NEON_LIBRARIES}) - diff --git a/csync/src/httpbf/src/httpbf.c b/csync/src/httpbf/src/httpbf.c deleted file mode 100644 index 2489e8d48..000000000 --- a/csync/src/httpbf/src/httpbf.c +++ /dev/null @@ -1,688 +0,0 @@ -/* - * httpbf - send big files via http - * - * Copyright (c) 2012 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 - */ - -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <sys/timeb.h> -#include <sys/time.h> -#include <inttypes.h> - -#include "httpbf.h" - -#include <neon/ne_session.h> -#include <neon/ne_request.h> -#include <neon/ne_basic.h> - -// #ifdef NDEBUG -// #define DEBUG_HBF(...) -// #else -#define DEBUG_HBF(...) { if(transfer->log_cb) { \ - char buf[1024]; \ - snprintf(buf, 1024, __VA_ARGS__); \ - transfer->log_cb(__func__, buf, transfer->user_data); \ - } } - -// #endif - -#define DEFAULT_BLOCK_SIZE (10*1024*1024) - -/* Platform specific defines go here. */ -#ifdef _WIN32 -#define _hbf_fstat _fstat64 -typedef struct stat64 hbf_stat_t; -#else -#define _hbf_fstat fstat -typedef struct stat hbf_stat_t; -#endif - -static int transfer_id( hbf_stat_t *sb ) { - struct timeval tp; - int res; - int r; - - if( gettimeofday(&tp, 0) < 0 ) { - return 0; - } - - /* build a Unique ID: - * take the current epoch and shift 8 bits up to keep the least bits. - * than add the milliseconds, again shift by 8 - * and finally add the least 8 bit of the inode of the file. - */ - res = tp.tv_sec; /* epoche value in seconds */ - res = res << 8; - r = (sb->st_ino & 0xFF); - res += r; /* least six bit of inode */ - res = res << sizeof(tp.tv_usec); - res += tp.tv_usec; /* milliseconds */ - - return res; -} - -hbf_transfer_t *hbf_init_transfer( const char *dest_uri ) { - hbf_transfer_t * transfer = NULL; - - transfer = malloc( sizeof(hbf_transfer_t) ); - memset(transfer, 0, sizeof(hbf_transfer_t)); - - /* store the target uri */ - transfer->url = strdup(dest_uri); - transfer->status_code = 200; - transfer->error_string = NULL; - transfer->start_id = 0; - transfer->block_size = DEFAULT_BLOCK_SIZE; - transfer->threshold = transfer->block_size; - transfer->modtime_accepted = 0; - transfer->oc_header_modtime = 0; - - return transfer; -} - -/* Create the splitlist of a given file descriptor */ -Hbf_State hbf_splitlist(hbf_transfer_t *transfer, int fd ) { - hbf_stat_t sb; - int64_t num_blocks; - int64_t blk_size; - int64_t remainder = 0; - - if( ! transfer ) { - return HBF_PARAM_FAIL; - } - - if( fd <= 0 ) { - DEBUG_HBF("File descriptor is invalid."); - return HBF_PARAM_FAIL; - } - - if( _hbf_fstat(fd, &sb) < 0 ) { - DEBUG_HBF("Failed to stat the file descriptor: errno = %d", errno); - return HBF_FILESTAT_FAIL; - } - - /* Store the file characteristics. */ - transfer->fd = fd; - transfer->stat_size = sb.st_size; - transfer->modtime = sb.st_mtime; - transfer->previous_etag = NULL; -#ifndef NDEBUG - transfer->calc_size = 0; -#endif - - DEBUG_HBF("block_size: %" PRId64 " threshold: %" PRId64 " st_size: %" PRId64, transfer->block_size, transfer->threshold, sb.st_size ); - - - /* calc the number of blocks to split in */ - blk_size = transfer->block_size; - if (sb.st_size < transfer->threshold) { - blk_size = transfer->threshold; - } - - num_blocks = sb.st_size / blk_size; - - /* there migth be a remainder. */ - remainder = sb.st_size - num_blocks * blk_size; - - /* if there is a remainder, add one block */ - if( remainder > 0 ) { - num_blocks++; - } - - /* The file has size 0. There still needs to be at least one block. */ - if( sb.st_size == 0 ) { - num_blocks = 1; - blk_size = 0; - } - - DEBUG_HBF("num_blocks: %" PRId64 " rmainder: %" PRId64 " blk_size: %" PRId64, num_blocks, remainder, blk_size ); - - - if( num_blocks ) { - int cnt; - int64_t overall = 0; - /* create a datastructure for the transfer data */ - transfer->block_arr = calloc(num_blocks, sizeof(hbf_block_t*)); - transfer->block_cnt = num_blocks; - transfer->transfer_id = transfer_id(&sb); - transfer->start_id = 0; - - for( cnt=0; cnt < num_blocks; cnt++ ) { - /* allocate a block struct and fill */ - hbf_block_t *block = malloc( sizeof(hbf_block_t) ); - memset(block, 0, sizeof(hbf_block_t)); - - block->seq_number = cnt; - if( cnt > 0 ) { - block->start = cnt * blk_size; - } - block->size = blk_size; - block->state = HBF_NOT_TRANSFERED; - - /* consider the remainder if we're already at the end */ - if( cnt == num_blocks-1 && remainder > 0 ) { - block->size = remainder; - } - overall += block->size; - /* store the block data into the result array in the transfer */ - *((transfer->block_arr)+cnt) = block; - - DEBUG_HBF("created block %d (start: %" PRId64 " size: %" PRId64 ")", cnt, block->start, block->size ); - } - -#ifndef NDEBUG - transfer->calc_size = overall; -#endif - } - return HBF_SUCCESS; -} - -void hbf_free_transfer( hbf_transfer_t *transfer ) { - int cnt; - - if( !transfer ) return; - - for( cnt = 0; cnt < transfer->block_cnt; cnt++ ) { - hbf_block_t *block = transfer->block_arr[cnt]; - if( !block ) continue; - if( block->http_error_msg ) free( block->http_error_msg ); - if( block->etag ) free( block->etag ); - } - free( transfer->block_arr ); - free( transfer->url ); - free( transfer->file_id ); - if( transfer->error_string) free( (void*) transfer->error_string ); - - free( transfer ); -} - -static char* get_transfer_url( hbf_transfer_t *transfer, int indx ) { - char *res = NULL; - - hbf_block_t *block = NULL; - - if( ! transfer ) return NULL; - if( indx >= transfer->block_cnt ) return NULL; - - block = transfer->block_arr[indx]; - if( ! block ) return NULL; - - if( transfer->block_cnt == 1 ) { - /* Just one chunk. We send as an ordinary request without chunking. */ - res = strdup( transfer->url ); - } else { - char trans_id_str[32]; - char trans_block_str[32]; - char indx_str[32]; - int len = 1; /* trailing zero. */ - int tlen = 0; - - tlen = sprintf( trans_id_str, "%u", transfer->transfer_id ); - if( tlen < 0 ) { - return NULL; - } - len += tlen; - - tlen = sprintf( trans_block_str, "%u", transfer->block_cnt ); - if( tlen < 0 ) { - return NULL; - } - len += tlen; - - tlen = sprintf( indx_str, "%u", indx ); - if( tlen < 0 ) { - return NULL; - } - len += tlen; - - len += strlen(transfer->url); - len += strlen("-chunking---"); - - res = malloc(len); - - /* Note: must be %u for unsigned because one does not want '--' */ - if( sprintf(res, "%s-chunking-%u-%u-%u", transfer->url, transfer->transfer_id, - transfer->block_cnt, indx ) < 0 ) { - return NULL; - } - } - return res; -} - -/* - * perform one transfer of one block. - * returns HBF_TRANSFER_SUCCESS if the transfer of this block was a success - * returns HBF_SUCCESS if the server aknoweldge that he received all the blocks - */ -static int _hbf_dav_request(hbf_transfer_t *transfer, ne_request *req, int fd, hbf_block_t *blk ) { - Hbf_State state = HBF_TRANSFER_SUCCESS; - int res; - const ne_status *req_status = NULL; - const char *etag = NULL; - - (void) transfer; - - if( ! (blk && req) ) return HBF_PARAM_FAIL; - - ne_set_request_body_fd(req, fd, blk->start, blk->size); - DEBUG_HBF("Block: %d , Start: %" PRId64 " and Size: %" PRId64 "", blk->seq_number, blk->start, blk->size ); - res = ne_request_dispatch(req); - - req_status = ne_get_status( req ); - - switch(res) { - case NE_OK: - blk->state = HBF_TRANSFER_FAILED; - state = HBF_FAIL; - etag = 0; - if( req_status->klass == 2 ) { - state = HBF_TRANSFER_SUCCESS; - blk->state = HBF_TRANSFER_SUCCESS; - etag = ne_get_response_header(req, "ETag"); - if (etag && etag[0]) { - /* When there is an etag, it means the transfer was complete */ - state = HBF_SUCCESS; - - if( etag[0] == '"' && etag[ strlen(etag)-1] == '"') { - int len = strlen( etag )-2; - blk->etag = malloc( len+1 ); - strncpy( blk->etag, etag+1, len ); - blk->etag[len] = '\0'; - } else { - blk->etag = strdup( etag ); - } - } else { - /* DEBUG_HBF("OOOOOOOO No etag returned!"); */ - } - - /* check if the server was able to set the mtime already. */ - etag = ne_get_response_header(req, "X-OC-MTime"); - if( etag && strcmp(etag, "accepted") == 0 ) { - /* the server acknowledged that the mtime was set. */ - transfer->modtime_accepted = 1; - } - - etag = ne_get_response_header(req, "OC-FileID"); - if( etag ) { - transfer->file_id = strdup( etag ); - } - } - break; - case NE_AUTH: - state = HBF_AUTH_FAIL; - blk->state = HBF_TRANSFER_FAILED; - break; - case NE_PROXYAUTH: - state = HBF_PROXY_AUTH_FAIL; - blk->state = HBF_TRANSFER_FAILED; - break; - case NE_CONNECT: - state = HBF_CONNECT_FAIL; - blk->state = HBF_TRANSFER_FAILED; - break; - case NE_TIMEOUT: - state = HBF_TIMEOUT_FAIL; - blk->state = HBF_TRANSFER_FAILED; - break; - case NE_ERROR: - state = HBF_FAIL; - blk->state = HBF_TRANSFER_FAILED; - break; - } - - blk->http_result_code = req_status->code; - if( req_status->reason_phrase ) { - blk->http_error_msg = strdup(req_status->reason_phrase); - } - - return state; -} - -Hbf_State hbf_validate_source_file( hbf_transfer_t *transfer ) { - Hbf_State state = HBF_SUCCESS; - hbf_stat_t sb; - - if( transfer == NULL ) { - state = HBF_PARAM_FAIL; - } - - if( state == HBF_SUCCESS ) { - if( transfer->fd <= 0 ) { - state = HBF_PARAM_FAIL; - } - } - - if( state == HBF_SUCCESS ) { - int rc = _hbf_fstat( transfer->fd, &sb ); - if( rc != 0 ) { - state = HBF_STAT_FAIL; - } - } - - if( state == HBF_SUCCESS ) { - if( sb.st_mtime != transfer->modtime || sb.st_size != transfer->stat_size ) { - state = HBF_SOURCE_FILE_CHANGE; - } - } - return state; -} - -/* Get the HTTP error code for the last request */ -static int _hbf_http_error_code(ne_session *session) { - const char *msg = ne_get_error( session ); - char *msg2; - int err; - err = strtol(msg, &msg2, 10); - if (msg == msg2) { - err = 0; - } - return err; -} - -static Hbf_State _hbf_transfer_no_chunk(ne_session *session, hbf_transfer_t *transfer, const char *verb) { - int res; - const ne_status* req_status; - - ne_request *req = ne_request_create(session, verb ? verb : "PUT", transfer->url); - if (!req) - return HBF_MEMORY_FAIL; - - ne_add_request_header( req, "Content-Type", "application/octet-stream"); - - ne_set_request_body_fd(req, transfer->fd, 0, transfer->stat_size); - DEBUG_HBF("HBF: chunking not supported for %s", transfer->url); - res = ne_request_dispatch(req); - req_status = ne_get_status( req ); - - if (res == NE_OK && req_status->klass == 2) { - ne_request_destroy(req); - return HBF_SUCCESS; - } - - if( transfer->error_string ) free( transfer->error_string ); - transfer->error_string = strdup( ne_get_error(session) ); - transfer->status_code = req_status->code; - ne_request_destroy(req); - return HBF_FAIL; -} - -Hbf_State hbf_transfer( ne_session *session, hbf_transfer_t *transfer, const char *verb ) { - Hbf_State state = HBF_TRANSFER_SUCCESS; - int cnt; - - if( ! session ) { - state = HBF_SESSION_FAIL; - } - if( ! transfer ) { - state = HBF_SPLITLIST_FAIL; - } - if( ! verb ) { - state = HBF_PARAM_FAIL; - } - - if(state == HBF_TRANSFER_SUCCESS) { - DEBUG_HBF("%s request to %s", verb, transfer->url); - } - - for( cnt=0; state == HBF_TRANSFER_SUCCESS && cnt < transfer->block_cnt; cnt++ ) { - /* cnt goes from O to block_cnt, but block_id starts at start_id and wrap around - * That way if we have not finished uploaded when we reach block_cnt, we re-upload - * the beginning of the file that the server did not have in cache anymore. - */ - int block_id = (cnt + transfer->start_id) % transfer->block_cnt; - hbf_block_t *block = transfer->block_arr[block_id]; - char *transfer_url = NULL; - - if( ! block ) state = HBF_PARAM_FAIL; - - if( transfer->abort_cb ) { - int do_abort = (transfer->abort_cb)(transfer->user_data); - if( do_abort ) { - state = HBF_USER_ABORTED; - transfer->start_id = block_id % transfer->block_cnt; - } - } - - if( state == HBF_TRANSFER_SUCCESS ) { - transfer_url = get_transfer_url( transfer, block_id ); - if( ! transfer_url ) { - state = HBF_PARAM_FAIL; - } - } - - if( state == HBF_TRANSFER_SUCCESS ) { - if( transfer->block_cnt > 1 && cnt > 0 ) { - /* The block count is > 1, check size and mtime before transmitting. */ - state = hbf_validate_source_file(transfer); - if( state == HBF_SOURCE_FILE_CHANGE ) { - /* The source file has changed meanwhile */ - } - } - } - - if( state == HBF_TRANSFER_SUCCESS || state == HBF_SUCCESS ) { - ne_request *req = ne_request_create(session, verb, transfer_url); - - if( req ) { - char buf[21]; - - snprintf(buf, sizeof(buf), "%"PRId64, transfer->stat_size); - ne_add_request_header(req, "OC-Total-Length", buf); - if( transfer->oc_header_modtime > 0 ) { - snprintf(buf, sizeof(buf), "%"PRId64, transfer->oc_header_modtime); - ne_add_request_header(req, "X-OC-Mtime", buf); - } - - if( transfer->previous_etag ) { - ne_add_request_header(req, "If-Match", transfer->previous_etag); - } - - if( transfer->block_cnt > 1 ) { - ne_add_request_header(req, "OC-Chunked", "1"); - snprintf(buf, sizeof(buf), "%"PRId64, transfer->threshold); - ne_add_request_header(req, "OC-Chunk-Size", buf); - } - ne_add_request_header( req, "Content-Type", "application/octet-stream"); - - state = _hbf_dav_request(transfer, req, transfer->fd, block ); - - if( state != HBF_TRANSFER_SUCCESS && state != HBF_SUCCESS) { - if( transfer->error_string ) free( transfer->error_string ); - transfer->error_string = strdup( ne_get_error(session) ); - transfer->start_id = block_id % transfer->block_cnt; - /* Set the code of the last transmission. */ - state = HBF_FAIL; - transfer->status_code = transfer->block_arr[block_id]->http_result_code; - } - ne_request_destroy(req); - - if (transfer->block_cnt > 1 && state == HBF_SUCCESS && cnt == 0) { - /* Success on the first chunk is suspicious. - It could happen that the server did not support chunking */ - int rc = ne_delete(session, transfer_url); - if (rc == NE_OK && _hbf_http_error_code(session) == 204) { - /* If delete suceeded, it means some proxy strips the OC_CHUNKING header - start again without chunking: */ - free( transfer_url ); - return _hbf_transfer_no_chunk(session, transfer, verb); - } - } - - if (state == HBF_TRANSFER_SUCCESS && transfer->chunk_finished_cb) { - transfer->chunk_finished_cb(transfer, block_id, transfer->user_data); - } - - } else { - state = HBF_MEMORY_FAIL; - } - } - free( transfer_url ); - } - - /* do the source file validation finally (again). */ - if( state == HBF_TRANSFER_SUCCESS ) { - /* This means that no etag was returned on one of the chunks to indicate - * that the upload was finished. */ - state = HBF_TRANSFER_NOT_ACKED; - } - - return state; -} - -int hbf_fail_http_code( hbf_transfer_t *transfer ) -{ - int cnt; - - if( ! transfer ) return 0; - - for( cnt = 0; cnt < transfer->block_cnt; cnt++ ) { - int block_id = (cnt + transfer->start_id) % transfer->block_cnt; - hbf_block_t *block = transfer->block_arr[block_id]; - - if( block->state != HBF_NOT_TRANSFERED && block->state != HBF_TRANSFER_SUCCESS ) { - return block->http_result_code; - } - } - return 200; -} - -const char *hbf_transfer_etag( hbf_transfer_t *transfer ) -{ - int cnt; - const char *etag = NULL; - - if( ! transfer ) return 0; - - /* Loop over all parts and do a assertion that there is only one etag. */ - for( cnt = 0; cnt < transfer->block_cnt; cnt++ ) { - int block_id = (cnt + transfer->start_id) % transfer->block_cnt; - hbf_block_t *block = transfer->block_arr[block_id]; - if( block->etag ) { - if( etag && strcmp(etag, block->etag) != 0 ) { - /* multiple etags in the transfer, not equal. */ - DEBUG_HBF( "WARN: etags are not equal in blocks of one single transfer." ); - } - etag = block->etag; - } - } - return etag; -} - -const char *hbf_transfer_file_id( hbf_transfer_t *transfer ) -{ - const char *re = NULL; - if(transfer) { - re = transfer->file_id; - } - return re; -} - -const char *hbf_error_string(hbf_transfer_t *transfer, Hbf_State state) -{ - const char *re; - int cnt; - switch( state ) { - case HBF_SUCCESS: - re = "Ok."; - break; - case HBF_NOT_TRANSFERED: /* never tried to transfer */ - re = "Block was not yet tried to transfer."; - break; - case HBF_TRANSFER: /* transfer currently running */ - re = "Block is currently transferred."; - break; - case HBF_TRANSFER_FAILED: /* transfer tried but failed */ - re = "Block transfer failed."; - break; - case HBF_TRANSFER_SUCCESS: /* transfer succeeded. */ - re = "Block transfer successful."; - break; - case HBF_SPLITLIST_FAIL: /* the file could not be split */ - re = "Splitlist could not be computed."; - break; - case HBF_SESSION_FAIL: - re = "No valid session in transfer."; - break; - case HBF_FILESTAT_FAIL: - re = "Source file could not be stat'ed."; - break; - case HBF_PARAM_FAIL: - re = "Parameter fail."; - break; - case HBF_AUTH_FAIL: - re = "Authentication fail."; - break; - case HBF_PROXY_AUTH_FAIL: - re = "Proxy Authentication fail."; - break; - case HBF_CONNECT_FAIL: - re = "Connection could not be established."; - break; - case HBF_TIMEOUT_FAIL: - re = "Network timeout."; - break; - case HBF_MEMORY_FAIL: - re = "Out of memory."; - break; - case HBF_STAT_FAIL: - re = "Filesystem stat on file failed."; - break; - case HBF_SOURCE_FILE_CHANGE: - re = "Source file changed too often during upload."; - break; - case HBF_USER_ABORTED: - re = "Transmission aborted by user."; - break; - case HBF_TRANSFER_NOT_ACKED: - re = "The server did not provide an Etag."; - break; - case HBF_FAIL: - default: - for( cnt = 0; cnt < transfer->block_cnt; cnt++ ) { - int block_id = (cnt + transfer->start_id) % transfer->block_cnt; - hbf_block_t *block = transfer->block_arr[block_id]; - - if( block->state != HBF_NOT_TRANSFERED && block->state != HBF_TRANSFER_SUCCESS - && block->http_error_msg != NULL) { - return block->http_error_msg; - } - } - re = "Unknown error."; - } - return re; -} - -void hbf_set_abort_callback( hbf_transfer_t *transfer, hbf_abort_callback cb) -{ - if( transfer ) { - transfer->abort_cb = cb; - } -} - -void hbf_set_log_callback(hbf_transfer_t* transfer, hbf_log_callback cb) -{ - if( transfer ) { - transfer->log_cb = cb; - } -} diff --git a/csync/src/httpbf/src/httpbf.h b/csync/src/httpbf/src/httpbf.h deleted file mode 100644 index 2d7ea2ed4..000000000 --- a/csync/src/httpbf/src/httpbf.h +++ /dev/null @@ -1,142 +0,0 @@ -/** - * http big file functions - * - * 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 _HBF_SEND_H -#define _HBF_SEND_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_session.h> - -#ifdef __cplusplus -extern "C" { -#endif - -enum hbf_state_e { - HBF_SUCCESS, - HBF_NOT_TRANSFERED, /* never tried to transfer */ - HBF_TRANSFER, /* transfer currently running */ - HBF_TRANSFER_FAILED, /* transfer tried but failed */ - HBF_TRANSFER_SUCCESS, /* block transfer succeeded. */ - HBF_SPLITLIST_FAIL, /* the file could not be split */ - HBF_SESSION_FAIL, - HBF_FILESTAT_FAIL, - HBF_PARAM_FAIL, - HBF_AUTH_FAIL, - HBF_PROXY_AUTH_FAIL, - HBF_CONNECT_FAIL, - HBF_TIMEOUT_FAIL, - HBF_MEMORY_FAIL, - HBF_STAT_FAIL, - HBF_SOURCE_FILE_CHANGE, - HBF_USER_ABORTED, - HBF_TRANSFER_NOT_ACKED, - HBF_FAIL -}; - -typedef enum hbf_state_e Hbf_State; - -typedef struct hbf_block_s hbf_block_t; - -struct hbf_block_s { - int seq_number; - - int64_t start; - int64_t size; - - Hbf_State state; - int http_result_code; - char *http_error_msg; - char *etag; - - int tries; -}; - -typedef struct hbf_transfer_s hbf_transfer_t; - -/* Callback for to check on abort */ -typedef int (*hbf_abort_callback) (void *); -typedef void (*hbf_log_callback) (const char *, const char *, void*); -typedef void (*hbf_chunk_finished_callback) (hbf_transfer_t*,int, void*); - -struct hbf_transfer_s { - hbf_block_t **block_arr; - int block_cnt; - int fd; - int transfer_id; - char *url; - int start_id; - - int status_code; - char *error_string; - - int64_t stat_size; - time_t modtime; - time_t oc_header_modtime; - int64_t block_size; - int64_t threshold; - - void *user_data; - hbf_abort_callback abort_cb; - hbf_log_callback log_cb; - hbf_chunk_finished_callback chunk_finished_cb; - int modtime_accepted; - const char *previous_etag; /* etag send as the If-Match http header */ - char *file_id; - -#ifndef NDEBUG - int64_t calc_size; -#endif -}; - -hbf_transfer_t *hbf_init_transfer( const char *dest_uri ); - -Hbf_State hbf_transfer( ne_session *session, hbf_transfer_t *transfer, const char *verb ); - -Hbf_State hbf_splitlist( hbf_transfer_t *transfer, int fd ); - -void hbf_free_transfer( hbf_transfer_t *transfer ); - -const char *hbf_error_string(hbf_transfer_t* transfer, Hbf_State state); - -const char *hbf_transfer_etag( hbf_transfer_t *transfer ); - -const char *hbf_transfer_file_id( hbf_transfer_t *transfer ); - -void hbf_set_abort_callback( hbf_transfer_t *transfer, hbf_abort_callback cb); -void hbf_set_log_callback( hbf_transfer_t *transfer, hbf_log_callback cb); - -/* returns an http (error) code of the transmission. If the transmission - * succeeded, the code is 200. If it failed, its the error code of the - * first part transmission that failed. - */ -int hbf_fail_http_code( hbf_transfer_t *transfer ); - -Hbf_State hbf_validate_source_file( hbf_transfer_t *transfer ); - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/csync/src/httpbf/tests/CMakeLists.txt b/csync/src/httpbf/tests/CMakeLists.txt deleted file mode 100644 index 4e6c647ef..000000000 --- a/csync/src/httpbf/tests/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -project(hbf_test C ) - -add_definitions(-DUNIT_TESTING=1) - -find_package(CMocka REQUIRED) - -include_directories( - ${CMAKE_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMOCKA_INCLUDE_DIRS} - ${NEON_INCLUDE_DIRS} - ${HTTPBF_PUBLIC_INCLUDE_DIRS} -) - -add_executable(send_test hbf_send_test.c) -target_link_libraries(send_test ${CMOCKA_LIBRARIES} ${NEON_LIBRARIES} ${HBF_LIBRARY} ) - - diff --git a/csync/src/httpbf/tests/church.jpg b/csync/src/httpbf/tests/church.jpg Binary files differdeleted file mode 100644 index 71bfd1a71..000000000 --- a/csync/src/httpbf/tests/church.jpg +++ /dev/null diff --git a/csync/src/httpbf/tests/hbf_send_test.c b/csync/src/httpbf/tests/hbf_send_test.c deleted file mode 100644 index 60a93009d..000000000 --- a/csync/src/httpbf/tests/hbf_send_test.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * httpbf - send big files via http - * - * Copyright (c) 2012 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 - */ - -#define _GNU_SOURCE /* See feature_test_macros(7) */ -#include <stdio.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <string.h> - -#include <cmocka.h> - -#include "config_csync.h" - -#include <httpbf.h> - - -// A test case that does nothing and succeeds. -static void null_test_success(void **state) { - (void) state; -} - - -static char* test_file( const char* name ) { - if( ! name ) return 0; - - char path[260]; - strcpy( path, TESTFILEDIR); - if(path[strlen(TESTFILEDIR)-1] != '/') - strcat( path, "/"); - strcat( path, name ); - - return strdup(path); -} - -static void test_get_transfer_url( void **state ) { - const char *url = "http://example.org/owncloud"; - const char *turl = NULL; - char res[256]; - int i; - Hbf_State hbf_state; - - hbf_transfer_t *list = NULL; - list = hbf_init_transfer( url ); - assert_non_null( list ); - - /* open a file */ - int fd = open( test_file("church.jpg"), O_RDONLY ); - assert_true(fd >= 0); - - hbf_state = hbf_splitlist(list, fd); - assert_true( hbf_state == HBF_SUCCESS); - - for( i=0; i < list->block_cnt; i++ ) { - turl = get_transfer_url( list, i ); - - sprintf(res, "%s-chunking-%d-%d-%d", url, list->transfer_id, - list->block_cnt, i ); - printf( "XX: %s\n", res ); - assert_string_equal( turl, res ); - - } -} - -static void test_hbf_init_transfer( void **state ) { - hbf_transfer_t *list = NULL; - const char *url = "http://example.org/owncloud"; - - list = hbf_init_transfer( url ); - assert_non_null( list ); - assert_string_equal( url, list->url ); -} - -/* test with a file size that is not a multiply of the slize size. */ -static void test_hbf_splitlist_odd( void **state ){ - - hbf_transfer_t *list = NULL; - const char *dest_url = "http://localhost/ocm/remote.php/webdav/big/church.jpg"; - - /* open a file */ - int fd = open(test_file("church.jpg"), O_RDONLY); - assert_true(fd >= 0); - - int prev_id = 0; - int i; - - Hbf_State hbf_state; - - /* do a smoke test for uniqueness */ - for( i=0; i < 10000; i++) { - list = hbf_init_transfer(dest_url); - assert_non_null(list); - usleep(1); - hbf_state = hbf_splitlist(list, fd); - - assert_int_not_equal(list->transfer_id, prev_id); - prev_id = list->transfer_id; - hbf_free_transfer(list); - } - - list = hbf_init_transfer(dest_url); - assert_non_null(list); - - hbf_state = hbf_splitlist(list, fd); - assert_non_null(list); - assert_int_equal(list->calc_size, list->stat_size); - assert_int_not_equal(list->block_cnt, 0); - assert_true( hbf_state == HBF_SUCCESS); - - /* checks on the block list */ - int seen_zero_seq = 0; - int prev_seq = -1; - int64_t prev_block_end = -1; - - for( i=0; i < list->block_cnt; i++) { - hbf_block_t *blk = list->block_arr[i]; - assert_non_null(blk); - if( blk->seq_number == 0 ) seen_zero_seq++; - - assert_int_equal(prev_seq, blk->seq_number -1 ); - prev_seq = blk->seq_number; - - assert_true((prev_block_end+1) == (blk->start)); - prev_block_end = blk->start + blk->size; - } - /* Make sure we exactly saw blk->seq_number == 0 exactly one times */ - assert_int_equal( seen_zero_seq, 1 ); - - hbf_free_transfer( list ); -} - -int main(void) { - const UnitTest tests[] = { - unit_test(null_test_success), - unit_test(test_hbf_splitlist_odd), - unit_test(test_hbf_init_transfer), - unit_test(test_get_transfer_url) - }; - return run_tests(tests); -} diff --git a/csync/src/vio/csync_vio.c b/csync/src/vio/csync_vio.c index b143d6033..3993af9a1 100644 --- a/csync/src/vio/csync_vio.c +++ b/csync/src/vio/csync_vio.c @@ -36,9 +36,6 @@ #define CSYNC_LOG_CATEGORY_NAME "csync.vio.main" #include "csync_log.h" -#if USE_NEON -#include "csync_owncloud.h" -#endif csync_vio_handle_t *csync_vio_opendir(CSYNC *ctx, const char *name) { switch(ctx->replica) { @@ -132,8 +129,5 @@ char *csync_vio_get_status_string(CSYNC *ctx) { if(ctx->error_string) { return ctx->error_string; } -#ifdef USE_NEON - return owncloud_error_string(ctx); -#endif return 0; } diff --git a/csync/tests/CMakeLists.txt b/csync/tests/CMakeLists.txt index a57c24eae..33eeee11a 100644 --- a/csync/tests/CMakeLists.txt +++ b/csync/tests/CMakeLists.txt @@ -7,7 +7,6 @@ include_directories( ${CSTDLIB_PUBLIC_INCLUDE_DIRS} ${CMAKE_BINARY_DIR} ${CMOCKA_INCLUDE_DIR} - ${HTTPBF_PUBLIC_INCLUDE_DIRS} ) include_directories(${CHECK_INCLUDE_DIRS}) @@ -54,10 +53,6 @@ add_cmocka_test(check_csync_update csync_tests/check_csync_update.c ${TEST_TARGE # encoding add_cmocka_test(check_encoding_functions encoding_tests/check_encoding.c ${TEST_TARGET_LIBRARIES}) -# httpbf -set(TEST_HTTPBF_LIBRARIES ${TEST_TARGET_LIBRARIES} ${NEON_LIBRARIES}) -add_cmocka_test(check_httpbf httpbf_tests/hbf_send_test.c ${TEST_HTTPBF_LIBRARIES} ) - if(UNIT_TESTING) INSTALL( FILES "${CMOCKA_LIBRARIES}" DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif(UNIT_TESTING) diff --git a/csync/tests/httpbf_tests/hbf_send_test.c b/csync/tests/httpbf_tests/hbf_send_test.c deleted file mode 100644 index 0989758f0..000000000 --- a/csync/tests/httpbf_tests/hbf_send_test.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * libcsync -- a library to sync a directory with another - * - * Copyright (c) 2013 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 - */ -#include <stdio.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <string.h> -#include <unistd.h> - -#include <cmocka.h> - -#include "config_test.h" - -#if USE_NEON -#include "httpbf.c" -#endif - -// A test case that does nothing and succeeds. -static void null_test_success(void **state) { - (void) state; -} - -#if USE_NEON - -static char* test_file( const char* name ) { - char path[260]; - - if( ! name ) return 0; - - strcpy( path, TESTFILES_DIR); - if(path[strlen(TESTFILES_DIR)-1] != '/') - strcat( path, "/"); - strcat( path, name ); - - return strdup(path); -} - -static void test_get_transfer_url( void **state ) { - const char *url = "http://example.org/owncloud"; - const char *turl = NULL; - int fd; - Hbf_State hbf_state; - - hbf_transfer_t *list = NULL; - - (void) state; - list = hbf_init_transfer( url ); - assert_non_null( list ); - - /* open a file */ - fd = open( test_file("church.jpg"), O_RDONLY ); - assert_true(fd >= 0); - - hbf_state = hbf_splitlist(list, fd); - assert_true( hbf_state == HBF_SUCCESS); - assert_true( list->block_cnt == 1); - - turl = get_transfer_url( list, 0 ); - assert_non_null( turl ); - assert_string_equal( url, turl ); - - hbf_free_transfer( list ); -} - - -static void test_get_transfer_url_bigfile( void **state ) { - const char *url = "http://example.org/big_file"; - const char *turl = NULL; - char res[256]; - int i, fd; - Hbf_State hbf_state; - hbf_transfer_t *list = NULL; - - (void) state; - - list = hbf_init_transfer( url ); - assert_non_null( list ); - - list->threshold = list->block_size = (1024*1024); /* block size 1 MB */ - - /* open a file */ - fd = open( test_file("church.jpg"), O_RDONLY ); - assert_true(fd >= 0); - - hbf_state = hbf_splitlist(list, fd); - assert_true( hbf_state == HBF_SUCCESS); - assert_true( list->block_cnt == 2 ); - - for( i=0; i < list->block_cnt; i++ ) { - turl = get_transfer_url( list, i ); - assert_non_null(turl); - - sprintf(res, "%s-chunking-%u-%u-%u", url, list->transfer_id, - list->block_cnt, i ); - /* printf( "XX: %s\n", res ); */ - assert_string_equal( turl, res ); - } - hbf_free_transfer(list); -} - -static void test_hbf_init_transfer( void **state ) { - hbf_transfer_t *list = NULL; - const char *url = "http://example.org/owncloud"; - - (void) state; - - list = hbf_init_transfer( url ); - assert_non_null( list ); - assert_string_equal( url, list->url ); -} - -/* test with a file size that is not a multiply of the slize size. */ -static void test_hbf_splitlist_odd( void **state ){ - - hbf_transfer_t *list = NULL; - const char *dest_url = "http://localhost/ocm/remote.php/webdav/big/church.jpg"; - int prev_id = 0; - int i, fd; - Hbf_State hbf_state; - - (void) state; - - /* open a file */ - fd = open(test_file("church.jpg"), O_RDONLY); - assert_true(fd >= 0); - - /* do a smoke test for uniqueness */ - for( i=0; i < 10000; i++) { - list = hbf_init_transfer(dest_url); - assert_non_null(list); - usleep(1); - hbf_state = hbf_splitlist(list, fd); - - assert_int_not_equal(list->transfer_id, prev_id); - prev_id = list->transfer_id; - hbf_free_transfer(list); - } - - list = hbf_init_transfer(dest_url); - assert_non_null(list); - - hbf_state = hbf_splitlist(list, fd); - assert_non_null(list); -#ifndef NDEBUG - assert_int_equal(list->calc_size, list->stat_size); -#endif - assert_int_not_equal(list->block_cnt, 0); - assert_true( hbf_state == HBF_SUCCESS); - - /* checks on the block list */ - if( 1 ) { - int seen_zero_seq = 0; - int prev_seq = -1; - int64_t prev_block_end = -1; - - for( i=0; i < list->block_cnt; i++) { - hbf_block_t *blk = list->block_arr[i]; - assert_non_null(blk); - if( blk->seq_number == 0 ) seen_zero_seq++; - - assert_int_equal(prev_seq, blk->seq_number -1 ); - prev_seq = blk->seq_number; - - assert_true((prev_block_end+1) == (blk->start)); - prev_block_end = blk->start + blk->size; - } - /* Make sure we exactly saw blk->seq_number == 0 exactly one times */ - assert_int_equal( seen_zero_seq, 1 ); - } - hbf_free_transfer( list ); -} - -/* test with a file size that is not a multiply of the slize size. */ -static void test_hbf_splitlist_zero( void **state ){ - - hbf_transfer_t *list = NULL; - const char *dest_url = "http://localhost/ocm/remote.php/webdav/big/zerofile.txt"; - int fd; - Hbf_State hbf_state; - - (void) state; - - /* open a file */ - fd = open(test_file("zerofile.txt"), O_RDONLY); - assert_true(fd >= 0); - - list = hbf_init_transfer(dest_url); - assert_non_null(list); - - hbf_state = hbf_splitlist(list, fd); - assert_non_null(list); - assert_int_equal(list->stat_size, 0); -#ifndef NDEBUG - assert_int_equal(list->calc_size, list->stat_size); -#endif - assert_int_equal(list->block_cnt, 1); - - assert_true( hbf_state == HBF_SUCCESS); - - hbf_free_transfer( list ); -} - -#endif - - -int main(void) { - const UnitTest tests[] = { - unit_test(null_test_success), -#if USE_NEON - unit_test(test_hbf_splitlist_odd), - unit_test(test_hbf_splitlist_zero), - unit_test(test_hbf_init_transfer), - unit_test(test_get_transfer_url), - unit_test(test_get_transfer_url_bigfile) -#endif - }; - return run_tests(tests); -} - diff --git a/src/cmd/cmd.cpp b/src/cmd/cmd.cpp index d596710e7..77c231a14 100644 --- a/src/cmd/cmd.cpp +++ b/src/cmd/cmd.cpp @@ -379,15 +379,11 @@ restart_sync: // ignore hidden files or not _csync_ctx->ignore_hidden_files = options.ignoreHiddenFiles; - csync_set_module_property(_csync_ctx, "csync_context", _csync_ctx); if( !options.proxy.isNull() ) { QString host; int port = 0; bool ok; - // Set as default and let overwrite later - csync_set_module_property(_csync_ctx, "proxy_type", (void*) "NoProxy"); - QStringList pList = options.proxy.split(':'); if(pList.count() == 3) { // http: //192.168.178.23 : 8080 @@ -397,13 +393,6 @@ restart_sync: port = pList.at(2).toInt(&ok); - if( !host.isNull() ) { - csync_set_module_property(_csync_ctx, "proxy_type", (void*) "HttpProxy"); - csync_set_module_property(_csync_ctx, "proxy_host", host.toUtf8().data()); - if( ok && port ) { - csync_set_module_property(_csync_ctx, "proxy_port", (void*) &port); - } - } QNetworkProxyFactory::setUseSystemConfiguration(false); QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, host, port)); } @@ -414,7 +403,6 @@ restart_sync: url.remove(0, 8); url = QString("http%1").arg(url); } - clientProxy.setCSyncProxy(QUrl(url), _csync_ctx); } // Exclude lists diff --git a/src/gui/creds/shibbolethcredentials.cpp b/src/gui/creds/shibbolethcredentials.cpp index d0e29edbf..2e8308812 100644 --- a/src/gui/creds/shibbolethcredentials.cpp +++ b/src/gui/creds/shibbolethcredentials.cpp @@ -76,7 +76,7 @@ void ShibbolethCredentials::setAccount(Account* account) void ShibbolethCredentials::syncContextPreInit(CSYNC* ctx) { - csync_set_auth_callback (ctx, handleNeonSSLProblems); + Q_UNUSED(ctx); } QByteArray ShibbolethCredentials::prepareCookieData() const @@ -93,7 +93,7 @@ QByteArray ShibbolethCredentials::prepareCookieData() const void ShibbolethCredentials::syncContextPreStart (CSYNC* ctx) { - csync_set_module_property(ctx, "session_key", prepareCookieData().data()); + Q_UNUSED(ctx); } bool ShibbolethCredentials::changed(AbstractCredentials* credentials) const @@ -207,8 +207,6 @@ void ShibbolethCredentials::invalidateToken() jar->clearSessionCookies(); removeShibCookie(); _shibCookie = QNetworkCookie(); - // ### access to ctx missing, but might not be required at all - //csync_set_module_property(ctx, "session_key", ""); } void ShibbolethCredentials::onShibbolethCookieReceived(const QNetworkCookie& shibCookie) diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp index 226e501bb..9dad4c939 100644 --- a/src/gui/folder.cpp +++ b/src/gui/folder.cpp @@ -839,9 +839,7 @@ void Folder::startSync(const QStringList &pathList) QMetaObject::invokeMethod(this, "slotSyncFinished", Qt::QueuedConnection); return; } - _clientProxy.setCSyncProxy(_accountState->account()->url(), _csync_ctx); } else if (proxyDirty()) { - _clientProxy.setCSyncProxy(_accountState->account()->url(), _csync_ctx); setProxyDirty(false); } diff --git a/src/gui/networksettings.cpp b/src/gui/networksettings.cpp index ef13a9480..2c5a22a71 100644 --- a/src/gui/networksettings.cpp +++ b/src/gui/networksettings.cpp @@ -117,6 +117,21 @@ void NetworkSettings::loadProxySettings() void NetworkSettings::loadBWLimitSettings() { +#if QT_VERSION < QT_VERSION_CHECK(5,3,3) + // QNAM bandwith limiting only works with versions of Qt greater or equal to 5.3.3 + // (It needs Qt commits 097b641 and b99fa32) + _ui->noDownloadLimitRadioButton->setChecked(true); + _ui->downloadLimitRadioButton->setEnabled(false); + _ui->noDownloadLimitRadioButton->setEnabled(false); + _ui->autoDownloadLimitRadioButton->setEnabled(false); + + _ui->noUploadLimitRadioButton->setChecked(true); + _ui->uploadLimitRadioButton->setEnabled(false); + _ui->noUploadLimitRadioButton->setEnabled(false); + _ui->autoUploadLimitRadioButton->setEnabled(false); + return; +#endif + ConfigFile cfgFile; int useDownloadLimit = cfgFile.useDownloadLimit(); diff --git a/src/libsync/CMakeLists.txt b/src/libsync/CMakeLists.txt index af340b49a..2daedad16 100644 --- a/src/libsync/CMakeLists.txt +++ b/src/libsync/CMakeLists.txt @@ -7,7 +7,6 @@ configure_file( version.h.in "${CMAKE_CURRENT_BINARY_DIR}/version.h" ) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) # csync is required. include_directories(${CMAKE_SOURCE_DIR}/csync/src - ${CMAKE_SOURCE_DIR}/csync/src/httpbf/src ${CMAKE_BINARY_DIR}/csync ${CMAKE_BINARY_DIR}/csync/src ) @@ -73,13 +72,6 @@ set(libsync_SRCS ../3rdparty/certificates/p12topem.cpp ) -if(USE_NEON) - list(APPEND libsync_SRCS - propagator_legacy.cpp - ) - add_definitions(-DUSE_NEON) -endif(USE_NEON) - # These headers are installed for libowncloudsync to be used by 3rd party apps set(owncloudsync_HEADERS account.h @@ -125,15 +117,6 @@ if(INOTIFY_FOUND) link_directories(${INOTIFY_LIBRARY_DIR}) endif() -if(NEON_FOUND) - list(APPEND libsync_LINK_TARGETS ${NEON_LIBRARIES} httpbf) - include_directories(${NEON_INCLUDE_DIRS}) - - if(NEON_WITH_LFS) - add_definitions(-DNE_LFS) - endif() -endif() - if(ZLIB_FOUND) list(APPEND libsync_LINK_TARGETS ${ZLIB_LIBRARIES}) include_directories(${ZLIB_INCLUDE_DIRS}) diff --git a/src/libsync/clientproxy.cpp b/src/libsync/clientproxy.cpp index 095d3489c..721906645 100644 --- a/src/libsync/clientproxy.cpp +++ b/src/libsync/clientproxy.cpp @@ -115,39 +115,6 @@ const char* ClientProxy::proxyTypeToCStr(QNetworkProxy::ProxyType type) } } -void ClientProxy::setCSyncProxy( const QUrl& url, CSYNC *csync_ctx ) -{ -#ifdef USE_NEON - /* Store proxy */ - QList<QNetworkProxy> proxies = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(url)); - // We set at least one in Application - Q_ASSERT(proxies.count() > 0); - if (proxies.count() == 0) { - qDebug() << Q_FUNC_INFO << "No proxy!"; - return; - } - QNetworkProxy proxy = proxies.first(); - if (proxy.type() == QNetworkProxy::NoProxy) { - qDebug() << "Passing NO proxy to csync for" << url.toString(); - } else { - qDebug() << "Passing" << proxy.hostName() << "of proxy type " << proxy.type() - << " to csync for" << url.toString(); - } - - csync_set_module_property( csync_ctx, "proxy_type", (void*)(proxyTypeToCStr(proxy.type()))); - csync_set_module_property( csync_ctx, "proxy_host", proxy.hostName().toUtf8().data()); - int proxy_port = proxy.port(); - csync_set_module_property( csync_ctx, "proxy_port", &proxy_port ); - csync_set_module_property( csync_ctx, "proxy_user", proxy.user().toUtf8().data()); - csync_set_module_property( csync_ctx, "proxy_pwd", proxy.password().toUtf8().data()); -#else - Q_UNUSED(url); - Q_UNUSED(csync_ctx); -#endif -} - - - void ClientProxy::lookupSystemProxyAsync(const QUrl &url, QObject *dst, const char *slot) { SystemProxyRunnable *runnable = new SystemProxyRunnable(url); diff --git a/src/libsync/clientproxy.h b/src/libsync/clientproxy.h index 93216e705..c377a04d8 100644 --- a/src/libsync/clientproxy.h +++ b/src/libsync/clientproxy.h @@ -40,7 +40,6 @@ public: static void lookupSystemProxyAsync(const QUrl &url, QObject *dst, const char *slot); public slots: - void setCSyncProxy( const QUrl& url, CSYNC *csync_ctx ); void setupQtProxyFromConfig(); private: diff --git a/src/libsync/creds/credentialscommon.cpp b/src/libsync/creds/credentialscommon.cpp index 7ea5c1d77..c13019f63 100644 --- a/src/libsync/creds/credentialscommon.cpp +++ b/src/libsync/creds/credentialscommon.cpp @@ -30,52 +30,5 @@ namespace OCC { -int handleNeonSSLProblems(const char* prompt, - char* buf, - size_t /*len*/, - int /*echo*/, - int /*verify*/, - void* userdata) -{ - int re = 0; - const QString qPrompt = QString::fromLatin1( prompt ).trimmed(); - SyncEngine* engine = reinterpret_cast<SyncEngine*>(userdata); - - if( qPrompt.startsWith( QLatin1String("There are problems with the SSL certificate:"))) { - // SSL is requested. If the program came here, the SSL check was done by Qt - // It needs to be checked if the chain is still equal to the one which - // was verified by the user. - const QRegExp regexp("fingerprint: ([\\w\\d:]+)"); - bool certOk = false; - int pos = 0; - // This is the set of certificates which QNAM accepted, so we should accept - // them as well - QList<QSslCertificate> certs = engine->account()->sslConfiguration().peerCertificateChain(); - - while (!certOk && (pos = regexp.indexIn(qPrompt, 1+pos)) != -1) { - QString neon_fingerprint = regexp.cap(1); - - foreach( const QSslCertificate& c, certs ) { - QString verified_shasum = Utility::formatFingerprint(c.digest(QCryptographicHash::Sha1).toHex()); - qDebug() << "SSL Fingerprint from neon: " << neon_fingerprint << " compared to verified: " << verified_shasum; - if( verified_shasum == neon_fingerprint ) { - certOk = true; - break; - } - } - } - // certOk = false; DEBUG setting, keep disabled! - if( !certOk ) { // Problem! - qstrcpy( buf, "no" ); - re = -1; - } else { - qstrcpy( buf, "yes" ); // Certificate is fine! - } - } else { - qDebug() << "Unknown prompt: <" << prompt << ">"; - re = -1; - } - return re; -} } // namespace OCC diff --git a/src/libsync/creds/credentialscommon.h b/src/libsync/creds/credentialscommon.h index ac518d6e6..9a66fbd54 100644 --- a/src/libsync/creds/credentialscommon.h +++ b/src/libsync/creds/credentialscommon.h @@ -21,13 +21,6 @@ namespace OCC { -OWNCLOUDSYNC_EXPORT int handleNeonSSLProblems(const char* prompt, - char* buf, - size_t len, - int echo, - int verify, - void* userdata); - } // namespace OCC #endif diff --git a/src/libsync/creds/httpcredentials.cpp b/src/libsync/creds/httpcredentials.cpp index f161c4aa2..69f132e67 100644 --- a/src/libsync/creds/httpcredentials.cpp +++ b/src/libsync/creds/httpcredentials.cpp @@ -35,44 +35,6 @@ using namespace QKeychain; namespace OCC { -int getauth(const char *prompt, - char *buf, - size_t len, - int echo, - int verify, - void *userdata) -{ - int re = 0; - - // ### safe? Not really. If the wizard is run in the main thread, the caccount could change during the sync. - SyncEngine* engine = reinterpret_cast<SyncEngine*>(userdata); - HttpCredentials* http_credentials = qobject_cast<HttpCredentials*>(engine->account()->credentials()); - - if (!http_credentials) { - qDebug() << "Not a HTTP creds instance!"; - return -1; - } - - QString qPrompt = QString::fromLatin1( prompt ).trimmed(); - QString user = http_credentials->user(); - QString pwd = http_credentials->password(); - - if( qPrompt == QLatin1String("Enter your username:") ) { - // qDebug() << "OOO Username requested!"; - qstrncpy( buf, user.toUtf8().constData(), len ); - } else if( qPrompt == QLatin1String("Enter your password:") ) { - // qDebug() << "OOO Password requested!"; - qstrncpy( buf, pwd.toUtf8().constData(), len ); - } else { - if( http_credentials->sslIsTrusted() ) { - qstrcpy( buf, "yes" ); // Certificate is fine! - } else { - re = handleNeonSSLProblems(prompt, buf, len, echo, verify, userdata); - } - } - return re; -} - namespace { const char userC[] = "user"; @@ -97,31 +59,12 @@ HttpCredentials::HttpCredentials(const QString& user, const QString& password, c void HttpCredentials::syncContextPreInit (CSYNC* ctx) { - csync_set_auth_callback (ctx, getauth); - // create a SSL client certificate configuration in CSYNC* ctx - struct csync_client_certs_s clientCerts; - clientCerts.certificatePath = strdup(_certificatePath.toStdString().c_str()); - clientCerts.certificatePasswd = strdup(_certificatePasswd.toStdString().c_str()); - csync_set_module_property(ctx, "SSLClientCerts", &clientCerts); - free(clientCerts.certificatePath); - free(clientCerts.certificatePasswd); + Q_UNUSED(ctx); } void HttpCredentials::syncContextPreStart (CSYNC* ctx) { - QList<QNetworkCookie> cookies(_account->lastAuthCookies()); - QString cookiesAsString; - - // Stuff cookies inside csync, then we can avoid the intermediate HTTP 401 reply - // when https://github.com/owncloud/core/pull/4042 is merged. - foreach(QNetworkCookie c, cookies) { - cookiesAsString += c.name(); - cookiesAsString += '='; - cookiesAsString += c.value(); - cookiesAsString += "; "; - } - - csync_set_module_property(ctx, "session_key", cookiesAsString.toLatin1().data()); + Q_UNUSED(ctx); } bool HttpCredentials::changed(AbstractCredentials* credentials) const diff --git a/src/libsync/creds/tokencredentials.cpp b/src/libsync/creds/tokencredentials.cpp index 5e4896df5..f5ed499ca 100644 --- a/src/libsync/creds/tokencredentials.cpp +++ b/src/libsync/creds/tokencredentials.cpp @@ -33,41 +33,6 @@ namespace OCC namespace { -int getauth(const char *prompt, - char *buf, - size_t len, - int echo, - int verify, - void *userdata) -{ - int re = 0; - QMutex mutex; - // ### safe? - TokenCredentials* http_credentials = qobject_cast<TokenCredentials*>(AccountManager::instance()->account()->credentials()); - - if (!http_credentials) { - qDebug() << "Not a HTTP creds instance!"; - return -1; - } - - QString qPrompt = QString::fromLatin1( prompt ).trimmed(); - QString user = http_credentials->user(); - QString pwd = http_credentials->password(); - - if( qPrompt == QLatin1String("Enter your username:") ) { - // qDebug() << "OOO Username requested!"; - QMutexLocker locker( &mutex ); - qstrncpy( buf, user.toUtf8().constData(), len ); - } else if( qPrompt == QLatin1String("Enter your password:") ) { - QMutexLocker locker( &mutex ); - // qDebug() << "OOO Password requested!"; - qstrncpy( buf, pwd.toUtf8().constData(), len ); - } else { - re = handleNeonSSLProblems(prompt, buf, len, echo, verify, userdata); - } - return re; -} - const char authenticationFailedC[] = "owncloud-authentication-failed"; } // ns @@ -117,12 +82,12 @@ TokenCredentials::TokenCredentials(const QString& user, const QString& password, void TokenCredentials::syncContextPreInit (CSYNC* ctx) { - csync_set_auth_callback (ctx, getauth); + Q_UNUSED(ctx); } void TokenCredentials::syncContextPreStart (CSYNC* ctx) { - csync_set_module_property(ctx, "session_key", _token.toUtf8().data()); + Q_UNUSED(ctx); } bool TokenCredentials::changed(AbstractCredentials* credentials) const diff --git a/src/libsync/owncloudpropagator.cpp b/src/libsync/owncloudpropagator.cpp index a93e84f3e..79a91203d 100644 --- a/src/libsync/owncloudpropagator.cpp +++ b/src/libsync/owncloudpropagator.cpp @@ -22,9 +22,6 @@ #include "propagateremotemove.h" #include "propagateremotemkdir.h" #include "propagatorjobs.h" -#ifdef USE_NEON -#include "propagator_legacy.h" -#endif #include "configfile.h" #include "utility.h" #include "account.h" @@ -193,11 +190,7 @@ bool PropagateItemJob::checkForProblemsWithShared(int httpStatusCode, const QStr downloadItem->_instruction = CSYNC_INSTRUCTION_SYNC; } downloadItem->_direction = SyncFileItem::Down; -#ifdef USE_NEON - newJob = new PropagateDownloadFileLegacy(_propagator, downloadItem); -#else newJob = new PropagateDownloadFileQNAM(_propagator, downloadItem); -#endif } else { // Directories are harder to recover. // But just re-create the directory, next sync will be able to recover the files @@ -256,15 +249,6 @@ PropagateItemJob* OwncloudPropagator::createJob(const SyncFileItemPtr &item) { // Should we set the mtime? return 0; } -#ifdef USE_NEON - if (useLegacyJobs()) { - if (item->_direction != SyncFileItem::Up) { - return new PropagateDownloadFileLegacy(this, item); - } else { - return new PropagateUploadFileLegacy(this, item); - } - } else -#endif { if (item->_direction != SyncFileItem::Up) { return new PropagateDownloadFileQNAM(this, item); @@ -386,7 +370,7 @@ void OwncloudPropagator::start(const SyncFileItemVector& items) connect(_rootJob.data(), SIGNAL(finished(SyncFileItem::Status)), this, SLOT(emitFinished())); connect(_rootJob.data(), SIGNAL(ready()), this, SLOT(scheduleNextJob()), Qt::QueuedConnection); - qDebug() << (useLegacyJobs() ? "Using legacy libneon/HTTP sequential code path" : "Using QNAM/HTTP parallel code path"); + qDebug() << "Using QNAM/HTTP parallel code path"; QTimer::singleShot(0, this, SLOT(scheduleNextJob())); } @@ -406,51 +390,6 @@ bool OwncloudPropagator::isInSharedDirectory(const QString& file) return re; } -/** - * Return true if we should use the legacy jobs. - * Some features are not supported by QNAM and therefore we still use the legacy jobs - * for this case. - */ -bool OwncloudPropagator::useLegacyJobs() -{ -#ifdef USE_NEON - // Allow an environement variable for debugging - QByteArray env = qgetenv("OWNCLOUD_USE_LEGACY_JOBS"); - if (env=="true" || env =="1") { - qDebug() << "Force Legacy Propagator ACTIVATED"; - return true; - } - - if (_downloadLimit.fetchAndAddAcquire(0) != 0 || _uploadLimit.fetchAndAddAcquire(0) != 0) { - // QNAM bandwith limiting only works with versions of Qt greater or equal to 5.3.3 - // (It needs Qt commits 097b641 and b99fa32) -#if QT_VERSION >= QT_VERSION_CHECK(5,3,3) - return false; -#elif QT_VERSION >= QT_VERSION_CHECK(5,0,0) - env = qgetenv("OWNCLOUD_NEW_BANDWIDTH_LIMITING"); - if (env=="true" || env =="1") { - qDebug() << "New Bandwidth Limiting Code ACTIVATED"; - return false; - } - - // Do a runtime check. - // (Poor man's version comparison) - const char *v = qVersion(); // "x.y.z"; - if (QLatin1String(v) >= QLatin1String("5.3.3")) { - return false; - } else { - qDebug() << "Use legacy jobs because qt version is only" << v << "while 5.3.3 is needed"; - return true; - } -#else - qDebug() << "Use legacy jobs because of Qt4"; - return true; -#endif - } -#endif // USE_NEON - return false; -} - int OwncloudPropagator::httpTimeout() { static int timeout; diff --git a/src/libsync/owncloudpropagator.h b/src/libsync/owncloudpropagator.h index 6c56c0cfa..2e334856e 100644 --- a/src/libsync/owncloudpropagator.h +++ b/src/libsync/owncloudpropagator.h @@ -30,11 +30,6 @@ #include "bandwidthmanager.h" #include "accountfwd.h" -struct hbf_transfer_s; -struct ne_session_s; -struct ne_decompress_s; -typedef struct ne_prop_result_set_s ne_prop_result_set; - namespace OCC { /** Free disk space threshold below which syncs will abort and not even start. @@ -127,7 +122,6 @@ signals: /* * Abstract class to propagate a single item - * (Only used for neon job) */ class PropagateItemJob : public PropagatorJob { Q_OBJECT @@ -260,14 +254,8 @@ class OwncloudPropagator : public QObject { PropagateItemJob *createJob(const SyncFileItemPtr& item); QScopedPointer<PropagateDirectory> _rootJob; - bool useLegacyJobs(); public: - /* 'const' because they are accessed by the thread */ - - QThread* _neonThread; - ne_session_s * const _session; - 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) @@ -277,12 +265,10 @@ public: public: - OwncloudPropagator(AccountPtr account, ne_session_s *session, const QString &localDir, + OwncloudPropagator(AccountPtr account, const QString &localDir, const QString &remoteDir, const QString &remoteFolder, - SyncJournalDb *progressDb, QThread *neonThread) - : _neonThread(neonThread) - , _session(session) - , _localDir((localDir.endsWith(QChar('/'))) ? localDir : localDir+'/' ) + SyncJournalDb *progressDb) + : _localDir((localDir.endsWith(QChar('/'))) ? localDir : localDir+'/' ) , _remoteDir((remoteDir.endsWith(QChar('/'))) ? remoteDir : remoteDir+'/' ) , _remoteFolder((remoteFolder.endsWith(QChar('/'))) ? remoteFolder : remoteFolder+'/' ) , _journal(progressDb) diff --git a/src/libsync/propagateupload.cpp b/src/libsync/propagateupload.cpp index 4fe2182f2..9aef0adaf 100644 --- a/src/libsync/propagateupload.cpp +++ b/src/libsync/propagateupload.cpp @@ -31,10 +31,6 @@ #include <cmath> #include <cstring> -#ifdef USE_NEON -#include "propagator_legacy.h" -#endif - #if QT_VERSION < QT_VERSION_CHECK(5, 4, 2) namespace { const char owncloudShouldSoftCancelPropertyName[] = "owncloud-should-soft-cancel"; @@ -691,15 +687,8 @@ void PropagateUploadFileQNAM::slotPutFinished() // X-OC-MTime is supported since owncloud 5.0. But not when chunking. // Normally Owncloud 6 always puts X-OC-MTime qWarning() << "Server does not support X-OC-MTime" << job->reply()->rawHeader("X-OC-MTime"); -#ifdef USE_NEON - PropagatorJob *newJob = new UpdateMTimeAndETagJob(_propagator, _item); - QObject::connect(newJob, SIGNAL(itemCompleted(SyncFileItem, PropagatorJob)), - this, SLOT(finalize(SyncFileItem))); - QMetaObject::invokeMethod(newJob, "start"); - return; -#else // Well, the mtime was not set -#endif + done(SyncFileItem::SoftError, "Server does not support X-OC-MTime"); } // performance logging diff --git a/src/libsync/propagator_legacy.cpp b/src/libsync/propagator_legacy.cpp deleted file mode 100644 index 8c518663f..000000000 --- a/src/libsync/propagator_legacy.cpp +++ /dev/null @@ -1,735 +0,0 @@ -/* - * Copyright (C) by Olivier Goffart <ogoffart@owncloud.com> - * Copyright (C) by Klaas Freitag <freitag@owncloud.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "propagator_legacy.h" -#include "owncloudpropagator_p.h" - -#include "utility.h" -#include "syncjournaldb.h" -#include "syncjournalfilerecord.h" -#include "filesystem.h" -#include <httpbf.h> -#include <qfile.h> -#include <qdir.h> -#include <qdiriterator.h> -#include <qtemporaryfile.h> -#include <QDebug> -#include <QDateTime> -#include <qstack.h> -#include <QCoreApplication> - -#include <neon/ne_basic.h> -#include <neon/ne_socket.h> -#include <neon/ne_session.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 <time.h> - - -namespace OCC { - -static QByteArray get_etag_from_reply(ne_request *req) -{ - QByteArray ret = parseEtag(ne_get_response_header(req, "OC-ETag")); - if (ret.isEmpty()) { - ret = parseEtag(ne_get_response_header(req, "ETag")); - } - if (ret.isEmpty()) { - ret = parseEtag(ne_get_response_header(req, "etag")); - } - return ret; -} - -bool PropagateNeonJob::updateErrorFromSession(int neon_code, ne_request* req, int ignoreHttpCode) -{ - if( neon_code != NE_OK ) { - qDebug("Neon error code was %d", neon_code); - } - - QString errorString; - int httpStatusCode = 0; - - switch(neon_code) { - case NE_OK: /* Success, but still the possiblity of problems */ - if( req ) { - const ne_status *status = ne_get_status(req); - - if (status) { - if ( status->klass == 2 || status->code == ignoreHttpCode) { - // Everything is ok, no error. - return false; - } - errorString = QString::fromUtf8( status->reason_phrase ); - httpStatusCode = status->code; - _item->_httpErrorCode = httpStatusCode; - } - } else { - errorString = QString::fromUtf8(ne_get_error(_propagator->_session)); - httpStatusCode = errorString.mid(0, errorString.indexOf(QChar(' '))).toInt(); - _item->_httpErrorCode = httpStatusCode; - if ((httpStatusCode >= 200 && httpStatusCode < 300) - || (httpStatusCode != 0 && httpStatusCode == ignoreHttpCode)) { - // No error - return false; - } - } - // FIXME: classify the error - done (SyncFileItem::NormalError, errorString); - return true; - case NE_ERROR: /* Generic error; use ne_get_error(session) for message */ - errorString = QString::fromUtf8(ne_get_error(_propagator->_session)); - // Check if we don't need to ignore that error. - httpStatusCode = errorString.mid(0, errorString.indexOf(QChar(' '))).toInt(); - _item->_httpErrorCode = httpStatusCode; - qDebug() << Q_FUNC_INFO << "NE_ERROR" << errorString << httpStatusCode << ignoreHttpCode; - if (ignoreHttpCode && httpStatusCode == ignoreHttpCode) - return false; - - done(SyncFileItem::NormalError, errorString); - return true; - case NE_LOOKUP: /* Server or proxy hostname lookup failed */ - case NE_AUTH: /* User authentication failed on server */ - case NE_PROXYAUTH: /* User authentication failed on proxy */ - case NE_CONNECT: /* Could not connect to server */ - case NE_TIMEOUT: /* Connection timed out */ - done(SyncFileItem::FatalError, QString::fromUtf8(ne_get_error(_propagator->_session))); - return true; - case NE_FAILED: /* The precondition failed */ - case NE_RETRY: /* Retry request (ne_end_request ONLY) */ - case NE_REDIRECT: /* See ne_redirect.h */ - default: - done(SyncFileItem::SoftError, QString::fromUtf8(ne_get_error(_propagator->_session))); - return true; - } - return false; -} - -void UpdateMTimeAndETagJob::start() -{ - QScopedPointer<char, QScopedPointerPodDeleter> uri( - ne_path_escape((_propagator->_remoteDir + _item->_file).toUtf8())); - if (!updateMTimeAndETag(uri.data(), _item->_modtime)) - return; - done(SyncFileItem::Success); -} - -void PropagateUploadFileLegacy::start() -{ - if (_propagator->_abortRequested.fetchAndAddRelaxed(0)) - return; - - QFile file(_propagator->getFilePath(_item->_file)); - if (!file.open(QIODevice::ReadOnly)) { - done(SyncFileItem::NormalError, file.errorString()); - return; - } - QScopedPointer<char, QScopedPointerPodDeleter> uri( - ne_path_escape((_propagator->_remoteDir + _item->_file).toUtf8())); - - int attempts = 0; - - /* - * do ten tries to upload the file chunked. Check the file size and mtime - * before submitting a chunk and after having submitted the last one. - * If the file has changed, retry. - */ - qDebug() << "** PUT request to" << uri.data(); - const SyncJournalDb::UploadInfo progressInfo = _propagator->_journal->getUploadInfo(_item->_file); - - do { - Hbf_State state = HBF_SUCCESS; - QScopedPointer<hbf_transfer_t, ScopedPointerHelpers> trans(hbf_init_transfer(uri.data())); - Q_ASSERT(trans); - trans->user_data = this; - hbf_set_log_callback(trans.data(), _log_callback); - hbf_set_abort_callback(trans.data(), _user_want_abort); - trans.data()->chunk_finished_cb = chunk_finished_cb; - static uint chunkSize = qgetenv("OWNCLOUD_CHUNK_SIZE").toUInt(); - if (chunkSize > 0) { - trans->block_size = trans->threshold = chunkSize; - } - - state = hbf_splitlist(trans.data(), file.handle()); - - // This is the modtime hbf will announce to the server. - // We don't trust the modtime hbf computes itself via _fstat64 - // on windows - hbf may only use it to detect file changes during - // upload. - trans->oc_header_modtime = FileSystem::getModTime(file.fileName()); - - // If the source file has changed during upload, it is detected and the - // variable _previousFileSize is set accordingly. The propagator waits a - // couple of seconds and retries. - if(_previousFileSize > 0) { - qDebug() << "File size changed underway: " << trans->stat_size - _previousFileSize; - // Report the change of the overall transmission size to the propagator (queued connection because we are in a thread) - QMetaObject::invokeMethod(_propagator, "adjustTotalTransmissionSize", Qt::QueuedConnection, - Q_ARG(qint64, trans->stat_size - _previousFileSize)); - // update the item's values to the current from trans. hbf_splitlist does a stat - _item->_size = trans->stat_size; - _item->_modtime = trans->oc_header_modtime; - - } - emit progress(*_item, 0); - - if (progressInfo._valid) { - if (Utility::qDateTimeToTime_t(progressInfo._modtime) == _item->_modtime) { - trans->start_id = progressInfo._chunk; - trans->transfer_id = progressInfo._transferid; - } - } - - ne_set_notifier(_propagator->_session, notify_status_cb, this); - _lastTime.restart(); - _lastProgress = 0; - _chunked_done = 0; - _chunked_total_size = _item->_size; - - if( state == HBF_SUCCESS ) { - QByteArray previousEtag; - if (!_item->_etag.isEmpty() && _item->_etag != "empty_etag") { - // We add quotes because the owncloud server always adds quotes around the etag, and - // csync_owncloud.c's owncloud_file_id always strips the quotes. - previousEtag = '"' + _item->_etag + '"'; - trans->previous_etag = previousEtag.data(); - } - _chunked_total_size = trans->stat_size; - qDebug() << "About to upload " << _item->_file << " (" << previousEtag << _item->_size << " bytes )"; - /* Transfer all the chunks through the HTTP session using PUT. */ - state = hbf_transfer( _propagator->_session, trans.data(), "PUT" ); - } - - // the file id should only be empty for new files up- or downloaded - QByteArray fid = hbf_transfer_file_id( trans.data() ); - if( !fid.isEmpty() ) { - if( !_item->_fileId.isEmpty() && _item->_fileId != fid ) { - qDebug() << "WARN: File ID changed!" << _item->_fileId << fid; - } - _item->_fileId = fid; - } - - /* Handle errors. */ - if ( state != HBF_SUCCESS ) { - - /* If the source file changed during submission, lets try again */ - if( state == HBF_SOURCE_FILE_CHANGE ) { - if( attempts++ < 5 ) { /* FIXME: How often do we want to try? */ - qDebug("SOURCE file has changed during upload, retry #%d in %d seconds!", attempts, 2*attempts); - Utility::sleep(2*attempts); - if( _previousFileSize == 0 ) { - _previousFileSize = _item->_size; - } else { - _previousFileSize = trans->stat_size; - } - continue; - } - - const QString errMsg = tr("Local file changed during sync, syncing once it arrives completely"); - done( SyncFileItem::SoftError, errMsg ); - } else if( state == HBF_USER_ABORTED ) { - const QString errMsg = tr("Sync was aborted by user."); - done( SyncFileItem::SoftError, errMsg ); - } else { - // Other HBF error conditions. - _item->_httpErrorCode = hbf_fail_http_code(trans.data()); - if(checkForProblemsWithShared(_item->_httpErrorCode, - tr("The file was edited locally but is part of a read only share. " - "It is restored and your edit is in the conflict file."))) - return; - - done(SyncFileItem::NormalError, hbf_error_string(trans.data(), state)); - } - return; - } - - ne_set_notifier(_propagator->_session, 0, 0); - - if( trans->modtime_accepted ) { - _item->_etag = parseEtag(hbf_transfer_etag( trans.data() )); - } else { - if (!updateMTimeAndETag(uri.data(), trans->oc_header_modtime)) - return; - } - - _propagator->_journal->setFileRecord(SyncJournalFileRecord(*_item, _propagator->getFilePath(_item->_file))); - // Remove from the progress database: - _propagator->_journal->setUploadInfo(_item->_file, SyncJournalDb::UploadInfo()); - _propagator->_journal->commit("upload file start"); - - if (hbf_validate_source_file(trans.data()) == HBF_SOURCE_FILE_CHANGE) { - /* Has the source file changed since the upload ? - * This is different from the previous check because the previous check happens between - * chunks while this one happens when the whole file has been uploaded. - * - * The new etag is already stored in the database in the previous lines so in case of - * crash, we won't have a conflict but we will properly do a new upload - */ - - if( attempts++ < 5 ) { /* FIXME: How often do we want to try? */ - qDebug("SOURCE file has changed after upload, retry #%d in %d seconds!", attempts, 2*attempts); - Utility::sleep(2*attempts); - continue; - } - - // Still the file change error, but we tried a couple of times. - // Ignore this file for now. - // Lets remove the file from the server (at least if it is new) as it is different - // from our file here. - if( _item->_instruction == CSYNC_INSTRUCTION_NEW ) { - QScopedPointer<char, QScopedPointerPodDeleter> uri( - ne_path_escape((_propagator->_remoteDir + _item->_file).toUtf8())); - - int rc = ne_delete(_propagator->_session, uri.data()); - qDebug() << "Remove the invalid file from server:" << rc; - } - - const QString errMsg = tr("Local file changed during sync, syncing once it arrives completely"); - done( SyncFileItem::SoftError, errMsg ); - return; - } - - done(SyncFileItem::Success); - return; - - } while( true ); -} - -void PropagateUploadFileLegacy::chunk_finished_cb(hbf_transfer_s *trans, int chunk, void* userdata) -{ - PropagateUploadFileLegacy *that = static_cast<PropagateUploadFileLegacy *>(userdata); - Q_ASSERT(that); - that->_chunked_done += trans->block_arr[chunk]->size; - if (trans->block_cnt > 1) { - SyncJournalDb::UploadInfo pi; - pi._valid = true; - pi._chunk = chunk + 1; // next chunk to start with - pi._transferid = trans->transfer_id; - pi._modtime = Utility::qDateTimeFromTime_t(trans->oc_header_modtime); - that->_propagator->_journal->setUploadInfo(that->_item->_file, pi); - that->_propagator->_journal->commit("Upload info"); - } -} - -void PropagateUploadFileLegacy::notify_status_cb(void* userdata, ne_session_status status, - const ne_session_status_info* info) -{ - PropagateUploadFileLegacy* that = reinterpret_cast<PropagateUploadFileLegacy*>(userdata); - - if (status == ne_status_sending && info->sr.total > 0) { - emit that->progress(*that->_item, that->_chunked_done + info->sr.progress); - - that->limitBandwidth(that->_chunked_done + info->sr.progress, that->_propagator->_uploadLimit.fetchAndAddAcquire(0)); - } -} - - - -static QByteArray parseFileId(ne_request *req) { - QByteArray fileId; - - const char *header = ne_get_response_header(req, "OC-FileId"); - if( header ) { - fileId = header; - } - return fileId; -} - -bool PropagateNeonJob::updateMTimeAndETag(const char* uri, time_t mtime) -{ - QByteArray modtime = QByteArray::number(qlonglong(mtime)); - ne_propname pname; - pname.nspace = "DAV:"; - pname.name = "lastmodified"; - ne_proppatch_operation ops[2]; - ops[0].name = &pname; - ops[0].type = ne_propset; - ops[0].value = modtime.constData(); - ops[1].name = NULL; - - int rc = ne_proppatch( _propagator->_session, uri, ops ); - Q_UNUSED(rc); - /* FIXME: error handling - * bool error = updateErrorFromSession( rc ); - * if( error ) { - * // FIXME: We could not set the mtime. Error or not? - * qDebug() << "PROP-Patching of modified date failed."; -}*/ - - // get the etag - QScopedPointer<ne_request, ScopedPointerHelpers> req(ne_request_create(_propagator->_session, "HEAD", uri)); - int neon_stat = ne_request_dispatch(req.data()); - if (updateErrorFromSession(neon_stat, req.data())) { - return false; - } else { - _item->_etag = get_etag_from_reply(req.data()); - - QByteArray fid = parseFileId(req.data()); - if( _item->_fileId.isEmpty() ) { - _item->_fileId = fid; - qDebug() << "FileID was empty, set it to " << _item->_fileId; - } else { - if( !fid.isEmpty() && fid != _item->_fileId ) { - qDebug() << "WARN: FileID seems to have changed: "<< fid << _item->_fileId; - } else { - qDebug() << "FileID is " << _item->_fileId; - } - } - return true; - } -} - -void PropagateNeonJob::limitBandwidth(qint64 progress, qint64 bandwidth_limit) -{ - if (_propagator->_abortRequested.fetchAndAddRelaxed(0)) { - // Do not limit bandwidth when aborting to speed up the current transfer - return; - } - - if (bandwidth_limit > 0) { - int64_t diff = _lastTime.nsecsElapsed() / 1000; - int64_t len = progress - _lastProgress; - if (len > 0 && diff > 0 && (1000000 * len / diff) > bandwidth_limit) { - int64_t wait_time = (1000000 * len / bandwidth_limit) - diff; - if (wait_time > 0) { - //qDebug() << "Limiting bandwidth to " << bandwidth_limit << "KB/s by waiting " << wait_time << " µs; "; - OCC::Utility::usleep(wait_time); - } - } - _lastProgress = progress; - _lastTime.start(); - } else if (bandwidth_limit < 0 && bandwidth_limit > -100) { - int64_t diff = _lastTime.nsecsElapsed() / 1000; - if (diff > 0) { - // -bandwidth_limit is the % of bandwidth - int64_t wait_time = -diff * (1 + 100.0 / bandwidth_limit); - if (wait_time > 0) { - OCC::Utility::usleep(qMin(wait_time, int64_t(1000000*10))); - } - } - _lastTime.start(); - } -} - -int PropagateDownloadFileLegacy::content_reader(void *userdata, const char *buf, size_t len) -{ - PropagateDownloadFileLegacy *that = static_cast<PropagateDownloadFileLegacy *>(userdata); - size_t written = 0; - - if (that->_propagator->_abortRequested.fetchAndAddRelaxed(0)) { - ne_set_error(that->_propagator->_session, "%s", tr("Sync was aborted by user.").toUtf8().data()); - return NE_ERROR; - } - - if(buf) { - written = that->_file->write(buf, len); - if( len != written || that->_file->error() != QFile::NoError) { - qDebug() << "WRN: content_reader wrote wrong num of bytes:" << len << "," << written; - return NE_ERROR; - } - return NE_OK; - } - - return NE_ERROR; -} - -/* - * This hook is called after the response is here from the server, but before - * the response body is parsed. It decides if the response is compressed and - * if it is it installs the compression reader accordingly. - * If the response is not compressed, the normal response body reader is installed. - */ -void PropagateDownloadFileLegacy::install_content_reader( ne_request *req, void *userdata, const ne_status *status ) -{ - PropagateDownloadFileLegacy *that = static_cast<PropagateDownloadFileLegacy *>(userdata); - - Q_UNUSED(status); - - if( !that ) { - qDebug("Error: install_content_reader called without valid write context!"); - return; - } - - if( ne_get_status(req)->klass != 2 ) { - qDebug() << "Request class != 2, aborting."; - ne_add_response_body_reader( req, do_not_accept, - do_not_download_content_reader, - (void*) that ); - return; - } - - QByteArray reason_phrase = ne_get_status(req)->reason_phrase; - if(reason_phrase == QByteArray("Connection established")) { - ne_add_response_body_reader( req, ne_accept_2xx, - content_reader, - (void*) that ); - return; - } - - QByteArray etag = get_etag_from_reply(req); - - if (etag.isEmpty()) { - qDebug() << Q_FUNC_INFO << "No E-Tag reply by server, considering it invalid" << ne_get_response_header(req, "etag"); - that->abortTransfer(req, tr("No E-Tag received from server, check Proxy/Gateway")); - return; - } else if (!that->_expectedEtagForResume.isEmpty() && that->_expectedEtagForResume != etag) { - qDebug() << Q_FUNC_INFO << "We received a different E-Tag for resuming!" - << QString::fromLatin1(that->_expectedEtagForResume.data()) << "vs" - << QString::fromLatin1(etag.data()); - that->abortTransfer(req, tr("We received a different E-Tag for resuming. Retrying next time.")); - return; - } - - quint64 start = 0; - QByteArray ranges = ne_get_response_header(req, "content-range"); - if (!ranges.isEmpty()) { - QRegExp rx("bytes (\\d+)-"); - if (rx.indexIn(ranges) >= 0) { - start = rx.cap(1).toULongLong(); - } - } - if (start != that->_resumeStart) { - qDebug() << Q_FUNC_INFO << "Wrong content-range: "<< ranges << " while expecting start was" << that->_resumeStart; - if (start == 0) { - // device doesn't support range, just try again from scratch - that->_file->close(); - if (!that->_file->open(QIODevice::WriteOnly)) { - that->abortTransfer(req, that->_file->errorString()); - return; - } - } else { - that->abortTransfer(req, tr("Server returned wrong content-range")); - return; - } - } - - - const char *enc = ne_get_response_header( req, "Content-Encoding" ); - qDebug("Content encoding ist <%s> with status %d", enc ? enc : "empty", - status ? status->code : -1 ); - - if( enc == QLatin1String("gzip") ) { - that->_decompress.reset(ne_decompress_reader( req, ne_accept_2xx, - content_reader, /* reader callback */ - that )); /* userdata */ - } else { - ne_add_response_body_reader( req, ne_accept_2xx, - content_reader, - (void*) that ); - } -} - -void PropagateDownloadFileLegacy::abortTransfer(ne_request* req, const QString& error) -{ - errorString = error; - ne_set_error(_propagator->_session, "%s", errorString.toUtf8().data()); - ne_add_response_body_reader( req, do_not_accept, - do_not_download_content_reader, - this); -} - - -void PropagateDownloadFileLegacy::notify_status_cb(void* userdata, ne_session_status status, - const ne_session_status_info* info) -{ - PropagateDownloadFileLegacy* that = reinterpret_cast<PropagateDownloadFileLegacy*>(userdata); - if (status == ne_status_recving && info->sr.total > 0) { - emit that->progress(*that->_item, info->sr.progress ); - - that->limitBandwidth(info->sr.progress, that->_propagator->_downloadLimit.fetchAndAddAcquire(0)); - } -} - -extern QString makeConflictFileName(const QString &fn, const QDateTime &dt); // propagatedownload.cpp - -void PropagateDownloadFileLegacy::start() -{ - if (_propagator->_abortRequested.fetchAndAddRelaxed(0)) - return; - - // do a case clash check. - if( _propagator->localFileNameClash(_item->_file) ) { - done( SyncFileItem::NormalError, tr("File %1 can not be downloaded because of a local file name clash!") - .arg(QDir::toNativeSeparators(_item->_file)) ); - return; - } - - emit progress(*_item, 0); - - QString tmpFileName; - const SyncJournalDb::DownloadInfo progressInfo = _propagator->_journal->getDownloadInfo(_item->_file); - if (progressInfo._valid) { - // if the etag has changed meanwhile, remove the already downloaded part. - if (progressInfo._etag != _item->_etag) { - QFile::remove(_propagator->getFilePath(progressInfo._tmpfile)); - _propagator->_journal->setDownloadInfo(_item->_file, SyncJournalDb::DownloadInfo()); - } else { - tmpFileName = progressInfo._tmpfile; - _expectedEtagForResume = progressInfo._etag; - } - - } - - if (tmpFileName.isEmpty()) { - tmpFileName = _item->_file; - //add a dot at the begining of the filename to hide the file. - int slashPos = tmpFileName.lastIndexOf('/'); - tmpFileName.insert(slashPos+1, '.'); - //add the suffix - tmpFileName += ".~" + QString::number(uint(qrand()), 16); - } - - QFile tmpFile(_propagator->getFilePath(tmpFileName)); - _file = &tmpFile; - if (!tmpFile.open(QIODevice::Append | QIODevice::Unbuffered)) { - done(SyncFileItem::NormalError, tmpFile.errorString()); - return; - } - - FileSystem::setFileHidden(tmpFile.fileName(), true); - - { - SyncJournalDb::DownloadInfo pi; - pi._etag = _item->_etag; - pi._tmpfile = tmpFileName; - pi._valid = true; - _propagator->_journal->setDownloadInfo(_item->_file, pi); - _propagator->_journal->commit("download file start"); - } - - if (!_item->_directDownloadUrl.isEmpty()) { - qDebug() << Q_FUNC_INFO << "Direct download URL" << _item->_directDownloadUrl << "not supported with legacy propagator, will go via ownCloud server"; - } - - /* actually do the request */ - int retry = 0; - - QScopedPointer<char, QScopedPointerPodDeleter> uri( - ne_path_escape((_propagator->_remoteDir + _item->_file).toUtf8())); - - do { - QScopedPointer<ne_request, ScopedPointerHelpers> req(ne_request_create(_propagator->_session, "GET", uri.data())); - - /* Allow compressed content by setting the header */ - ne_add_request_header( req.data(), "Accept-Encoding", "gzip" ); - - if (tmpFile.size() > 0) { - quint64 done = tmpFile.size(); - if (done == _item->_size) { - qDebug() << "File is already complete, no need to download"; - break; - } - QByteArray rangeRequest = "bytes=" + QByteArray::number(done) +'-'; - ne_add_request_header(req.data(), "Range", rangeRequest.constData()); - ne_add_request_header(req.data(), "Accept-Ranges", "bytes"); - qDebug() << "Retry with range " << rangeRequest; - _resumeStart = done; - } - - /* hook called before the content is parsed to set the correct reader, - * either the compressed- or uncompressed reader. - */ - ne_hook_post_headers( _propagator->_session, install_content_reader, this); - ne_set_notifier(_propagator->_session, notify_status_cb, this); - _lastProgress = 0; - _lastTime.start(); - - int neon_stat = ne_request_dispatch(req.data()); - - _decompress.reset(); // Destroy the decompress after the request has been dispatched. - - /* delete the hook again, otherwise they get chained as they are with the session */ - ne_unhook_post_headers( _propagator->_session, install_content_reader, this ); - ne_set_notifier(_propagator->_session, 0, 0); - - if (neon_stat == NE_TIMEOUT && (++retry) < 3) { - continue; - } - - // This one is set by install_content_reader if e.g. there is no E-Tag - if (!errorString.isEmpty()) { - // don't keep the temporary file as the file downloaded so far is invalid - tmpFile.close(); - tmpFile.remove(); - _propagator->_journal->setDownloadInfo(_item->_file, SyncJournalDb::DownloadInfo()); - done(SyncFileItem::SoftError, errorString); - return; - } - - // This one is set by neon - if( updateErrorFromSession(neon_stat, req.data() ) ) { - qDebug("Error GET: Neon: %d", neon_stat); - if (tmpFile.size() == 0) { - // don't keep the temporary file if it is empty. - tmpFile.close(); - tmpFile.remove(); - _propagator->_journal->setDownloadInfo(_item->_file, SyncJournalDb::DownloadInfo()); - } - return; - } - _item->_etag = get_etag_from_reply(req.data()); - break; - } while (1); - - tmpFile.close(); - tmpFile.flush(); - QString fn = _propagator->getFilePath(_item->_file); - - - bool isConflict = _item->_instruction == CSYNC_INSTRUCTION_CONFLICT - && !FileSystem::fileEquals(fn, tmpFile.fileName()); // compare the files to see if there was an actual conflict. - //In case of conflict, make a backup of the old file - if (isConflict) { - auto conflictDate = FileSystem::fileExists(fn) ? FileSystem::getModTime(fn) : _item->_modtime; - QString conflictFileName = makeConflictFileName(fn, Utility::qDateTimeFromTime_t(conflictDate)); - QString renameError; - if (!FileSystem::rename(fn, conflictFileName, &renameError)) { - //If the rename fails, don't replace it. - done(SyncFileItem::NormalError, renameError); - return; - } - } - - QFileInfo existingFile(fn); - if(existingFile.exists() && existingFile.permissions() != tmpFile.permissions()) { - tmpFile.setPermissions(existingFile.permissions()); - } - - FileSystem::setFileHidden(tmpFile.fileName(), false); - - QString error; - _propagator->addTouchedFile(fn); - const qint64 expectedFileSize = _item->log._other_size; - const time_t expectedFileMtime = _item->log._other_modtime; - if (!FileSystem::renameReplace(tmpFile.fileName(), fn, - expectedFileSize, expectedFileMtime, - &error)) { - done(SyncFileItem::NormalError, error); - return; - } - - FileSystem::setModTime(fn, _item->_modtime); - - _propagator->_journal->setFileRecord(SyncJournalFileRecord(*_item, fn)); - _propagator->_journal->setDownloadInfo(_item->_file, SyncJournalDb::DownloadInfo()); - _propagator->_journal->commit("download file start2"); - done(isConflict ? SyncFileItem::Conflict : SyncFileItem::Success); -} - - -} diff --git a/src/libsync/propagator_legacy.h b/src/libsync/propagator_legacy.h deleted file mode 100644 index 75ec8fda3..000000000 --- a/src/libsync/propagator_legacy.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) by Olivier Goffart <ogoffart@owncloud.com> - * Copyright (C) by Klaas Freitag <freitag@owncloud.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#pragma once - -#include "propagatorjobs.h" -#include <httpbf.h> -#include <neon/ne_compress.h> -struct hbf_transfer_s; -struct ne_session_s; -typedef struct ne_prop_result_set_s ne_prop_result_set; - - -namespace OCC { - - - -/* Helper for QScopedPointer<>, to be used as the deleter. - * QScopePointer will call the right overload of cleanup for the pointer it holds - */ -struct ScopedPointerHelpers { - static inline void cleanup(hbf_transfer_t *pointer) { if (pointer) hbf_free_transfer(pointer); } - static inline void cleanup(ne_request *pointer) { if (pointer) ne_request_destroy(pointer); } - static inline void cleanup(ne_decompress *pointer) { if (pointer) ne_decompress_destroy(pointer); } - // static inline void cleanup(ne_propfind_handler *pointer) { if (pointer) ne_propfind_destroy(pointer); } -}; - - - -/** - * @brief Abstract class for neon job. Lives in the neon thread - * @ingroup libsync - */ -class PropagateNeonJob : public PropagateItemJob { - Q_OBJECT -protected: - - /* Issue a PROPPATCH and PROPFIND to update the mtime, and fetch the etag - * Return true in case of success, and false if the PROPFIND failed and the - * error has been reported - */ - bool updateMTimeAndETag(const char *uri, time_t); - - /* fetch the error code and string from the session - in case of error, calls done with the error and returns true. - - If the HTTP error code is ignoreHTTPError, the error is ignored - */ - bool updateErrorFromSession(int neon_code = 0, ne_request *req = 0, int ignoreHTTPError = 0); - - /* - * to be called by the progress callback and will wait the amount of time needed. - */ - void limitBandwidth(qint64 progress, qint64 limit); - - QElapsedTimer _lastTime; - qint64 _lastProgress; - int _httpStatusCode; - -public: - PropagateNeonJob(OwncloudPropagator* propagator, const SyncFileItemPtr &item) - : PropagateItemJob(propagator, item), _lastProgress(0), _httpStatusCode(0) { - moveToThread(propagator->_neonThread); - } - - JobParallelism parallelism() Q_DECL_OVERRIDE { return WaitForFinished; } -}; - -/** - * @brief The UpdateMTimeAndETagJob class - * @ingroup libsync - */ -class UpdateMTimeAndETagJob : public PropagateNeonJob { - Q_OBJECT -public: - UpdateMTimeAndETagJob (OwncloudPropagator* propagator, const SyncFileItemPtr& item) : PropagateNeonJob(propagator, item) {} - void start() Q_DECL_OVERRIDE; -}; - -/** - * @brief The PropagateUploadFileLegacy class - * @ingroup libsync - */ -class PropagateUploadFileLegacy: public PropagateNeonJob { - Q_OBJECT -public: - explicit PropagateUploadFileLegacy(OwncloudPropagator* propagator,const SyncFileItemPtr& item) - : PropagateNeonJob(propagator, item) - , _chunked_done(0), _chunked_total_size(0), _previousFileSize(0) {} - void start() Q_DECL_OVERRIDE; -private: - // Log callback for httpbf - static void _log_callback(const char *func, const char *text, void*) - { - qDebug() << " " << func << text; - } - - // abort callback for httpbf - static int _user_want_abort(void *userData) - { - return static_cast<PropagateUploadFileLegacy *>(userData)->_propagator->_abortRequested.fetchAndAddRelaxed(0); - } - - // callback from httpbf when a chunk is finished - static void chunk_finished_cb(hbf_transfer_s *trans, int chunk, void* userdata); - static void notify_status_cb(void* userdata, ne_session_status status, - const ne_session_status_info* info); - - qint64 _chunked_done; // amount of bytes already sent with the previous chunks - qint64 _chunked_total_size; // total size of the whole file - qint64 _previousFileSize; // In case the file size has changed during upload, this is the previous one. -}; - -class PropagateDownloadFileLegacy: public PropagateNeonJob { - Q_OBJECT -public: - explicit PropagateDownloadFileLegacy(OwncloudPropagator* propagator,const SyncFileItemPtr& item) - : PropagateNeonJob(propagator, item), _file(0), _resumeStart(0) {} - void start() Q_DECL_OVERRIDE; -private: - QFile *_file; - QScopedPointer<ne_decompress, ScopedPointerHelpers> _decompress; - QString errorString; - QByteArray _expectedEtagForResume; - quint64 _resumeStart; - - static int do_not_accept (void *userdata, ne_request *req, const ne_status *st) - { - Q_UNUSED(userdata); Q_UNUSED(req); Q_UNUSED(st); - return 0; // ignore this response - } - - static int do_not_download_content_reader(void *userdata, const char *buf, size_t len) - { - Q_UNUSED(userdata); Q_UNUSED(buf); Q_UNUSED(len); - return NE_ERROR; - } - - // neon hooks: - static int content_reader(void *userdata, const char *buf, size_t len); - static void install_content_reader( ne_request *req, void *userdata, const ne_status *status ); - static void notify_status_cb(void* userdata, ne_session_status status, - const ne_session_status_info* info); - - /** To be called from install_content_reader if we want to abort the transfer */ - void abortTransfer(ne_request *req, const QString &error); -}; - -} diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp index ca2f8ff7c..cab49b499 100644 --- a/src/libsync/syncengine.cpp +++ b/src/libsync/syncengine.cpp @@ -47,9 +47,6 @@ #include <QElapsedTimer> #include <qtextcodec.h> -#ifdef USE_NEON -extern "C" int owncloud_commit(CSYNC* ctx); -#endif extern "C" const char *csync_instruction_str(enum csync_instructions_e instr); namespace OCC { @@ -664,11 +661,6 @@ void SyncEngine::startSync() csync_set_userdata(_csync_ctx, this); _account->credentials()->syncContextPreStart(_csync_ctx); - // csync_set_auth_callback( _csync_ctx, getauth ); - //csync_set_log_level( 11 ); don't set the loglevel here, it shall be done by folder.cpp or owncloudcmd.cpp - int timeout = OwncloudPropagator::httpTimeout(); - csync_set_module_property(_csync_ctx, "timeout", &timeout); - _stopWatch.start(); qDebug() << "#### Discovery start #################################################### >>"; @@ -799,12 +791,6 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult) } } - // FIXME: The propagator could create his session in propagator_legacy.cpp - // There's no reason to keep csync_owncloud.c around - ne_session_s *session = 0; - // that call to set property actually is a get which will return the session - csync_set_module_property(_csync_ctx, "get_dav_session", &session); - // post update phase script: allow to tweak stuff by a custom script in debug mode. if( !qgetenv("OWNCLOUD_POST_UPDATE_SCRIPT").isEmpty() ) { #ifndef NDEBUG @@ -821,7 +807,7 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult) _journal->commit("post treewalk"); _propagator = QSharedPointer<OwncloudPropagator>( - new OwncloudPropagator (_account, session, _localPath, _remoteUrl, _remotePath, _journal, &_thread)); + new OwncloudPropagator (_account, _localPath, _remoteUrl, _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)), @@ -912,11 +898,6 @@ void SyncEngine::finalize() _thread.quit(); _thread.wait(); -#ifdef USE_NEON - // De-init the neon HTTP(S) connections - owncloud_commit(_csync_ctx); -#endif - csync_commit(_csync_ctx); qDebug() << "CSync run took " << _stopWatch.addLapTime(QLatin1String("Sync Finished")); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index faab1f8c4..46972dacc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,5 +1,5 @@ include_directories(${CMAKE_BINARY_DIR}/csync ${CMAKE_BINARY_DIR}/csync/src ${CMAKE_BINARY_DIR}/src) -include_directories(${CMAKE_SOURCE_DIR}/csync/src/ ${CMAKE_SOURCE_DIR}/csync/src/httpbf/src) +include_directories(${CMAKE_SOURCE_DIR}/csync/src/) include_directories(${CMAKE_SOURCE_DIR}/csync/src/std ${CMAKE_SOURCE_DIR}/src) include(owncloud_add_test.cmake) |