1
0
mirror of https://github.com/chylex/Nextcloud-Desktop.git synced 2025-04-09 19:15:43 +02:00

Add iconv support to convert charsets to different platforms.

This commit is contained in:
Daniel Molkentin 2013-02-06 14:56:42 +01:00 committed by Andreas Schneider
parent 13bb5ca2c3
commit 9c0c693081
18 changed files with 680 additions and 56 deletions

View File

@ -39,6 +39,7 @@ macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source buil
include(MacroAddPlugin)
include(MacroCopyFile)
find_package(Iconv)
find_package(CMocka)
if (CMOCKA_FOUND AND UNIT_TESTING)
include(AddCMockaTest)

View File

@ -1,2 +1,5 @@
if ( NOT WIN32 )
option(WITH_ICONV "Build csync with iconv support" ON)
endif()
option(UNIT_TESTING "Build with unit tests" OFF)
option(MEM_NULL_TESTS "Enable NULL memory testing" OFF)

View File

@ -53,8 +53,11 @@ at LOCAL with the ones at REMOTE.\n\
--disable-statedb Disable the usage and creation of a statedb.\n\
--dry-run This runs only update detection and reconcilation.\n\
\n\
--exclude-file=<file> Add an additional exclude file\n\
--test-statedb Test creation of the statedb. Runs update\n\
--exclude-file=<file> Add an additional exclude file\n"
#ifdef WITH_ICONV
" --iconv=codec Request charset conversion of local filenames\n"
#endif
" --test-statedb Test creation of the statedb. Runs update\n\
detection.\n\
--test-update Test the update detection\n\
-?, --help Give this help list\n\
@ -68,6 +71,9 @@ static const struct option long_options[] =
{"exclude-file", required_argument, 0, 0 },
{"debug-level", required_argument, 0, 'd' },
{"disable-statedb", no_argument, 0, 0 },
#ifdef WITH_ICONV
{"iconv", required_argument, 0, 0 },
#endif
{"dry-run", no_argument, 0, 0 },
{"test-statedb", no_argument, 0, 0 },
{"conflict-copies", no_argument, 0, 'c' },
@ -82,6 +88,7 @@ struct argument_s {
char *args[2]; /* SOURCE and DESTINATION */
char *exclude_file;
int debug_level;
char *iconv;
int disable_statedb;
int create_statedb;
int update;
@ -149,7 +156,9 @@ static int parse_args(struct argument_s *csync_args, int argc, char **argv)
csync_args->reconcile = 1;
csync_args->propagate = 0;
/* printf("Argument: dry-run\n" ); */
} else if(c_streq(opt->name, "iconv")) {
csync_args->iconv = c_strdup(optarg);
/* printf("Argument: iconv\n" ); */
} else if(c_streq(opt->name, "test-statedb")) {
csync_args->create_statedb = 1;
csync_args->update = 1;
@ -158,7 +167,6 @@ static int parse_args(struct argument_s *csync_args, int argc, char **argv)
/* printf("Argument: test-statedb\n"); */
} else {
fprintf(stderr, "Argument: No idea what!\n");
}
break;
default:
@ -181,6 +189,7 @@ int main(int argc, char **argv) {
/* Default values. */
arguments.exclude_file = NULL;
arguments.debug_level = 4;
arguments.iconv = NULL;
arguments.disable_statedb = 0;
arguments.create_statedb = 0;
arguments.update = 1;
@ -227,6 +236,12 @@ int main(int argc, char **argv) {
csync_disable_statedb(csync);
}
#ifdef WITH_ICONV
if (arguments.iconv) {
csync_set_iconv_codec(arguments.iconv);
}
#endif
if(arguments.with_conflict_copys)
{
csync_enable_conflictcopys(csync);

View File

@ -0,0 +1,80 @@
# - Try to find Iconv
# Once done this will define
#
# ICONV_FOUND - system has Iconv
# ICONV_INCLUDE_DIR - the Iconv include directory
# ICONV_LIBRARIES - Link these to use Iconv
# ICONV_SECOND_ARGUMENT_IS_CONST - the second argument for iconv() is const
#
include(CheckCCompilerFlag)
include(CheckCSourceCompiles)
IF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
# Already in cache, be silent
SET(ICONV_FIND_QUIETLY TRUE)
ENDIF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
IF(APPLE)
FIND_PATH(ICONV_INCLUDE_DIR iconv.h
PATHS
/opt/local/include/
NO_CMAKE_SYSTEM_PATH
)
FIND_LIBRARY(ICONV_LIBRARIES NAMES iconv libiconv c
PATHS
/opt/local/lib/
NO_CMAKE_SYSTEM_PATH
)
ENDIF(APPLE)
FIND_PATH(ICONV_INCLUDE_DIR iconv.h PATHS /opt/local/include /sw/include)
string(REGEX REPLACE "(.*)/include/?" "\\1" ICONV_INCLUDE_BASE_DIR "${ICONV_INCLUDE_DIR}")
FIND_LIBRARY(ICONV_LIBRARIES NAMES iconv libiconv c HINTS "${ICONV_INCLUDE_BASE_DIR}/lib" PATHS /opt/local/lib)
IF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
SET(ICONV_FOUND TRUE)
ENDIF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${ICONV_LIBRARIES})
IF(ICONV_FOUND)
check_c_compiler_flag("-Werror" ICONV_HAVE_WERROR)
set (CMAKE_C_FLAGS_BACKUP "${CMAKE_C_FLAGS}")
if(ICONV_HAVE_WERROR)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
endif(ICONV_HAVE_WERROR)
check_c_source_compiles("
#include <iconv.h>
int main(){
iconv_t conv = 0;
const char* in = 0;
size_t ilen = 0;
char* out = 0;
size_t olen = 0;
iconv(conv, &in, &ilen, &out, &olen);
return 0;
}
" ICONV_SECOND_ARGUMENT_IS_CONST )
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS_BACKUP}")
ENDIF(ICONV_FOUND)
set(CMAKE_REQUIRED_INCLUDES)
set(CMAKE_REQUIRED_LIBRARIES)
IF(ICONV_FOUND)
IF(NOT ICONV_FIND_QUIETLY)
MESSAGE(STATUS "Found Iconv: ${ICONV_LIBRARIES}")
ENDIF(NOT ICONV_FIND_QUIETLY)
ELSE(ICONV_FOUND)
IF(Iconv_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find Iconv")
ENDIF(Iconv_FIND_REQUIRED)
ENDIF(ICONV_FOUND)
MARK_AS_ADVANCED(
ICONV_INCLUDE_DIR
ICONV_LIBRARIES
ICONV_SECOND_ARGUMENT_IS_CONST
)

View File

@ -11,6 +11,7 @@
#cmakedefine HAVE_CLOCK_GETTIME
#cmakedefine WITH_LOG4C 1
#cmakedefine WITH_ICONV 1
#cmakedefine HAVE_ARGP_H 1

View File

@ -32,6 +32,11 @@ set(CSYNC_LINK_LIBRARIES
${SQLITE3_LIBRARIES}
)
if(ICONV_FOUND AND WITH_ICONV)
list(APPEND CSYNC_PRIVATE_INCLUDE_DIRS ${ICONV_INCLUDE_DIRS})
list(APPEND CSYNC_LINK_LIBRARIES ${ICONV_LIBRARIES})
endif()
set(csync_SRCS
csync.c
csync_config.c

View File

@ -32,6 +32,10 @@
#include <sys/types.h>
#include <stdbool.h>
#ifdef WITH_ICONV
#include <iconv.h>
#endif
#include "c_lib.h"
#include "csync_private.h"
#include "csync_config.h"
@ -41,6 +45,7 @@
#include "csync_time.h"
#include "csync_util.h"
#include "csync_misc.h"
#include "std/c_private.h"
#include "csync_update.h"
#include "csync_reconcile.h"
@ -215,7 +220,7 @@ int csync_init(CSYNC *ctx) {
if (csync_exclude_load(ctx, exclude) < 0) {
strerror_r(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "Could not load %s - %s", exclude,
CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "Could not load %s - %s", exclude,
errbuf);
}
#endif
@ -644,6 +649,10 @@ int csync_destroy(CSYNC *ctx) {
SAFE_FREE(ctx->options.config_dir);
SAFE_FREE(ctx->statedb.file);
#ifdef WITH_ICONV
c_close_iconv();
#endif
SAFE_FREE(ctx);
SAFE_FREE(lock);
@ -833,4 +842,17 @@ bool csync_get_local_only( CSYNC *ctx ) {
return ctx->options.local_only_mode;
}
#ifdef WITH_ICONV
int csync_set_iconv_codec(const char *from)
{
c_close_iconv();
if (from != NULL) {
c_setup_iconv(from);
}
return 0;
}
#endif
/* vim: set ts=8 sw=2 et cindent: */

View File

@ -35,6 +35,7 @@
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <config.h>
#ifdef __cplusplus
extern "C" {
@ -421,6 +422,17 @@ int csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int fi
*/
int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter);
#ifdef WITH_ICONV
/**
* @brief Set iconv source codec for filenames.
*
* @param from Source codec.
*
* @return 0 on success, or an iconv error number.
*/
int csync_set_iconv_codec(const char *from);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -40,6 +40,10 @@
#include "c_private.h"
#include "csync.h"
#ifdef WITH_ICONV
#include <iconv.h>
#endif
#include "vio/csync_vio_method.h"
#include "csync_macros.h"
@ -128,6 +132,9 @@ struct csync_s {
char *config_dir;
bool with_conflict_copys;
bool local_only_mode;
#ifdef WITH_ICONV
iconv_t iconv_cd;
#endif
} options;
struct {

View File

@ -39,7 +39,8 @@
/* check if path is a file */
int c_isfile(const char *path) {
csync_stat_t sb;
const mbchar_t *wpath = c_multibyte(path);
mbchar_t *wpath = c_multibyte(path);
int re = _tstat(wpath, &sb);
c_free_multibyte(wpath);
@ -69,8 +70,10 @@ int c_copy(const char* src, const char *dst, mode_t mode) {
#ifdef _WIN32
if(src && dst) {
if (CopyFile(src, dst, FALSE)) {
return 0;
mbchar_t *wsrc = c_multibyte(src);
mbchar_t *wdst = c_multibyte(dst);
if (CopyFileW(wsrc, wdst, FALSE)) {
rc = 0;
}
errno = GetLastError();

View File

@ -31,7 +31,6 @@
#include <winbase.h>
#endif
#ifdef _WIN32
#define EDQUOT 0
#define ENODATA 0
@ -111,6 +110,13 @@ typedef char mbchar_t;
#define _trewinddir rewinddir
#endif
#ifdef WITH_ICONV
/** @internal */
int c_setup_iconv(const char* to);
/** @internal */
int c_close_iconv(void);
#endif
#endif //_C_PRIVATE_H
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */

View File

@ -20,6 +20,9 @@
* vim: ts=2 sw=2 et cindent
*/
#include "config.h"
#include <assert.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
@ -29,8 +32,6 @@
#include <sys/types.h>
#include <wchar.h>
#include "config.h"
#include "c_string.h"
#include "c_alloc.h"
#include "c_macro.h"
@ -39,6 +40,78 @@
#include <windows.h>
#endif
#ifdef WITH_ICONV
#include <iconv.h>
typedef struct {
iconv_t to;
iconv_t from;
} iconv_conversions;
static iconv_conversions _iconvs = { NULL, NULL };
int c_setup_iconv(const char* to) {
_iconvs.to = iconv_open(to, "UTF-8");
_iconvs.from = iconv_open("UTF-8", to);
if (_iconvs.to == (iconv_t)-1 || _iconvs.from == (iconv_t)-1)
return -1;
return 0;
}
int c_close_iconv() {
int ret_to = iconv_close(_iconvs.to);
int ret_from = iconv_close(_iconvs.from);
if (ret_to == -1 || ret_from == -1)
return -1;
_iconvs.to = (iconv_t) 0;
_iconvs.from = (iconv_t) 0;
return 0;
}
enum iconv_direction { iconv_from_native, iconv_to_native };
static char *c_iconv(const char* str, enum iconv_direction dir)
{
char *in = (char*)str;
size_t size;
size_t outsize;
char *out;
char *out_in;
size_t ret;
if (str == NULL)
return NULL;
if(_iconvs.from == NULL && _iconvs.to == NULL) {
#ifdef __APPLE__
c_setup_iconv("UTF-8-MAC");
#else
return c_strdup(str);
#endif
}
size = strlen(in);
outsize = size*2;
out = c_malloc(outsize);
out_in = out;
if (dir == iconv_to_native) {
ret = iconv(_iconvs.to, &in, &size, &out, &outsize);
} else {
ret = iconv(_iconvs.from, &in, &size, &out, &outsize);
}
assert(ret != (size_t)-1);
return out_in;
}
#endif
int c_streq(const char *a, const char *b) {
register const char *s1 = a;
register const char *s2 = b;
@ -197,9 +270,9 @@ char *c_lowercase(const char* str) {
}
/* Convert a wide multibyte String to UTF8 */
const char* c_utf8(const mbchar_t *wstr)
char* c_utf8(const mbchar_t *wstr)
{
const char *dst = NULL;
char *dst = NULL;
#ifdef _WIN32
char *mdst = NULL;
@ -214,19 +287,22 @@ const char* c_utf8(const mbchar_t *wstr)
WideCharToMultiByte(CP_UTF8, 0, wstr, len, mdst, size_needed, NULL, NULL);
dst = mdst;
}
#else
#ifdef WITH_ICONV
dst = c_iconv(wstr, iconv_from_native);
#else
dst = wstr;
#endif
#endif
return dst;
}
/* Convert a an UTF8 string to multibyte */
const mbchar_t* c_multibyte(const char *str)
mbchar_t* c_multibyte(const char *str)
{
mbchar_t *dst = NULL;
#ifdef _WIN32
mbchar_t *wstrTo = NULL;
if(!str) return NULL;
size_t len = strlen( str );
int size_needed = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
if(size_needed > 0) {
@ -235,26 +311,12 @@ const mbchar_t* c_multibyte(const char *str)
memset( (void*)wstrTo, 0, size_char);
MultiByteToWideChar(CP_UTF8, 0, str, -1, wstrTo, size_needed);
}
return wstrTo;
#else
return str;
#endif
}
void c_free_utf8(char* buf)
{
#ifdef _WIN32
SAFE_FREE(buf);
#ifdef WITH_ICONV
dst = c_iconv(str, iconv_to_native);
#else
(void)buf;
dst = str;
#endif
}
void c_free_multibyte(const mbchar_t* buf)
{
#ifdef _WIN32
SAFE_FREE(buf);
#else
(void)buf;
#endif
return dst;
}

View File

@ -34,6 +34,9 @@
#define _C_STR_H
#include "c_private.h"
#include "c_macro.h"
#include <stdlib.h>
struct c_strlist_s; typedef struct c_strlist_s c_strlist_t;
@ -162,7 +165,7 @@ char *c_lowercase(const char* str);
* @see c_multibyte()
*
*/
const char* c_utf8(const mbchar_t *str);
char* c_utf8(const mbchar_t *str);
/**
* @brief Convert a utf8 encoded string to multibyte (Win32).
@ -187,8 +190,9 @@ const char* c_utf8(const mbchar_t *str);
* @see c_utf8()
*
*/
const mbchar_t* c_multibyte(const char *wstr);
mbchar_t* c_multibyte(const char *wstr);
#if defined(_WIN32) || defined(WITH_ICONV)
/**
* @brief Free buffer malloced by c_utf8().
*
@ -206,7 +210,8 @@ const mbchar_t* c_multibyte(const char *wstr);
* @see c_utf8()
*
*/
void c_free_utf8(char* buf);
#define c_free_multibyte(x) SAFE_FREE(x)
/**
* @brief Free buffer malloced by c_multibyte().
@ -225,7 +230,11 @@ void c_free_utf8(char* buf);
* @see c_multibyte()
*
*/
void c_free_multibyte(const mbchar_t* buf);
#define c_free_utf8(x) SAFE_FREE(x)
#else
#define c_free_multibyte(x) (void)x
#define c_free_utf8(x) (void)x
#endif
/**
* }@

View File

@ -21,6 +21,8 @@
*/
#include "config.h"
#include "c_private.h"
#include "c_string.h"
#include "c_time.h"
@ -68,7 +70,10 @@ double c_secdiff(struct timespec clock1, struct timespec clock0) {
#ifdef HAVE_UTIMES
int c_utimes(const char *uri, const struct timeval *times) {
return utimes(uri, times);
mbchar_t *wuri = c_multibyte(uri);
int ret = utimes(wuri, times);
c_free_multibyte(wuri);
return ret;
}
#else // HAVE_UTIMES
@ -92,6 +97,7 @@ int c_utimes(const char *uri, const struct timeval *times) {
FILETIME LastAccessTime;
FILETIME LastModificationTime;
HANDLE hFile;
mbchar_t *wuri = c_multibyte( uri );
if(times) {
UnixTimevalToFileTime(times[0], &LastAccessTime);

View File

@ -51,6 +51,12 @@ int csync_vio_init(CSYNC *ctx, const char *module, const char *args) {
csync_vio_method_init_fn init_fn;
const mbchar_t *mpath = NULL;
#ifdef _WIN32
mbchar_t tbuf[MAX_PATH];
mbchar_t *pathBuf = NULL;
char *buf = NULL;
char *last_bslash = NULL;
#endif
if (asprintf(&path, "%s/csync_%s.%s", PLUGINDIR, module, MODULE_EXTENSION) < 0) {
return -1;

View File

@ -47,7 +47,7 @@ typedef struct fhandle_s {
csync_vio_method_handle_t *csync_vio_local_open(const char *durl, int flags, mode_t mode) {
fhandle_t *handle = NULL;
int fd = -1;
const mbchar_t *url = c_multibyte(durl);
mbchar_t *url = c_multibyte(durl);
if ((fd = _topen(url, flags, mode)) < 0) {
c_free_multibyte(url);
@ -71,7 +71,7 @@ csync_vio_method_handle_t *csync_vio_local_open(const char *durl, int flags, mod
csync_vio_method_handle_t *csync_vio_local_creat(const char *durl, mode_t mode) {
fhandle_t *handle = NULL;
int fd = -1;
const mbchar_t *url = c_multibyte(durl);
mbchar_t *url = c_multibyte(durl);
if(( fd = _tcreat( url, mode)) < 0) {
c_free_multibyte(url);
@ -163,7 +163,8 @@ typedef struct dhandle_s {
csync_vio_method_handle_t *csync_vio_local_opendir(const char *name) {
dhandle_t *handle = NULL;
const mbchar_t *dirname = c_multibyte(name);
mbchar_t *dirname = c_multibyte(name);
handle = c_malloc(sizeof(dhandle_t));
if (handle == NULL) {
c_free_multibyte(dirname);
@ -176,8 +177,7 @@ csync_vio_method_handle_t *csync_vio_local_opendir(const char *name) {
SAFE_FREE(handle);
return NULL;
}
handle->path = c_strdup(name);
c_free_multibyte(dirname);
handle->path = c_utf8(dirname);
return (csync_vio_method_handle_t *) handle;
}
@ -223,7 +223,7 @@ csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_method_handle_t *dhandl
goto err;
}
file_stat->name = (char*) c_utf8(dirent->d_name);
file_stat->name = c_utf8(dirent->d_name);
file_stat->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
#ifndef _WIN32
@ -263,7 +263,7 @@ int csync_vio_local_mkdir(const char *uri, mode_t mode) {
}
int csync_vio_local_rmdir(const char *uri) {
const mbchar_t *dirname = c_multibyte(uri);
mbchar_t *dirname = c_multibyte(uri);
int re = -1;
re = _trmdir(dirname);
@ -274,7 +274,8 @@ int csync_vio_local_rmdir(const char *uri) {
int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
csync_stat_t sb;
const mbchar_t *wuri = c_multibyte( uri );
mbchar_t *wuri = c_multibyte( uri );
if( _tstat(wuri, &sb) < 0) {
c_free_multibyte(wuri);
return -1;
@ -372,10 +373,10 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
}
int csync_vio_local_rename(const char *olduri, const char *newuri) {
#ifdef _WIN32
const mbchar_t *nuri = c_multibyte(newuri);
const mbchar_t *ouri = c_multibyte(olduri);
mbchar_t *nuri = c_multibyte(newuri);
mbchar_t *ouri = c_multibyte(olduri);
#ifdef _WIN32
if(ouri && nuri) {
if (MoveFileExW(ouri, nuri, MOVEFILE_COPY_ALLOWED + MOVEFILE_REPLACE_EXISTING + MOVEFILE_WRITE_THROUGH )) {
return 0;
@ -384,24 +385,23 @@ int csync_vio_local_rename(const char *olduri, const char *newuri) {
} else {
errno = ENOENT;
}
#else
return rename(ouri, nuri);
#endif
c_free_multibyte(nuri);
c_free_multibyte(ouri);
return -1;
#else
return rename(olduri, newuri);
#endif
}
int csync_vio_local_unlink(const char *uri) {
const mbchar_t *nuri = c_multibyte(uri);
mbchar_t *nuri = c_multibyte(uri);
int re = _tunlink( nuri );
c_free_multibyte(nuri);
return re;
}
int csync_vio_local_chmod(const char *uri, mode_t mode) {
const mbchar_t *nuri = c_multibyte(uri);
mbchar_t *nuri = c_multibyte(uri);
int re = -1;
re = _tchmod(nuri, mode);

View File

@ -0,0 +1,306 @@
/*
* Copyright 2012 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 <stdio.h>
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <iniparser.h>
#include <std/c_path.h>
#include "../../modules/csync_owncloud.c"
#include <cmocka.h>
#include "config_test.h"
struct oc_credentials {
const char *url;
const char *user;
const char *pwd;
char *oc_server;
} _credentials;
static bool load_oc_config( const char *config ) {
dictionary *dict;
const char* val;
bool re = true;
char *deflt;
char b;
deflt = &b;
dict = iniparser_load( config );
if( ! dict ) {
printf("Could not load config %s\n", config);
return false;
}
val = iniparser_getstring(dict, "global:host", deflt);
if( val ) {
_credentials.url = c_strdup( val );
} else {
re = false;
}
val = iniparser_getstring(dict, "global:user", deflt);
if( re && val ) {
_credentials.user = c_strdup( val );
} else {
re = false;
}
val = iniparser_getstring(dict, "global:pwd", deflt);
if( re && val ) {
_credentials.pwd = c_strdup( val );
} else {
re = false;
}
if( re ) {
asprintf(&(_credentials.oc_server),
"owncloud://%s:%s@%s/files/webdav.php",
_credentials.user, _credentials.pwd,
_credentials.url );
}
return re;
}
// A test case that does nothing and succeeds.
static void null_test_success(void **state) {
(void) state;
}
static void connect_test_success(void **state) {
int re = 0;
char buf[255];
(void) state;
strcpy(buf, TEST_CONFIG_DIR);
strcat(buf, "mockatest.cfg");
assert_true( load_oc_config( buf ));
re = dav_connect( _credentials.oc_server );
assert_int_equal( re, 0 );
assert_int_equal( _connected, 1 );
assert_int_equal( dav_session.time_delta_sum, 0);
assert_int_equal( dav_session.time_delta_cnt, 0);
}
static void fetch_a_context(void **state) {
struct listdir_context *fetchCtx = NULL;
char *curi = _cleanPath(_credentials.oc_server);
int rc = 0;
unsigned int i;
(void) state;
fetchCtx = fetch_resource_list( curi, NE_DEPTH_ONE);
assert_int_equal( rc, 0 );
printf("Results: %d\n", fetchCtx->result_count);
fetchCtx->currResource = fetchCtx->list;
for( i = 0; i < fetchCtx->result_count; i++ ) {
assert_true( fetchCtx->currResource != NULL );
assert_true( fetchCtx->currResource->uri != NULL );
assert_true( fetchCtx->currResource->name != NULL );
printf( " %s -> %s\n", fetchCtx->currResource->uri, fetchCtx->currResource->name );
printf( " MD5: %s\n", fetchCtx->currResource->md5);
fetchCtx->currResource = fetchCtx->currResource->next;
}
}
static int test_mkdir(const char *dir) {
char path[255];
strcpy( path, _credentials.oc_server );
strcat( path, "/");
strcat( path, dir );
return owncloud_mkdir( path, 775 );
}
static void setup_toplevel_dir( void **state ) {
char basepath[255];
strcpy( basepath, "tXXXXXX");
assert_int_equal( c_tmpname(basepath), 0 );
printf("Using top testing dir %s\n", basepath);
assert_int_equal( test_mkdir( basepath ), 0 );
*state = (void*) c_strdup(basepath);
}
static void teardown_toplevel_dir( void **state ) {
(void) state;
}
static void stat_local_file( csync_stat_t *sb, const char *file )
{
_TCHAR *mpath = NULL;
mpath = c_multibyte(file);
assert_int_not_equal(_tstat(mpath, sb), -1);
c_free_multibyte(mpath);
assert_null(mpath);
}
#define BUFSIZE 4096
static size_t upload_a_file( void **state, const char *src_name, const char *durl ) {
char buffer[BUFSIZE+1];
int size;
char path[256];
char src_path[256];
int fh;
csync_vio_method_handle_t *handle;
size_t written;
size_t overall_size = 0;
csync_stat_t sb;
/* Create the target path */
strcpy( path, _credentials.oc_server );
strcat( path, "/");
strcat( path, (const char*) *state );
strcat( path, "/");
strcat( path, durl );
handle = owncloud_creat( path, 0644 );
assert_int_not_equal( handle, NULL );
strcpy(src_path, TESTFILES_DIR);
strcat(src_path, src_name);
fh = open(src_path, O_RDONLY);
assert_int_not_equal( fh, -1 );
while( (size = read(fh, buffer, BUFSIZE) )>0 ) {
buffer[size] = '\0';
written = owncloud_write( handle, buffer, size );
assert_int_equal( size, written );
overall_size += written;
}
assert_int_equal( owncloud_close(handle), 0);
/* stat the local file */
stat_local_file( &sb, src_path );
assert_int_equal( overall_size, sb.st_size );
close(fh);
return overall_size;
}
static void test_upload_files( void **state ) {
const char *bpath = (char*) (*state);
upload_a_file( state, "test.txt", "t1/test.txt");
upload_a_file( state, "red_is_the_rose.jpg", "t1/red is the rose.jpg");
printf("Base path: %s\n", bpath);
}
static void download_a_file( const char* local, void **state, const char *durl)
{
char buffer[BUFSIZE+1];
char path[256];
char src_path[256];
int did;
_TCHAR tlocal[256];
csync_vio_method_handle_t *handle;
ssize_t count;
ssize_t overall_size = 0;
csync_stat_t sb;
/* Create the target path */
strcpy( path, _credentials.oc_server );
strcat( path, "/");
strcat( path, (const char*) *state );
strcat( path, "/");
strcat( path, durl );
strcpy( tlocal, "/tmp/");
strcat( tlocal, local );
did = _topen(tlocal, O_RDWR|O_CREAT, 0644);
assert_true( did > -1 );
handle = owncloud_open( path, O_RDONLY, 0644 );
assert_int_not_equal( handle, NULL );
while( (count = owncloud_read(handle, buffer, BUFSIZE)) > 0 ) {
write( did, buffer, count );
overall_size += count;
}
assert_int_equal( owncloud_close(handle), 0 );
close(did);
strcpy(src_path, TESTFILES_DIR);
strcat(src_path, local);
stat_local_file( &sb, src_path );
/* assert the download size, it has to be the same. */
assert_true( overall_size == sb.st_size );
}
static void test_download_files( void **state ) {
const char *bpath = (char*) (*state);
printf("Base path: %s\n", bpath);
download_a_file( "test.txt", state, "t1/test.txt");
download_a_file( "red_is_the_rose.jpg", state, "t1/red is the rose.jpg");
}
static void test_setup_dirs(void **state) {
const char *basepath = *state;
char path[255];
strcpy( path, basepath );
strcat( path, "/t1" );
assert_int_equal( test_mkdir( path ), 0 );
strcpy( path, basepath );
strcat( path, "/t2");
assert_int_equal( test_mkdir( path ), 0 );
strcat( path, "/Übergröße");
assert_int_equal( test_mkdir( path ), 0 );
}
int main(void) {
const UnitTest tests[] = {
unit_test(null_test_success),
unit_test(connect_test_success),
unit_test_setup_teardown(test_setup_dirs, setup_toplevel_dir, teardown_toplevel_dir),
unit_test(test_upload_files),
unit_test(fetch_a_context),
unit_test(test_download_files),
};
srand(time(NULL));
return run_tests(tests);
}

View File

@ -1,6 +1,7 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "torture.h"
@ -173,6 +174,82 @@ static void check_c_uppercase_null(void **state)
assert_null(str);
}
static void check_iconv_setup(void **state)
{
int rc = 0;
(void) state; /* unused */
#ifdef __APPLE__
rc = c_setup_iconv("UTF-8-MAC");
assert_int_equal(rc, 0);
#endif
}
static void check_iconv_teardown(void **state)
{
int rc = 0;
(void) state; /* unused */
// this must never crash
rc = c_close_iconv();
assert_int_equal(rc, 0);
}
static void check_iconv_to_native_normalization(void **state)
{
const char *out = NULL;
const char *in= "\x48\xc3\xa4"; // UTF8
#ifdef __APPLE__
const char *exp_out = "\x48\x61\xcc\x88"; // UTF-8-MAC
#else
const char *exp_out = "\x48\xc3\xa4"; // UTF8
#endif
out = c_multibyte(in);
assert_string_equal(out, exp_out);
c_free_multibyte(out);
assert_null(out);
(void) state; /* unused */
}
static void check_iconv_from_native_normalization(void **state)
{
const char *out = NULL;
#ifdef __APPLE__
const char* in = "\x48\x61\xcc\x88"; // UTF-8-MAC
#else
const char *in = "\x48\xc3\xa4"; // UTF-8
#endif
const char *exp_out = "\x48\xc3\xa4"; // UTF-8
out = c_utf8(in);
assert_string_equal(out, exp_out);
c_free_utf8(out);
assert_null(out);
(void) state; /* unused */
}
static void check_iconv_ascii(void **state)
{
const char *out = NULL;
const char* in = "abc/ABC\\123";
const char *exp_out = "abc/ABC\\123";
out = c_utf8(in);
assert_string_equal(out, exp_out);
c_free_utf8(out);
assert_null(out);
(void) state; /* unused */
}
int torture_run_tests(void)
{
const UnitTest tests[] = {
@ -189,6 +266,9 @@ int torture_run_tests(void)
unit_test(check_c_uppercase),
unit_test(check_c_uppercase_empty),
unit_test(check_c_uppercase_null),
unit_test_setup_teardown(check_iconv_ascii, check_iconv_setup, check_iconv_teardown),
unit_test_setup_teardown(check_iconv_to_native_normalization, check_iconv_setup, check_iconv_teardown),
unit_test_setup_teardown(check_iconv_from_native_normalization, check_iconv_setup, check_iconv_teardown),
};
return run_tests(tests);