From 87792b59e6440b87c07d1b5d78601d01124aebda Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 26 Nov 2013 11:55:47 +0100 Subject: [PATCH] Fix -gzip removal from etag Removes when the etag is both "foo-gzip" or "foo"-gzip Add to patch for https://github.com/owncloud/mirall/issues/1195 --- src/csync_dbtree.c | 3 +-- src/csync_misc.c | 32 ++++++++++++++++++----- src/csync_misc.h | 2 +- src/csync_owncloud.c | 13 ++-------- src/csync_statedb.c | 6 ++--- tests/CMakeLists.txt | 1 + tests/csync_tests/check_csync_misc.c | 38 ++++++++++++++++++++++++++++ 7 files changed, 71 insertions(+), 24 deletions(-) create mode 100644 tests/csync_tests/check_csync_misc.c diff --git a/src/csync_dbtree.c b/src/csync_dbtree.c index f4e78848d..313fd25a1 100644 --- a/src/csync_dbtree.c +++ b/src/csync_dbtree.c @@ -178,8 +178,7 @@ csync_vio_method_handle_t *csync_dbtree_opendir(CSYNC *ctx, const char *name) fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; column = list->vector[base+8]; /* type */ - fs->etag = c_strdup(column); - csync_normalize_etag(fs->etag); + fs->etag = csync_normalize_etag(column); fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG; /* store into result list. */ diff --git a/src/csync_misc.c b/src/csync_misc.c index 1aea40a49..2654060ae 100644 --- a/src/csync_misc.c +++ b/src/csync_misc.c @@ -261,19 +261,37 @@ CSYNC_STATUS csync_errno_to_status(int error, CSYNC_STATUS default_status) return status; } -/* Remove "-gzip" at the end (cf. https://github.com/owncloud/mirall/issues/1195) +/* Remove possible quotes, and also the -gzip at the end + * Remove "-gzip" at the end (cf. https://github.com/owncloud/mirall/issues/1195) + * The caller must take ownership of the resulting string. * (work in place) */ -char *csync_normalize_etag(char *etag) +char *csync_normalize_etag(const char *etag) { int len = 0; - if (!etag) return etag; + char *buf = NULL; + if (!etag) + return NULL; len = strlen(etag); - if (len > 5 && c_streq(etag + len - 5, "-gzip")) { - CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Removing -gzip from etag: %s", etag); - etag[len-5] = '\0'; + /* strip "XXXX-gzip" */ + if(len >= 7 && etag[0] == '"' && c_streq(etag + len - 6, "-gzip\"")) { + etag++; + len -= 7; } - return etag; + /* strip leading -gzip */ + if(len >= 5 && c_streq(etag + len - 5, "-gzip")) { + len -= 5; + } + /* strip normal quotes */ + if (etag[0] == '"' && etag[len-1] == '"') { + etag++; + len -= 2; + } + + buf = c_malloc( len+1 ); + strncpy( buf, etag, len ); + buf[len] = '\0'; + return buf; } diff --git a/src/csync_misc.h b/src/csync_misc.h index 02394bef1..84d3f6a20 100644 --- a/src/csync_misc.h +++ b/src/csync_misc.h @@ -64,6 +64,6 @@ typedef struct { } csync_overall_progress_t; -char *csync_normalize_etag(char *); +char *csync_normalize_etag(const char *); #endif /* _CSYNC_MISC_H */ diff --git a/src/csync_owncloud.c b/src/csync_owncloud.c index de5c93ff3..5420dc535 100644 --- a/src/csync_owncloud.c +++ b/src/csync_owncloud.c @@ -954,16 +954,7 @@ static const char* owncloud_get_etag( const char *path ) /* In case the result is surrounded by "" cut them away. */ if( header ) { - if( header [0] == '"' && header[ strlen(header)-1] == '"') { - int len = strlen( header )-2; - buf = c_malloc( len+1 ); - strncpy( buf, header+1, len ); - buf[len] = '\0'; - cbuf = buf; - /* do not free header here, as it belongs to the request */ - } else { - cbuf = c_strdup(header); - } + cbuf = csync_normalize_etag(header); } /* fix server problem: If we end up with an empty string, set something strange... */ @@ -977,7 +968,7 @@ static const char* owncloud_get_etag( const char *path ) if( req ) ne_request_destroy(req); SAFE_FREE(uri); - csync_normalize_etag(cbuf); + return cbuf; } diff --git a/src/csync_statedb.c b/src/csync_statedb.c index 995003d8e..527a17724 100644 --- a/src/csync_statedb.c +++ b/src/csync_statedb.c @@ -392,7 +392,7 @@ csync_file_stat_t *csync_statedb_get_stat_by_hash(sqlite3 *db, } if(column_count > 9 && sqlite3_column_text(_by_hash_stmt, 9)) { - st->etag = csync_normalize_etag(c_strdup( (char*) sqlite3_column_text(_by_hash_stmt, 9) )); + st->etag = csync_normalize_etag( (char*) sqlite3_column_text(_by_hash_stmt, 9) ); } } } else { @@ -461,7 +461,7 @@ csync_file_stat_t *csync_statedb_get_stat_by_file_id( sqlite3 *db, st->modtime = strtoul(result->vector[7], NULL, 10); st->type = atoi(result->vector[8]); if( result->vector[9] ) - st->etag = csync_normalize_etag(c_strdup(result->vector[9])); + st->etag = csync_normalize_etag(result->vector[9]); csync_vio_set_file_id(st->file_id, file_id); @@ -516,7 +516,7 @@ csync_file_stat_t *csync_statedb_get_stat_by_inode(sqlite3 *db, st->modtime = strtoul(result->vector[7], NULL, 10); st->type = atoi(result->vector[8]); if( result->vector[9] ) - st->etag = csync_normalize_etag(c_strdup(result->vector[9])); + st->etag = csync_normalize_etag(result->vector[9]); csync_vio_set_file_id( st->file_id, result->vector[10]); c_strlist_destroy(result); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index eb879f573..02a6121ea 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -45,6 +45,7 @@ add_cmocka_test(check_csync_exclude csync_tests/check_csync_exclude.c ${TEST_TAR add_cmocka_test(check_csync_statedb_load csync_tests/check_csync_statedb_load.c ${TEST_TARGET_LIBRARIES}) add_cmocka_test(check_csync_time csync_tests/check_csync_time.c ${TEST_TARGET_LIBRARIES}) add_cmocka_test(check_csync_util csync_tests/check_csync_util.c ${TEST_TARGET_LIBRARIES}) +add_cmocka_test(check_csync_misc csync_tests/check_csync_misc.c ${TEST_TARGET_LIBRARIES}) # csync tests which require init add_cmocka_test(check_csync_init csync_tests/check_csync_init.c ${TEST_TARGET_LIBRARIES}) diff --git a/tests/csync_tests/check_csync_misc.c b/tests/csync_tests/check_csync_misc.c new file mode 100644 index 000000000..e6bd5001c --- /dev/null +++ b/tests/csync_tests/check_csync_misc.c @@ -0,0 +1,38 @@ +#include "torture.h" + +#include "csync_misc.h" +#include + +static void check_csync_normalize_etag(void **state) +{ + char *str; + + (void) state; /* unused */ + +#define CHECK_NORMALIZE_ETAG(TEST, EXPECT) \ + str = csync_normalize_etag(TEST); \ + assert_string_equal(str, EXPECT); \ + free(str); + + + CHECK_NORMALIZE_ETAG("foo", "foo"); + CHECK_NORMALIZE_ETAG("\"foo\"", "foo"); + CHECK_NORMALIZE_ETAG("\"nar123\"", "nar123"); + CHECK_NORMALIZE_ETAG("", ""); + CHECK_NORMALIZE_ETAG("\"\"", ""); + + /* Test with -gzip (all combinaison) */ + CHECK_NORMALIZE_ETAG("foo-gzip", "foo"); + CHECK_NORMALIZE_ETAG("\"foo\"-gzip", "foo"); + CHECK_NORMALIZE_ETAG("\"foo-gzip\"", "foo"); +} + +int torture_run_tests(void) +{ + const UnitTest tests[] = { + unit_test(check_csync_normalize_etag), + }; + + return run_tests(tests); +} +