Comparar commits
62 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| f380852986 | |||
| d13ac31e08 | |||
| 3f543b881d | |||
| 4a1d0eb80e | |||
| 760ecd71fc | |||
| 04f1026cd8 | |||
| b03c4cc62e | |||
| e497b6d458 | |||
| 2e4320ee05 | |||
| 14a5ff6747 | |||
| abf0f90a13 | |||
| 4d5c74c019 | |||
| ef3b4956ad | |||
| fd4642d827 | |||
| 6dd248e527 | |||
| 7d00c3646a | |||
| e355e12385 | |||
| 34b31c0146 | |||
| 3934fa019e | |||
| dc53e96f92 | |||
| 7fcf6f9f79 | |||
| b814b45e50 | |||
| ded8914df2 | |||
| bd48ab23c3 | |||
| 4e28ba73bb | |||
| 16cb37ecd0 | |||
| 7a7b0e8939 | |||
| d4d630b2e9 | |||
| a4f6370774 | |||
| 2ff27cdd63 | |||
| 2f81167164 | |||
| 6897c5d41f | |||
| 233450d850 | |||
| 7428a8fa63 | |||
| 18359d7871 | |||
| df12a58e3d | |||
| 4b3d124b5a | |||
| 51e941e7b5 | |||
| 62ea6f316f | |||
| 6605a89990 | |||
| 4cb9b3a85b | |||
| 806ab8ea46 | |||
| 582a8fe7fd | |||
| 08ca8b54b1 | |||
| abafbef985 | |||
| 6e10b8c5c4 | |||
| 06863ca9c6 | |||
| e49b8981dd | |||
| 24616bead4 | |||
| 2e91557c28 | |||
| 4d4eab8b1c | |||
| 13f9970257 | |||
| 4d4ae9374b | |||
| b8e20b412c | |||
| e36f3c5b10 | |||
| 8a55f831f4 | |||
| 0dcc9be5c1 | |||
| 5ee00a8df7 | |||
| 1af3d3f18b | |||
| f54248c0a7 | |||
| 2911c0e1c4 | |||
| 16d35c1489 |
@@ -108,7 +108,10 @@ if(NOT TOKEN_AUTH_ONLY)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
Find_package(Sparkle)
|
||||
if(APPLE)
|
||||
find_package(Sparkle)
|
||||
endif(APPLE)
|
||||
|
||||
if(UNIX)
|
||||
find_package(INotify REQUIRED)
|
||||
else()
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
set( MIRALL_VERSION_MAJOR 1 )
|
||||
set( MIRALL_VERSION_MINOR 6 )
|
||||
set( MIRALL_VERSION_MINOR 7 )
|
||||
set( MIRALL_VERSION_PATCH 0 )
|
||||
set( MIRALL_SOVERSION 0 )
|
||||
|
||||
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||
set( MIRALL_VERSION_SUFFIX "") #e.g. beta1, beta2, rc1
|
||||
set( MIRALL_VERSION_SUFFIX "prealpha") #e.g. beta1, beta2, rc1
|
||||
endif( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||
|
||||
if( NOT DEFINED MIRALL_VERSION_BUILD )
|
||||
|
||||
@@ -1,28 +1,37 @@
|
||||
# Auto-generated - do not modify
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Näytä julkaisutiedot"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Havaittiin sovelluksen ${APPLICATION_EXECUTABLE} prosessi (tai prosesseja) jotka pitäisi pysäyttää.\nHaluatko että asennusohjelma pysäyttää nämä puolestasi?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Pysäytetään sovelluksen ${APPLICATION_EXECUTABLE} prosessit."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Tapettavaa prosessia ei löytynyt!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Vanhempi versio sovelluksesta ${APPLICATION_NAME} on jo asennettu. On suositeltavaa että poistat vanhan asennuksen ensin. Valitse mikä toiminto suoritetaan ja napsauta Seuraava jatkaaksesi."
|
||||
StrCpy $PageReinstall_NEW_Field_2 "Poista ennen asentamista"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "Älä poista"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Asennettu jo"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Valitse miten ${APPLICATION_NAME} asennetaan."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Uudempi versio sovelluksesta ${APPLICATION_NAME} on jo asennettu! Vanhan version asennus ei ole suositeltavaa. Jos todella haluat asentaa vanhemman version, kannattaa poistaa nykyisen version asennus ensin. Valitse minkä toimenpiteen haluat suorittaa ja paina Seuraava jatkaaksesi."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} on jo asennettu.\nValitse suoritettava toimenpide ja napsauta Seuraava jatkaaksesi."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Lisää/uudelleenasenna komponentteja"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Poista ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Poista ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Valitse suoritettava huoltotoimenpide."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Asennetaan sovelluksen ${APPLICATION_NAME} välttämättömyyksiä."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Käynnistä-valikon pikakuvake"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Lisätään ${APPLICATION_NAME}-pikakuvake Käynnistä-valikkoon."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Työpöydän pikakuvake"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Luodaan työpöydän pikakuvakkeet"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Pikakäynnistyksen pikakuvake"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Luodaan pikakuvaketta pikakäynnistykseen"
|
||||
StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} välttämättömyydet."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME}-pikakuvake."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Sovelluksen ${APPLICATION_NAME} työpyötäpikakuvake."
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Pikakäynnistyksen pikakuvake sovellukselle ${APPLICATION_NAME}."
|
||||
StrCpy $UNINSTALLER_APPDATA_SUBTITLE "Poista ${APPLICATION_NAME}-datakansio tietokoneelta."
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_1 "Haluatko varmasti poistaa ${APPLICATION_NAME}-datakansion?"
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Jätä valinta ruksimatta säilyttääksesti datakansion myöhempää käyttöä varten tai täytä ruksi jos haluat poistaa datakansion ja siinä olevat tiedostot."
|
||||
StrCpy $UNINSTALLER_APPDATA_CHECKBOX "Kyllä, poista tämä datakansio."
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Kirjoitetaan asennusohjelman rekisteriavaimia"
|
||||
StrCpy $UNINSTALLER_FINISHED_Detail "Valmis"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Vaikuttaa siltä että sovellus ${APPLICATION_NAME} on asennettu kansioon '$INSTDIR'.\n\nHaluatko jatkaa tästä huolimatta (ei suositeltavaa)?"
|
||||
StrCpy $UNINSTALL_ABORT "Poistaminen keskeytettiin käyttäjän toimesta"
|
||||
StrCpy $INIT_NO_DESKTOP "Työpöydän pikakuvake (korvaa nykyinen)"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Tämä asennusohjelma vaatii ylläpitäjän oikeudet, yritä uudelleen."
|
||||
@@ -30,15 +39,6 @@ StrCpy $INIT_INSTALLER_RUNNING "Asennusohjelma on jo k
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Tämä poisto-ohjelma vaatii ylläpitäjän oikeudet, yritä uudelleen."
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Poisto-ohjelma on jo käynnissä."
|
||||
StrCpy $SectionGroup_Shortcuts "Pikakuvakkeet"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Found ${APPLICATION_EXECUTABLE} process(s) which need to be stopped.$\nDo you want the installer to stop these for you?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Killing ${APPLICATION_EXECUTABLE} processes."
|
||||
StrCpy $PageReinstall_NEW_Field_1 "An older version of ${APPLICATION_NAME} is installed on your system. It is recommended that you uninstall the current version before installing. Select the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "A newer version of ${APPLICATION_NAME} is already installed! It is not recommended that you install an older version. If you really want to install this older version, it is better to uninstall the current version first. Select the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Add/Reinstall components"
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Installing ${APPLICATION_NAME} essentials."
|
||||
StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} essentials."
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Leave unchecked to keep the data folder for later use or check to delete the data folder."
|
||||
StrCpy $UNINSTALLER_FILE_Detail "Writing Uninstaller"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "It does not appear that ${APPLICATION_NAME} is installed in the directory '$INSTDIR'.$\r$\nContinue anyway (not recommended)?"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Quick Launch Shortcut (N/A)"
|
||||
StrCpy $UAC_ERROR_ELEVATE "Unable to elevate, error:"
|
||||
|
||||
@@ -7,7 +7,7 @@ StrCpy $PageReinstall_NEW_Field_2 "在安装前先卸载"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "不要卸载"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "已经安装"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "选择如何安装${APPLICATION_NAME}。"
|
||||
StrCpy $PageReinstall_SAME_Field_2 "添加/重装组件"
|
||||
StrCpy $PageReinstall_SAME_Field_2 "增加/重装组件"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "卸载${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "卸载${APPLICATION_NAME}"
|
||||
StrCpy $SEC_APPLICATION_DETAILS "安装${APPLICATION_NAME}基本组件。"
|
||||
|
||||
@@ -151,6 +151,12 @@ UninstPage custom un.UnPageUserAppData un.UnPageUserAppDataLeave
|
||||
!include ${source_path}/admin/win/nsi/l10n/languages.nsh
|
||||
!include ${source_path}/admin/win/nsi/l10n/declarations.nsh
|
||||
|
||||
; Set version strings with english locale
|
||||
VIProductVersion "${VERSION}"
|
||||
VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "${APPLICATION_NAME}"
|
||||
VIAddVersionKey /LANG=${LANG_ENGLISH} "CompanyName" "${APPLICATION_VENDOR}"
|
||||
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "${VERSION}"
|
||||
|
||||
!macro SETLANG un
|
||||
Function ${un}SetLang
|
||||
# load the selected language file
|
||||
|
||||
@@ -27,10 +27,6 @@ include(MacroCopyFile)
|
||||
if (NOT WIN32)
|
||||
find_package(Iconv)
|
||||
endif (NOT WIN32)
|
||||
find_package(CMocka)
|
||||
if (CMOCKA_FOUND AND UNIT_TESTING)
|
||||
include(AddCMockaTest)
|
||||
endif (CMOCKA_FOUND AND UNIT_TESTING)
|
||||
|
||||
include(ConfigureChecks.cmake)
|
||||
|
||||
@@ -47,9 +43,13 @@ endif (MEM_NULL_TESTS)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
if (CMOCKA_FOUND AND UNIT_TESTING)
|
||||
add_subdirectory(tests)
|
||||
endif (CMOCKA_FOUND AND UNIT_TESTING)
|
||||
if (UNIT_TESTING)
|
||||
find_package(CMocka)
|
||||
if (CMOCKA_FOUND)
|
||||
include(AddCMockaTest)
|
||||
add_subdirectory(tests)
|
||||
endif (CMOCKA_FOUND)
|
||||
endif (UNIT_TESTING)
|
||||
|
||||
configure_file(config_csync.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config_csync.h)
|
||||
configure_file(config_test.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config_test.h)
|
||||
|
||||
@@ -96,8 +96,6 @@ static int _data_cmp(const void *key, const void *data) {
|
||||
int csync_create(CSYNC **csync, const char *local, const char *remote) {
|
||||
CSYNC *ctx;
|
||||
size_t len = 0;
|
||||
char *home;
|
||||
int rc;
|
||||
|
||||
ctx = c_malloc(sizeof(CSYNC));
|
||||
if (ctx == NULL) {
|
||||
@@ -129,32 +127,10 @@ int csync_create(CSYNC **csync, const char *local, const char *remote) {
|
||||
}
|
||||
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
ctx->options.local_only_mode = false;
|
||||
|
||||
ctx->pwd.uid = getuid();
|
||||
ctx->pwd.euid = geteuid();
|
||||
|
||||
home = csync_get_user_home_dir();
|
||||
if (home == NULL) {
|
||||
SAFE_FREE(ctx->local.uri);
|
||||
SAFE_FREE(ctx->remote.uri);
|
||||
SAFE_FREE(ctx);
|
||||
errno = ENOMEM;
|
||||
ctx->status_code = CSYNC_STATUS_MEMORY_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = asprintf(&ctx->options.config_dir, "%s/%s", home, CSYNC_CONF_DIR);
|
||||
SAFE_FREE(home);
|
||||
if (rc < 0) {
|
||||
SAFE_FREE(ctx->local.uri);
|
||||
SAFE_FREE(ctx->remote.uri);
|
||||
SAFE_FREE(ctx);
|
||||
errno = ENOMEM;
|
||||
ctx->status_code = CSYNC_STATUS_MEMORY_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->local.list = 0;
|
||||
ctx->remote.list = 0;
|
||||
ctx->current_fs = NULL;
|
||||
@@ -167,7 +143,6 @@ int csync_create(CSYNC **csync, const char *local, const char *remote) {
|
||||
|
||||
int csync_init(CSYNC *ctx) {
|
||||
int rc;
|
||||
char *config = NULL;
|
||||
|
||||
if (ctx == NULL) {
|
||||
errno = EBADF;
|
||||
@@ -190,12 +165,8 @@ int csync_init(CSYNC *ctx) {
|
||||
|
||||
ctx->local.type = LOCAL_REPLICA;
|
||||
|
||||
if ( !ctx->options.local_only_mode) {
|
||||
owncloud_init(csync_get_userdata(ctx));
|
||||
ctx->remote.type = REMOTE_REPLICA;
|
||||
} else {
|
||||
ctx->remote.type = LOCAL_REPLICA;
|
||||
}
|
||||
owncloud_init(ctx);
|
||||
ctx->remote.type = REMOTE_REPLICA;
|
||||
|
||||
if (c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp) < 0) {
|
||||
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
|
||||
@@ -211,15 +182,12 @@ int csync_init(CSYNC *ctx) {
|
||||
|
||||
ctx->status = CSYNC_STATUS_INIT;
|
||||
|
||||
csync_set_module_property(ctx, "csync_context", ctx);
|
||||
|
||||
/* initialize random generator */
|
||||
srand(time(NULL));
|
||||
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
SAFE_FREE(config);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -234,7 +202,6 @@ int csync_update(CSYNC *ctx) {
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
/* create/load statedb */
|
||||
if (! csync_is_statedb_disabled(ctx)) {
|
||||
rc = asprintf(&ctx->statedb.file, "%s/.csync_journal.db",
|
||||
ctx->local.uri);
|
||||
if (rc < 0) {
|
||||
@@ -248,7 +215,6 @@ int csync_update(CSYNC *ctx) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
@@ -283,27 +249,25 @@ int csync_update(CSYNC *ctx) {
|
||||
}
|
||||
|
||||
/* update detection for remote replica */
|
||||
if( ! ctx->options.local_only_mode ) {
|
||||
csync_gettime(&start);
|
||||
ctx->current = REMOTE_REPLICA;
|
||||
ctx->replica = ctx->remote.type;
|
||||
csync_gettime(&start);
|
||||
ctx->current = REMOTE_REPLICA;
|
||||
ctx->replica = ctx->remote.type;
|
||||
|
||||
rc = csync_ftw(ctx, ctx->remote.uri, csync_walker, MAX_DEPTH);
|
||||
if (rc < 0) {
|
||||
if(ctx->status_code == CSYNC_STATUS_OK)
|
||||
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_UPDATE_ERROR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
csync_gettime(&finish);
|
||||
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
|
||||
"Update detection for remote replica took %.2f seconds "
|
||||
"walking %zu files.",
|
||||
c_secdiff(finish, start), c_rbtree_size(ctx->remote.tree));
|
||||
csync_memstat_check();
|
||||
rc = csync_ftw(ctx, ctx->remote.uri, csync_walker, MAX_DEPTH);
|
||||
if (rc < 0) {
|
||||
if(ctx->status_code == CSYNC_STATUS_OK)
|
||||
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_UPDATE_ERROR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
csync_gettime(&finish);
|
||||
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
|
||||
"Update detection for remote replica took %.2f seconds "
|
||||
"walking %zu files.",
|
||||
c_secdiff(finish, start), c_rbtree_size(ctx->remote.tree));
|
||||
csync_memstat_check();
|
||||
|
||||
ctx->status |= CSYNC_STATUS_UPDATE;
|
||||
|
||||
return 0;
|
||||
@@ -444,6 +408,8 @@ static int _csync_treewalk_visitor(void *obj, void *data) {
|
||||
trav.rename_path = cur->destpath;
|
||||
trav.etag = cur->etag;
|
||||
trav.file_id = cur->file_id;
|
||||
trav.directDownloadUrl = cur->directDownloadUrl;
|
||||
trav.directDownloadCookies = cur->directDownloadCookies;
|
||||
trav.inode = cur->inode;
|
||||
|
||||
trav.error_status = cur->error_status;
|
||||
@@ -466,7 +432,7 @@ static int _csync_treewalk_visitor(void *obj, void *data) {
|
||||
|
||||
rc = (*visitor)(&trav, twctx->userdata);
|
||||
cur->instruction = trav.instruction;
|
||||
if (trav.etag != cur->etag) {
|
||||
if (trav.etag != cur->etag) { // FIXME It would be nice to have this documented
|
||||
SAFE_FREE(cur->etag);
|
||||
cur->etag = c_strdup(trav.etag);
|
||||
}
|
||||
@@ -617,7 +583,7 @@ int csync_commit(CSYNC *ctx) {
|
||||
}
|
||||
ctx->statedb.db = NULL;
|
||||
|
||||
rc = csync_vio_commit(ctx);
|
||||
rc = owncloud_commit(ctx);
|
||||
if (rc < 0) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "commit failed: %s",
|
||||
ctx->error_string ? ctx->error_string : "");
|
||||
@@ -676,9 +642,10 @@ int csync_destroy(CSYNC *ctx) {
|
||||
|
||||
SAFE_FREE(ctx->local.uri);
|
||||
SAFE_FREE(ctx->remote.uri);
|
||||
SAFE_FREE(ctx->options.config_dir);
|
||||
SAFE_FREE(ctx->error_string);
|
||||
|
||||
owncloud_destroy(ctx);
|
||||
|
||||
#ifdef WITH_ICONV
|
||||
c_close_iconv();
|
||||
#endif
|
||||
@@ -710,70 +677,6 @@ void csync_clear_exclude_list(CSYNC *ctx)
|
||||
csync_exclude_clear(ctx);
|
||||
}
|
||||
|
||||
const char *csync_get_config_dir(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctx->options.config_dir;
|
||||
}
|
||||
|
||||
int csync_set_config_dir(CSYNC *ctx, const char *path) {
|
||||
if (ctx == NULL || path == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SAFE_FREE(ctx->options.config_dir);
|
||||
ctx->options.config_dir = c_strdup(path);
|
||||
if (ctx->options.config_dir == NULL) {
|
||||
ctx->status_code = CSYNC_STATUS_MEMORY_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int csync_enable_statedb(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
if (ctx->status & CSYNC_STATUS_INIT) {
|
||||
fprintf(stderr, "This function must be called before initialization.");
|
||||
ctx->status_code = CSYNC_STATUS_CSYNC_STATUS_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->statedb.disabled = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int csync_disable_statedb(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
if (ctx->status & CSYNC_STATUS_INIT) {
|
||||
fprintf(stderr, "This function must be called before initialization.");
|
||||
ctx->status_code = CSYNC_STATUS_CSYNC_STATUS_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->statedb.disabled = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int csync_is_statedb_disabled(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return ctx->statedb.disabled;
|
||||
}
|
||||
|
||||
int csync_set_auth_callback(CSYNC *ctx, csync_auth_callback cb) {
|
||||
if (ctx == NULL || cb == NULL) {
|
||||
return -1;
|
||||
@@ -789,15 +692,6 @@ int csync_set_auth_callback(CSYNC *ctx, csync_auth_callback cb) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *csync_get_statedb_file(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
return c_strdup(ctx->statedb.file);
|
||||
}
|
||||
|
||||
void *csync_get_userdata(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return NULL;
|
||||
@@ -841,33 +735,6 @@ CSYNC_STATUS csync_get_status(CSYNC *ctx) {
|
||||
return ctx->status_code;
|
||||
}
|
||||
|
||||
int csync_set_local_only(CSYNC *ctx, bool local_only) {
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
if (ctx->status & CSYNC_STATUS_INIT) {
|
||||
fprintf(stderr, "csync_set_local_only: This function must be called before initialization.");
|
||||
ctx->status_code = CSYNC_STATUS_CSYNC_STATUS_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->options.local_only_mode=local_only;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool csync_get_local_only(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
return ctx->options.local_only_mode;
|
||||
}
|
||||
|
||||
const char *csync_get_status_string(CSYNC *ctx)
|
||||
{
|
||||
return csync_vio_get_status_string(ctx);
|
||||
@@ -912,6 +779,8 @@ int csync_abort_requested(CSYNC *ctx)
|
||||
void csync_file_stat_free(csync_file_stat_t *st)
|
||||
{
|
||||
if (st) {
|
||||
SAFE_FREE(st->directDownloadUrl);
|
||||
SAFE_FREE(st->directDownloadCookies);
|
||||
SAFE_FREE(st->etag);
|
||||
SAFE_FREE(st->destpath);
|
||||
SAFE_FREE(st);
|
||||
@@ -920,7 +789,7 @@ void csync_file_stat_free(csync_file_stat_t *st)
|
||||
|
||||
int csync_set_module_property(CSYNC* ctx, const char* key, void* value)
|
||||
{
|
||||
return csync_vio_set_property(ctx, key, value);
|
||||
return owncloud_set_property(ctx, key, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -44,13 +44,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* csync file declarations
|
||||
*/
|
||||
#define CSYNC_CONF_DIR ".ocsync"
|
||||
#define CSYNC_CONF_FILE "ocsync.conf"
|
||||
#define CSYNC_EXCLUDE_FILE "ocsync_exclude.conf"
|
||||
|
||||
/**
|
||||
* Instruction enum. In the file traversal structure, it describes
|
||||
* the csync state of a file.
|
||||
@@ -59,7 +52,7 @@ enum csync_status_codes_e {
|
||||
CSYNC_STATUS_OK = 0,
|
||||
|
||||
CSYNC_STATUS_ERROR = 1024, /* don't use this code,
|
||||
just use in csync_status_ok */
|
||||
*/
|
||||
CSYNC_STATUS_UNSUCCESSFUL,
|
||||
CSYNC_STATUS_NO_LOCK, /* OBSOLETE does not happen anymore */
|
||||
CSYNC_STATUS_STATEDB_LOAD_ERROR,
|
||||
@@ -189,6 +182,8 @@ struct csync_tree_walk_file_s {
|
||||
const char *rename_path;
|
||||
const char *etag;
|
||||
const char *file_id;
|
||||
char *directDownloadUrl;
|
||||
char *directDownloadCookies;
|
||||
struct {
|
||||
int64_t size;
|
||||
time_t modtime;
|
||||
@@ -214,14 +209,6 @@ typedef void (*csync_log_callback) (int verbosity,
|
||||
const char *buffer,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Check internal csync status.
|
||||
*
|
||||
* @param csync The context to check.
|
||||
*
|
||||
* @return true if status is error free, false for error states.
|
||||
*/
|
||||
bool csync_status_ok(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Allocate a csync context.
|
||||
@@ -333,62 +320,6 @@ int csync_add_exclude_list(CSYNC *ctx, const char *path);
|
||||
*/
|
||||
void csync_clear_exclude_list(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Get the config directory.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*
|
||||
* @return The path of the config directory or NULL on error.
|
||||
*/
|
||||
const char *csync_get_config_dir(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Change the config directory.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*
|
||||
* @param path The path to the new config directory.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
*/
|
||||
int csync_set_config_dir(CSYNC *ctx, const char *path);
|
||||
|
||||
/**
|
||||
* @brief Remove the complete config directory.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
*/
|
||||
int csync_remove_config_dir(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Enable the usage of the statedb. It is enabled by default.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
*/
|
||||
int csync_enable_statedb(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Disable the usage of the statedb. It is enabled by default.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
*/
|
||||
int csync_disable_statedb(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Check if the statedb usage is enabled.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*
|
||||
* @return 1 if it is enabled, 0 if it is disabled.
|
||||
*/
|
||||
int csync_is_statedb_disabled(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Get the userdata saved in the context.
|
||||
*
|
||||
@@ -481,31 +412,6 @@ void *csync_get_log_userdata(void);
|
||||
*/
|
||||
int csync_set_log_userdata(void *data);
|
||||
|
||||
/**
|
||||
* @brief Get the path of the statedb file used.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*
|
||||
* @return The path to the statedb file, NULL if an error occured.
|
||||
*/
|
||||
const char *csync_get_statedb_file(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Flag to tell csync that only a local run is intended. Call before csync_init
|
||||
*
|
||||
* @param local_only Bool flag to indicate local only mode.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
*/
|
||||
int csync_set_local_only( CSYNC *ctx, bool local_only );
|
||||
|
||||
/**
|
||||
* @brief Retrieve the flag to tell csync that only a local run is intended.
|
||||
*
|
||||
* @return 1: stay local only, 0: local and remote mode
|
||||
*/
|
||||
bool csync_get_local_only( CSYNC *ctx );
|
||||
|
||||
/* Used for special modes or debugging */
|
||||
CSYNC_STATUS csync_get_status(CSYNC *ctx);
|
||||
|
||||
|
||||
@@ -20,12 +20,18 @@
|
||||
|
||||
#include "config_csync.h"
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "c_private.h"
|
||||
|
||||
#include "csync_private.h"
|
||||
#include "csync_exclude.h"
|
||||
@@ -217,7 +223,7 @@ CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype) {
|
||||
SAFE_FREE(bname);
|
||||
SAFE_FREE(dname);
|
||||
|
||||
if (ctx->excludes == NULL) {
|
||||
if (ctx == NULL || ctx->excludes == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,52 +47,6 @@
|
||||
#include "csync_macros.h"
|
||||
#include "csync_log.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
char *csync_get_user_home_dir(void) {
|
||||
wchar_t tmp[MAX_PATH];
|
||||
char *szPath = NULL;
|
||||
|
||||
if( SHGetFolderPathW( NULL,
|
||||
CSIDL_PROFILE|CSIDL_FLAG_CREATE,
|
||||
NULL,
|
||||
0,
|
||||
tmp) == S_OK ) {
|
||||
szPath = c_utf8_from_locale(tmp);
|
||||
return szPath;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else /* ************* !WIN32 ************ */
|
||||
|
||||
#ifndef NSS_BUFLEN_PASSWD
|
||||
#define NSS_BUFLEN_PASSWD 4096
|
||||
#endif /* NSS_BUFLEN_PASSWD */
|
||||
|
||||
char *csync_get_user_home_dir(void) {
|
||||
const char *envp;
|
||||
struct passwd pwd;
|
||||
struct passwd *pwdbuf;
|
||||
char buf[NSS_BUFLEN_PASSWD];
|
||||
int rc;
|
||||
|
||||
envp = getenv("HOME");
|
||||
if (envp != NULL && envp[0] != '\0') {
|
||||
return c_strdup(envp);
|
||||
}
|
||||
|
||||
/* Still nothing found, read the password file */
|
||||
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
|
||||
if (rc != 0) {
|
||||
return c_strdup(pwd.pw_dir);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* ************* WIN32 ************ */
|
||||
|
||||
#ifdef HAVE_FNMATCH
|
||||
#include <fnmatch.h>
|
||||
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
|
||||
#endif
|
||||
|
||||
char *csync_get_user_home_dir(void);
|
||||
|
||||
int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags);
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,79 +20,10 @@
|
||||
*/
|
||||
|
||||
#include "csync_owncloud.h"
|
||||
#include "csync_owncloud_private.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
/*
|
||||
* free the fetchCtx
|
||||
*/
|
||||
static void free_fetchCtx( struct listdir_context *ctx )
|
||||
{
|
||||
struct resource *newres, *res;
|
||||
if( ! ctx ) return;
|
||||
newres = ctx->list;
|
||||
res = newres;
|
||||
|
||||
ctx->ref--;
|
||||
if (ctx->ref > 0) return;
|
||||
|
||||
SAFE_FREE(ctx->target);
|
||||
|
||||
while( res ) {
|
||||
SAFE_FREE(res->uri);
|
||||
SAFE_FREE(res->name);
|
||||
SAFE_FREE(res->md5);
|
||||
memset( res->file_id, 0, FILE_ID_BUF_SIZE+1 );
|
||||
|
||||
newres = res->next;
|
||||
SAFE_FREE(res);
|
||||
res = newres;
|
||||
}
|
||||
SAFE_FREE(ctx);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* local variables.
|
||||
*/
|
||||
|
||||
struct dav_session_s dav_session; /* The DAV Session, initialised in dav_connect */
|
||||
int _connected = 0; /* flag to indicate if a connection exists, ie.
|
||||
the dav_session is valid */
|
||||
|
||||
|
||||
void *_userdata;
|
||||
long long chunked_total_size = 0;
|
||||
long long chunked_done = 0;
|
||||
|
||||
struct listdir_context *propfind_cache = 0;
|
||||
|
||||
bool is_first_propfind = true;
|
||||
|
||||
|
||||
csync_vio_file_stat_t _stat_cache;
|
||||
/* id cache, cache the ETag: header of a GET request */
|
||||
struct { char *uri; char *id; } _id_cache = { NULL, NULL };
|
||||
|
||||
static void clean_caches() {
|
||||
clear_propfind_recursive_cache();
|
||||
|
||||
free_fetchCtx(propfind_cache);
|
||||
propfind_cache = NULL;
|
||||
|
||||
SAFE_FREE(_stat_cache.name);
|
||||
SAFE_FREE(_stat_cache.etag );
|
||||
memset( _stat_cache.file_id, 0, FILE_ID_BUF_SIZE+1 );
|
||||
|
||||
SAFE_FREE(_id_cache.uri);
|
||||
SAFE_FREE(_id_cache.id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define PUT_BUFFER_SIZE 1024*5
|
||||
|
||||
char _buffer[PUT_BUFFER_SIZE];
|
||||
|
||||
/*
|
||||
* helper method to build up a user text for SSL problems, called from the
|
||||
@@ -116,7 +47,7 @@ static void addSSLWarning( char *ptr, const char *warn, int len )
|
||||
* it to the csync callback to ask the user.
|
||||
*/
|
||||
#define LEN 4096
|
||||
static int verify_sslcert(void *userdata, int failures,
|
||||
static int ssl_callback_by_neon(void *userdata, int failures,
|
||||
const ne_ssl_certificate *certificate)
|
||||
{
|
||||
char problem[LEN];
|
||||
@@ -124,8 +55,8 @@ static int verify_sslcert(void *userdata, int failures,
|
||||
int ret = -1;
|
||||
const ne_ssl_certificate *cert = certificate;
|
||||
csync_auth_callback authcb = NULL;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
|
||||
(void) userdata;
|
||||
memset( problem, 0, LEN );
|
||||
|
||||
while( cert ) {
|
||||
@@ -161,14 +92,14 @@ static int verify_sslcert(void *userdata, int failures,
|
||||
}
|
||||
addSSLWarning( problem, "Do you want to accept the certificate chain anyway?\nAnswer yes to do so and take the risk: ", LEN );
|
||||
|
||||
if( dav_session.csync_ctx ) {
|
||||
authcb = csync_get_auth_callback( dav_session.csync_ctx );
|
||||
if( ctx->csync_ctx ) {
|
||||
authcb = csync_get_auth_callback( ctx->csync_ctx );
|
||||
}
|
||||
if( authcb ){
|
||||
/* call the csync callback */
|
||||
DEBUG_WEBDAV("Call the csync callback for SSL problems");
|
||||
memset( buf, 0, NE_ABUFSIZ );
|
||||
(*authcb) ( problem, buf, NE_ABUFSIZ-1, 1, 0, _userdata );
|
||||
(*authcb) ( problem, buf, NE_ABUFSIZ-1, 1, 0, csync_get_userdata(ctx->csync_ctx) );
|
||||
if( buf[0] == 'y' || buf[0] == 'Y') {
|
||||
ret = 0;
|
||||
} else {
|
||||
@@ -184,41 +115,39 @@ static int verify_sslcert(void *userdata, int failures,
|
||||
* Authentication callback. Is set by ne_set_server_auth to be called
|
||||
* from the neon lib to authenticate a request.
|
||||
*/
|
||||
static int ne_auth( void *userdata, const char *realm, int attempt,
|
||||
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) userdata;
|
||||
(void) realm;
|
||||
|
||||
/* DEBUG_WEBDAV( "Authentication required %s", realm ); */
|
||||
if( username && password ) {
|
||||
DEBUG_WEBDAV( "Authentication required %s", username );
|
||||
if( dav_session.user ) {
|
||||
if( ctx->dav_session.user ) {
|
||||
/* allow user without password */
|
||||
if( strlen( dav_session.user ) < NE_ABUFSIZ ) {
|
||||
strcpy( username, dav_session.user );
|
||||
if( strlen( ctx->dav_session.user ) < NE_ABUFSIZ ) {
|
||||
strcpy( username, ctx->dav_session.user );
|
||||
}
|
||||
if( dav_session.pwd && strlen( dav_session.pwd ) < NE_ABUFSIZ ) {
|
||||
strcpy( password, dav_session.pwd );
|
||||
if( ctx->dav_session.pwd && strlen( ctx->dav_session.pwd ) < NE_ABUFSIZ ) {
|
||||
strcpy( password, ctx->dav_session.pwd );
|
||||
}
|
||||
} else {
|
||||
if( dav_session.csync_ctx ) {
|
||||
authcb = csync_get_auth_callback( dav_session.csync_ctx );
|
||||
}
|
||||
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, _userdata );
|
||||
(*authcb) ("Enter your username: ", buf, NE_ABUFSIZ-1, 1, 0, csync_get_userdata(ctx->csync_ctx) );
|
||||
if( strlen(buf) < NE_ABUFSIZ ) {
|
||||
strcpy( username, buf );
|
||||
}
|
||||
memset( buf, 0, NE_ABUFSIZ );
|
||||
(*authcb) ("Enter your password: ", buf, NE_ABUFSIZ-1, 0, 0, _userdata );
|
||||
(*authcb) ("Enter your password: ", buf, NE_ABUFSIZ-1, 0, 0, csync_get_userdata(ctx->csync_ctx) );
|
||||
if( strlen(buf) < NE_ABUFSIZ) {
|
||||
strcpy( password, buf );
|
||||
}
|
||||
@@ -235,15 +164,15 @@ static int ne_auth( void *userdata, const char *realm, int attempt,
|
||||
* from the neon lib to authenticate against a proxy. The data to authenticate
|
||||
* against comes from mirall throught vio_module_init function.
|
||||
*/
|
||||
static int ne_proxy_auth( void *userdata, const char *realm, int attempt,
|
||||
static int proxy_authentication_callback_by_neon( void *userdata, const char *realm, int attempt,
|
||||
char *username, char *password)
|
||||
{
|
||||
(void) userdata;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
(void) realm;
|
||||
if( dav_session.proxy_user && strlen( dav_session.proxy_user ) < NE_ABUFSIZ) {
|
||||
strcpy( username, dav_session.proxy_user );
|
||||
if( dav_session.proxy_pwd && strlen( dav_session.proxy_pwd ) < NE_ABUFSIZ) {
|
||||
strcpy( password, dav_session.proxy_pwd );
|
||||
if( ctx->dav_session.proxy_user && strlen( ctx->dav_session.proxy_user ) < NE_ABUFSIZ) {
|
||||
strcpy( username, ctx->dav_session.proxy_user );
|
||||
if( ctx->dav_session.proxy_pwd && strlen( ctx->dav_session.proxy_pwd ) < NE_ABUFSIZ) {
|
||||
strcpy( password, ctx->dav_session.proxy_pwd );
|
||||
}
|
||||
}
|
||||
/* NTLM needs several attempts */
|
||||
@@ -251,42 +180,42 @@ static int ne_proxy_auth( void *userdata, const char *realm, int attempt,
|
||||
}
|
||||
|
||||
/* Configure the proxy depending on the variables */
|
||||
static int configureProxy( ne_session *session )
|
||||
static int configureProxy( csync_owncloud_ctx_t *ctx, ne_session *session )
|
||||
{
|
||||
int port = 8080;
|
||||
int re = -1;
|
||||
|
||||
if( ! session ) return -1;
|
||||
if( ! dav_session.proxy_type ) return 0; /* Go by NoProxy per default */
|
||||
if( ! ctx->dav_session.proxy_type ) return 0; /* Go by NoProxy per default */
|
||||
|
||||
if( dav_session.proxy_port > 0 ) {
|
||||
port = dav_session.proxy_port;
|
||||
if( ctx->dav_session.proxy_port > 0 ) {
|
||||
port = ctx->dav_session.proxy_port;
|
||||
}
|
||||
|
||||
if( c_streq(dav_session.proxy_type, "NoProxy" )) {
|
||||
if( c_streq(ctx->dav_session.proxy_type, "NoProxy" )) {
|
||||
DEBUG_WEBDAV("No proxy configured.");
|
||||
re = 0;
|
||||
} else if( c_streq(dav_session.proxy_type, "DefaultProxy") ||
|
||||
c_streq(dav_session.proxy_type, "HttpProxy") ||
|
||||
c_streq(dav_session.proxy_type, "HttpCachingProxy") ||
|
||||
c_streq(dav_session.proxy_type, "Socks5Proxy")) {
|
||||
} else if( c_streq(ctx->dav_session.proxy_type, "DefaultProxy") ||
|
||||
c_streq(ctx->dav_session.proxy_type, "HttpProxy") ||
|
||||
c_streq(ctx->dav_session.proxy_type, "HttpCachingProxy") ||
|
||||
c_streq(ctx->dav_session.proxy_type, "Socks5Proxy")) {
|
||||
|
||||
if( dav_session.proxy_host ) {
|
||||
DEBUG_WEBDAV("%s at %s:%d", dav_session.proxy_type, dav_session.proxy_host, port );
|
||||
if (c_streq(dav_session.proxy_type, "Socks5Proxy")) {
|
||||
ne_session_socks_proxy(session, NE_SOCK_SOCKSV5, dav_session.proxy_host, port,
|
||||
dav_session.proxy_user, dav_session.proxy_pwd);
|
||||
if( ctx->dav_session.proxy_host ) {
|
||||
DEBUG_WEBDAV("%s at %s:%d", ctx->dav_session.proxy_type, ctx->dav_session.proxy_host, port );
|
||||
if (c_streq(ctx->dav_session.proxy_type, "Socks5Proxy")) {
|
||||
ne_session_socks_proxy(session, NE_SOCK_SOCKSV5, ctx->dav_session.proxy_host, port,
|
||||
ctx->dav_session.proxy_user, ctx->dav_session.proxy_pwd);
|
||||
} else {
|
||||
ne_session_proxy(session, dav_session.proxy_host, port );
|
||||
ne_session_proxy(session, ctx->dav_session.proxy_host, port );
|
||||
}
|
||||
re = 2;
|
||||
} else {
|
||||
DEBUG_WEBDAV("%s requested but no proxy host defined.", dav_session.proxy_type );
|
||||
DEBUG_WEBDAV("%s requested but no proxy host defined.", ctx->dav_session.proxy_type );
|
||||
/* we used to try ne_system_session_proxy here, but we should rather err out
|
||||
to behave exactly like the caller. */
|
||||
}
|
||||
} else {
|
||||
DEBUG_WEBDAV( "Unsupported Proxy: %s", dav_session.proxy_type );
|
||||
DEBUG_WEBDAV( "Unsupported Proxy: %s", ctx->dav_session.proxy_type );
|
||||
}
|
||||
|
||||
return re;
|
||||
@@ -303,9 +232,9 @@ static void post_request_hook(ne_request *req, void *userdata, const ne_status *
|
||||
const char *sc = NULL;
|
||||
char *key = NULL;
|
||||
|
||||
(void) userdata;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
|
||||
if (dav_session.session_key)
|
||||
if (ctx->dav_session.session_key)
|
||||
return; /* We already have a session cookie, and we should ignore other ones */
|
||||
|
||||
if(!(status && req)) return;
|
||||
@@ -373,8 +302,8 @@ static void post_request_hook(ne_request *req, void *userdata, const ne_status *
|
||||
}
|
||||
if( key ) {
|
||||
DEBUG_WEBDAV("----> Session-key: %s", key);
|
||||
SAFE_FREE(dav_session.session_key);
|
||||
dav_session.session_key = key;
|
||||
SAFE_FREE(ctx->dav_session.session_key);
|
||||
ctx->dav_session.session_key = key;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,13 +314,14 @@ static void post_request_hook(ne_request *req, void *userdata, const ne_status *
|
||||
static void request_created_hook(ne_request *req, void *userdata,
|
||||
const char *method, const char *requri)
|
||||
{
|
||||
(void) userdata;
|
||||
// FIXME Can possibly be merged with pre_send_hook
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t *) userdata;
|
||||
(void) method;
|
||||
(void) requri;
|
||||
|
||||
if( !req ) return;
|
||||
|
||||
if(dav_session.proxy_type) {
|
||||
if(ctx->dav_session.proxy_type) {
|
||||
/* required for NTLM */
|
||||
ne_add_request_header(req, "Proxy-Connection", "Keep-Alive");
|
||||
}
|
||||
@@ -404,12 +334,12 @@ static void request_created_hook(ne_request *req, void *userdata,
|
||||
static void pre_send_hook(ne_request *req, void *userdata,
|
||||
ne_buffer *header)
|
||||
{
|
||||
(void) userdata;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t *) userdata;
|
||||
|
||||
if( !req ) return;
|
||||
|
||||
if(dav_session.session_key) {
|
||||
ne_buffer_concat(header, "Cookie: ", dav_session.session_key, "\r\n", NULL);
|
||||
if(ctx->dav_session.session_key) {
|
||||
ne_buffer_concat(header, "Cookie: ", ctx->dav_session.session_key, "\r\n", NULL);
|
||||
} else {
|
||||
DEBUG_WEBDAV("csync pre_send_hook We don't have a Auth Cookie (session_key), this is wrong!");
|
||||
}
|
||||
@@ -419,16 +349,15 @@ static int post_send_hook(ne_request *req, void *userdata,
|
||||
const ne_status *status)
|
||||
{
|
||||
const char *location;
|
||||
|
||||
(void) userdata;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t *) userdata;
|
||||
(void) status;
|
||||
|
||||
location = ne_get_response_header(req, "Location");
|
||||
|
||||
if( !location ) return NE_OK;
|
||||
|
||||
if( dav_session.redir_callback ) {
|
||||
if( dav_session.redir_callback( dav_session.csync_ctx, location ) ) {
|
||||
if( ctx->dav_session.redir_callback ) {
|
||||
if( ctx->dav_session.redir_callback( ctx->csync_ctx, location ) ) {
|
||||
return NE_REDIRECT;
|
||||
} else {
|
||||
return NE_RETRY;
|
||||
@@ -438,37 +367,12 @@ static int post_send_hook(ne_request *req, void *userdata,
|
||||
return NE_REDIRECT;
|
||||
}
|
||||
|
||||
// as per http://sourceforge.net/p/predef/wiki/OperatingSystems/
|
||||
// extend as required
|
||||
static const char* 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
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
static int dav_connect(const char *base_url) {
|
||||
static int dav_connect(csync_owncloud_ctx_t *ctx, const char *base_url) {
|
||||
int useSSL = 0;
|
||||
int rc;
|
||||
char protocol[6] = {'\0'};
|
||||
@@ -479,11 +383,14 @@ static int dav_connect(const char *base_url) {
|
||||
unsigned int port = 0;
|
||||
int proxystate = -1;
|
||||
|
||||
if (_connected) {
|
||||
if (ctx->_connected) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = c_parse_uri( base_url, &scheme, &dav_session.user, &dav_session.pwd, &host, &port, &path );
|
||||
rc = c_parse_uri( base_url, &scheme,
|
||||
&ctx->dav_session.user,
|
||||
&ctx->dav_session.pwd,
|
||||
&host, &port, &path );
|
||||
if( rc < 0 ) {
|
||||
DEBUG_WEBDAV("Failed to parse uri %s", base_url );
|
||||
goto out;
|
||||
@@ -505,29 +412,29 @@ static int dav_connect(const char *base_url) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
DEBUG_WEBDAV("* user %s", dav_session.user ? dav_session.user : "");
|
||||
DEBUG_WEBDAV("* user %s", ctx->dav_session.user ? ctx->dav_session.user : "");
|
||||
|
||||
if (port == 0) {
|
||||
port = ne_uri_defaultport(protocol);
|
||||
}
|
||||
|
||||
dav_session.ctx = ne_session_create( protocol, host, port);
|
||||
ctx->dav_session.ctx = ne_session_create( protocol, host, port);
|
||||
|
||||
if (dav_session.ctx == NULL) {
|
||||
if (ctx->dav_session.ctx == NULL) {
|
||||
DEBUG_WEBDAV("Session create with protocol %s failed", protocol );
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dav_session.read_timeout != 0) {
|
||||
ne_set_read_timeout(dav_session.ctx, dav_session.read_timeout);
|
||||
DEBUG_WEBDAV("Timeout set to %u seconds", dav_session.read_timeout );
|
||||
if (ctx->dav_session.read_timeout != 0) {
|
||||
ne_set_read_timeout(ctx->dav_session.ctx, ctx->dav_session.read_timeout);
|
||||
DEBUG_WEBDAV("Timeout set to %u seconds", ctx->dav_session.read_timeout );
|
||||
}
|
||||
|
||||
snprintf( uaBuf, sizeof(uaBuf), "Mozilla/5.0 (%s) csyncoC/%s",
|
||||
get_platform(), CSYNC_STRINGIFY( LIBCSYNC_VERSION ));
|
||||
ne_set_useragent( dav_session.ctx, uaBuf);
|
||||
ne_set_server_auth(dav_session.ctx, ne_auth, 0 );
|
||||
csync_owncloud_get_platform(), CSYNC_STRINGIFY( LIBCSYNC_VERSION ));
|
||||
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)) {
|
||||
@@ -536,28 +443,28 @@ static int dav_connect(const char *base_url) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ne_ssl_trust_default_ca( dav_session.ctx );
|
||||
ne_ssl_set_verify( dav_session.ctx, verify_sslcert, 0 );
|
||||
ne_ssl_trust_default_ca( ctx->dav_session.ctx );
|
||||
ne_ssl_set_verify( ctx->dav_session.ctx, ssl_callback_by_neon, ctx);
|
||||
}
|
||||
|
||||
/* Hook called when a request is created. It sets the proxy connection header. */
|
||||
ne_hook_create_request( dav_session.ctx, request_created_hook, NULL );
|
||||
ne_hook_create_request( ctx->dav_session.ctx, request_created_hook, ctx );
|
||||
/* Hook called after response headers are read. It gets the Session ID. */
|
||||
ne_hook_post_headers( dav_session.ctx, post_request_hook, NULL );
|
||||
ne_hook_post_headers( ctx->dav_session.ctx, post_request_hook, ctx );
|
||||
/* Hook called before a request is sent. It sets the cookies. */
|
||||
ne_hook_pre_send( dav_session.ctx, pre_send_hook, NULL );
|
||||
ne_hook_pre_send( ctx->dav_session.ctx, pre_send_hook, ctx );
|
||||
/* Hook called after request is dispatched. Used for handling possible redirections. */
|
||||
ne_hook_post_send( dav_session.ctx, post_send_hook, NULL );
|
||||
ne_hook_post_send( ctx->dav_session.ctx, post_send_hook, ctx );
|
||||
|
||||
/* Proxy support */
|
||||
proxystate = configureProxy( dav_session.ctx );
|
||||
proxystate = configureProxy( ctx, ctx->dav_session.ctx );
|
||||
if( proxystate < 0 ) {
|
||||
DEBUG_WEBDAV("Error: Proxy-Configuration failed.");
|
||||
} else if( proxystate > 0 ) {
|
||||
ne_set_proxy_auth( dav_session.ctx, ne_proxy_auth, 0 );
|
||||
ne_set_proxy_auth( ctx->dav_session.ctx, proxy_authentication_callback_by_neon, 0 );
|
||||
}
|
||||
|
||||
_connected = 1;
|
||||
ctx->_connected = 1;
|
||||
rc = 0;
|
||||
out:
|
||||
SAFE_FREE(path);
|
||||
@@ -573,7 +480,7 @@ out:
|
||||
* and fills a resource struct and stores it to the result list which
|
||||
* is stored in the listdir_context.
|
||||
*/
|
||||
static void results(void *userdata,
|
||||
static void propfind_results_callback(void *userdata,
|
||||
const ne_uri *uri,
|
||||
const ne_prop_result_set *set)
|
||||
{
|
||||
@@ -583,6 +490,8 @@ static void results(void *userdata,
|
||||
const char *resourcetype = NULL;
|
||||
const char *md5sum = NULL;
|
||||
const char *file_id = NULL;
|
||||
const char *directDownloadUrl = NULL;
|
||||
const char *directDownloadCookies = NULL;
|
||||
const ne_status *status = NULL;
|
||||
char *path = ne_path_unescape( uri->path );
|
||||
|
||||
@@ -608,6 +517,8 @@ static void results(void *userdata,
|
||||
resourcetype = ne_propset_value( set, &ls_props[2] );
|
||||
md5sum = ne_propset_value( set, &ls_props[3] );
|
||||
file_id = ne_propset_value( set, &ls_props[4] );
|
||||
directDownloadUrl = ne_propset_value( set, &ls_props[5] );
|
||||
directDownloadCookies = ne_propset_value( set, &ls_props[6] );
|
||||
|
||||
newres->type = resr_normal;
|
||||
if( clength == NULL && resourcetype && strncmp( resourcetype, "<DAV:collection>", 16 ) == 0) {
|
||||
@@ -631,6 +542,13 @@ static void results(void *userdata,
|
||||
|
||||
csync_vio_set_file_id(newres->file_id, file_id);
|
||||
|
||||
if (directDownloadUrl) {
|
||||
newres->directDownloadUrl = c_strdup(directDownloadUrl);
|
||||
}
|
||||
if (directDownloadCookies) {
|
||||
newres->directDownloadCookies = c_strdup(directDownloadCookies);
|
||||
}
|
||||
|
||||
/* prepend the new resource to the result list */
|
||||
newres->next = fetchCtx->list;
|
||||
fetchCtx->list = newres;
|
||||
@@ -643,7 +561,7 @@ static void results(void *userdata,
|
||||
/*
|
||||
* fetches a resource list from the WebDAV server. This is equivalent to list dir.
|
||||
*/
|
||||
static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
||||
static struct listdir_context *fetch_resource_list(csync_owncloud_ctx_t *ctx, const char *uri, int depth)
|
||||
{
|
||||
struct listdir_context *fetchCtx;
|
||||
int ret = 0;
|
||||
@@ -657,12 +575,12 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
||||
|
||||
/* The old legacy one-level PROPFIND cache. Also gets filled
|
||||
by the recursive cache if 'infinity' did not suceed. */
|
||||
if (propfind_cache) {
|
||||
if (c_streq(curi, propfind_cache->target)) {
|
||||
if (ctx->propfind_cache) {
|
||||
if (c_streq(curi, ctx->propfind_cache->target)) {
|
||||
DEBUG_WEBDAV("fetch_resource_list Using simple PROPFIND cache %s", curi);
|
||||
propfind_cache->ref++;
|
||||
ctx->propfind_cache->ref++;
|
||||
SAFE_FREE(curi);
|
||||
return propfind_cache;
|
||||
return ctx->propfind_cache;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -678,10 +596,10 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
||||
fetchCtx->ref = 1;
|
||||
|
||||
/* do a propfind request and parse the results in the results function, set as callback */
|
||||
hdl = ne_propfind_create(dav_session.ctx, curi, depth);
|
||||
hdl = ne_propfind_create(ctx->dav_session.ctx, curi, depth);
|
||||
|
||||
if(hdl) {
|
||||
ret = ne_propfind_named(hdl, ls_props, results, fetchCtx);
|
||||
ret = ne_propfind_named(hdl, ls_props, propfind_results_callback, fetchCtx);
|
||||
request = ne_propfind_get_request( hdl );
|
||||
req_status = ne_get_status( request );
|
||||
}
|
||||
@@ -694,14 +612,14 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
||||
DEBUG_WEBDAV("ERROR: Request failed: status %d (%s)", req_status->code,
|
||||
req_status->reason_phrase);
|
||||
ret = NE_CONNECT;
|
||||
set_error_message(req_status->reason_phrase);
|
||||
set_error_message(ctx, req_status->reason_phrase);
|
||||
}
|
||||
DEBUG_WEBDAV("Simple propfind result code %d.", req_status->code);
|
||||
} else {
|
||||
if( ret == NE_ERROR && req_status->code == 404) {
|
||||
errno = ENOENT;
|
||||
} else {
|
||||
set_errno_from_neon_errcode(ret);
|
||||
set_errno_from_neon_errcode(ctx, ret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -716,18 +634,18 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
||||
DEBUG_WEBDAV("ERROR: Content type of propfind request not XML: %s.",
|
||||
content_type ? content_type: "<empty>");
|
||||
errno = ERRNO_WRONG_CONTENT;
|
||||
set_error_message("Server error: PROPFIND reply is not XML formatted!");
|
||||
set_error_message(ctx, "Server error: PROPFIND reply is not XML formatted!");
|
||||
ret = NE_CONNECT;
|
||||
}
|
||||
}
|
||||
|
||||
if( ret != NE_OK ) {
|
||||
const char *err = NULL;
|
||||
set_errno_from_neon_errcode(ret);
|
||||
set_errno_from_neon_errcode(ctx, ret);
|
||||
|
||||
err = ne_get_error( dav_session.ctx );
|
||||
err = ne_get_error( ctx->dav_session.ctx );
|
||||
if(err) {
|
||||
set_error_message(err);
|
||||
set_error_message(ctx, err);
|
||||
}
|
||||
DEBUG_WEBDAV("WRN: propfind named failed with %d, request error: %s", ret, err ? err : "<nil>");
|
||||
}
|
||||
@@ -740,19 +658,19 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free_fetchCtx(propfind_cache);
|
||||
propfind_cache = fetchCtx;
|
||||
propfind_cache->ref++;
|
||||
free_fetchCtx(ctx->propfind_cache);
|
||||
ctx->propfind_cache = fetchCtx;
|
||||
ctx->propfind_cache->ref++;
|
||||
return fetchCtx;
|
||||
}
|
||||
|
||||
static struct listdir_context *fetch_resource_list_attempts(const char *uri, int depth)
|
||||
static struct listdir_context *fetch_resource_list_attempts(csync_owncloud_ctx_t *ctx, const char *uri, int depth)
|
||||
{
|
||||
int i;
|
||||
|
||||
struct listdir_context *fetchCtx = NULL;
|
||||
for(i = 0; i < 10; ++i) {
|
||||
fetchCtx = fetch_resource_list(uri, depth);
|
||||
fetchCtx = fetch_resource_list(ctx, uri, depth);
|
||||
if(fetchCtx) break;
|
||||
/* only loop in case the content is not XML formatted. Otherwise for every
|
||||
* non successful stat (for non existing directories) its tried 10 times. */
|
||||
@@ -764,165 +682,39 @@ static struct listdir_context *fetch_resource_list_attempts(const char *uri, int
|
||||
return fetchCtx;
|
||||
}
|
||||
|
||||
static void fill_stat_cache( csync_vio_file_stat_t *lfs ) {
|
||||
|
||||
if( _stat_cache.name ) SAFE_FREE(_stat_cache.name);
|
||||
if( _stat_cache.etag ) SAFE_FREE(_stat_cache.etag );
|
||||
|
||||
if( !lfs) return;
|
||||
|
||||
_stat_cache.name = c_strdup(lfs->name);
|
||||
_stat_cache.mtime = lfs->mtime;
|
||||
_stat_cache.fields = lfs->fields;
|
||||
_stat_cache.type = lfs->type;
|
||||
_stat_cache.size = lfs->size;
|
||||
csync_vio_file_stat_set_file_id(&_stat_cache, lfs->file_id);
|
||||
|
||||
if( lfs->etag ) {
|
||||
_stat_cache.etag = c_strdup(lfs->etag);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* file functions
|
||||
*/
|
||||
int owncloud_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
/* get props:
|
||||
* modtime
|
||||
* creattime
|
||||
* size
|
||||
*/
|
||||
csync_vio_file_stat_t *lfs = NULL;
|
||||
struct listdir_context *fetchCtx = NULL;
|
||||
char *decodedUri = NULL;
|
||||
int len = 0;
|
||||
errno = 0;
|
||||
|
||||
buf->name = c_basename(uri);
|
||||
|
||||
if (buf->name == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( _stat_cache.name && strcmp( buf->name, _stat_cache.name ) == 0 ) {
|
||||
buf->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS;
|
||||
buf->fields = _stat_cache.fields;
|
||||
buf->type = _stat_cache.type;
|
||||
buf->mtime = _stat_cache.mtime;
|
||||
buf->size = _stat_cache.size;
|
||||
buf->mode = _stat_perms( _stat_cache.type );
|
||||
buf->etag = NULL;
|
||||
if( _stat_cache.etag ) {
|
||||
buf->etag = c_strdup( _stat_cache.etag );
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG;
|
||||
}
|
||||
csync_vio_file_stat_set_file_id( buf, _stat_cache.file_id );
|
||||
return 0;
|
||||
}
|
||||
DEBUG_WEBDAV("owncloud_stat => Could not find in stat cache %s", uri);
|
||||
|
||||
/* fetch data via a propfind call. */
|
||||
/* fetchCtx = fetch_resource_list( uri, NE_DEPTH_ONE); */
|
||||
fetchCtx = fetch_resource_list_attempts( uri, NE_DEPTH_ONE);
|
||||
DEBUG_WEBDAV("=> Errno after fetch resource list for %s: %d", uri, errno);
|
||||
if (!fetchCtx) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( fetchCtx ) {
|
||||
struct resource *res = fetchCtx->list;
|
||||
while( res ) {
|
||||
/* remove trailing slashes */
|
||||
len = strlen(res->uri);
|
||||
while( len > 0 && res->uri[len-1] == '/' ) --len;
|
||||
decodedUri = ne_path_unescape( fetchCtx->target ); /* allocates memory */
|
||||
|
||||
/* Only do the comparaison of the part of the string without the trailing
|
||||
slashes, and make sure decodedUri is not too large */
|
||||
if( strncmp(res->uri, decodedUri, len ) == 0 && decodedUri[len] == '\0') {
|
||||
SAFE_FREE( decodedUri );
|
||||
break;
|
||||
}
|
||||
res = res->next;
|
||||
SAFE_FREE( decodedUri );
|
||||
}
|
||||
if( res ) {
|
||||
DEBUG_WEBDAV("Working on file %s", res->name );
|
||||
} else {
|
||||
DEBUG_WEBDAV("ERROR: Result struct not valid!");
|
||||
}
|
||||
|
||||
lfs = resourceToFileStat( res );
|
||||
if( lfs ) {
|
||||
buf->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG;
|
||||
|
||||
buf->fields = lfs->fields;
|
||||
buf->type = lfs->type;
|
||||
buf->mtime = lfs->mtime;
|
||||
buf->size = lfs->size;
|
||||
buf->mode = _stat_perms( lfs->type );
|
||||
buf->etag = NULL;
|
||||
if( lfs->etag ) {
|
||||
buf->etag = c_strdup( lfs->etag );
|
||||
}
|
||||
csync_vio_file_stat_set_file_id( buf, lfs->file_id );
|
||||
|
||||
/* fill the static stat buf as input for the stat function */
|
||||
csync_vio_file_stat_destroy( lfs );
|
||||
}
|
||||
|
||||
free_fetchCtx( fetchCtx );
|
||||
}
|
||||
DEBUG_WEBDAV("STAT result from propfind: %s, mtime: %llu", buf->name ? buf->name:"NULL",
|
||||
(unsigned long long) buf->mtime );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* directory functions
|
||||
*/
|
||||
csync_vio_handle_t *owncloud_opendir(const char *uri) {
|
||||
csync_vio_handle_t *owncloud_opendir(CSYNC *ctx, const char *uri) {
|
||||
struct listdir_context *fetchCtx = NULL;
|
||||
char *curi = NULL;
|
||||
|
||||
DEBUG_WEBDAV("opendir method called on %s", uri );
|
||||
|
||||
if (dav_connect( uri ) < 0) {
|
||||
if (dav_connect( ctx->owncloud_context, uri ) < 0) {
|
||||
DEBUG_WEBDAV("connection failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
curi = _cleanPath( uri );
|
||||
if (is_first_propfind && !dav_session.no_recursive_propfind) {
|
||||
is_first_propfind = false;
|
||||
if (ctx->owncloud_context->is_first_propfind && !ctx->owncloud_context->dav_session.no_recursive_propfind) {
|
||||
ctx->owncloud_context->is_first_propfind = false;
|
||||
// Try to fill it
|
||||
fill_recursive_propfind_cache(uri, curi);
|
||||
fill_recursive_propfind_cache(ctx->owncloud_context, uri, curi);
|
||||
}
|
||||
if (propfind_recursive_cache) {
|
||||
if (ctx->owncloud_context->propfind_recursive_cache) {
|
||||
// Try to fetch from recursive cache (if we have one)
|
||||
fetchCtx = get_listdir_context_from_recursive_cache(curi);
|
||||
fetchCtx = get_listdir_context_from_recursive_cache(ctx->owncloud_context, curi);
|
||||
}
|
||||
SAFE_FREE(curi);
|
||||
is_first_propfind = false;
|
||||
ctx->owncloud_context->is_first_propfind = false;
|
||||
if (fetchCtx) {
|
||||
return fetchCtx;
|
||||
}
|
||||
|
||||
/* fetchCtx = fetch_resource_list( uri, NE_DEPTH_ONE ); */
|
||||
fetchCtx = fetch_resource_list_attempts( uri, NE_DEPTH_ONE);
|
||||
fetchCtx = fetch_resource_list_attempts( ctx->owncloud_context, uri, NE_DEPTH_ONE);
|
||||
if( !fetchCtx ) {
|
||||
/* errno is set properly in fetch_resource_list */
|
||||
DEBUG_WEBDAV("Errno set to %d", errno);
|
||||
@@ -935,17 +727,16 @@ csync_vio_handle_t *owncloud_opendir(const char *uri) {
|
||||
/* no freeing of curi because its part of the fetchCtx and gets freed later */
|
||||
}
|
||||
|
||||
int owncloud_closedir(csync_vio_handle_t *dhandle) {
|
||||
|
||||
int owncloud_closedir(CSYNC *ctx, csync_vio_handle_t *dhandle) {
|
||||
struct listdir_context *fetchCtx = dhandle;
|
||||
|
||||
free_fetchCtx(fetchCtx);
|
||||
|
||||
(void)ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
csync_vio_file_stat_t *owncloud_readdir(csync_vio_handle_t *dhandle) {
|
||||
csync_vio_file_stat_t *owncloud_readdir(CSYNC *ctx, csync_vio_handle_t *dhandle) {
|
||||
struct listdir_context *fetchCtx = dhandle;
|
||||
(void)ctx;
|
||||
|
||||
// DEBUG_WEBDAV("owncloud_readdir" );
|
||||
// DEBUG_WEBDAV("owncloud_readdir %s ", fetchCtx->target);
|
||||
@@ -971,8 +762,10 @@ csync_vio_file_stat_t *owncloud_readdir(csync_vio_handle_t *dhandle) {
|
||||
*/
|
||||
escaped_path = ne_path_escape( currResource->uri );
|
||||
if (ne_path_compare(fetchCtx->target, escaped_path) != 0) {
|
||||
csync_vio_file_stat_t* lfs = resourceToFileStat(currResource);
|
||||
fill_stat_cache(lfs);
|
||||
// Convert the resource for the caller
|
||||
csync_vio_file_stat_t* lfs = csync_vio_file_stat_new();
|
||||
resourceToFileStat(lfs, currResource);
|
||||
|
||||
SAFE_FREE( escaped_path );
|
||||
return lfs;
|
||||
}
|
||||
@@ -984,39 +777,55 @@ csync_vio_file_stat_t *owncloud_readdir(csync_vio_handle_t *dhandle) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *owncloud_error_string(void)
|
||||
char *owncloud_error_string(CSYNC* ctx)
|
||||
{
|
||||
return dav_session.error_string;
|
||||
return ctx->owncloud_context->dav_session.error_string;
|
||||
}
|
||||
|
||||
int owncloud_commit(void) {
|
||||
int owncloud_commit(CSYNC* ctx) {
|
||||
if (!ctx->owncloud_context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
clean_caches();
|
||||
clear_propfind_recursive_cache(ctx->owncloud_context);
|
||||
|
||||
if( dav_session.ctx ) {
|
||||
ne_forget_auth(dav_session.ctx);
|
||||
ne_session_destroy( dav_session.ctx );
|
||||
}
|
||||
free_fetchCtx(ctx->owncloud_context->propfind_cache);
|
||||
ctx->owncloud_context->propfind_cache = NULL;
|
||||
|
||||
if( ctx->owncloud_context->dav_session.ctx ) {
|
||||
ne_forget_auth(ctx->owncloud_context->dav_session.ctx);
|
||||
ne_session_destroy(ctx->owncloud_context->dav_session.ctx );
|
||||
ctx->owncloud_context->dav_session.ctx = 0;
|
||||
}
|
||||
|
||||
ctx->owncloud_context->is_first_propfind = true;
|
||||
/* DEBUG_WEBDAV( "********** vio_module_shutdown" ); */
|
||||
|
||||
dav_session.ctx = 0;
|
||||
ctx->owncloud_context->dav_session.ctx = 0;
|
||||
|
||||
// ne_sock_exit();
|
||||
_connected = 0; /* triggers dav_connect to go through the whole neon setup */
|
||||
ctx->owncloud_context->_connected = 0; /* triggers dav_connect to go through the whole neon setup */
|
||||
|
||||
SAFE_FREE( dav_session.user );
|
||||
SAFE_FREE( dav_session.pwd );
|
||||
SAFE_FREE( dav_session.session_key);
|
||||
SAFE_FREE( dav_session.error_string );
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.user );
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.pwd );
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.session_key);
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.error_string );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int owncloud_set_property(const char *key, void *data) {
|
||||
void owncloud_destroy(CSYNC* ctx)
|
||||
{
|
||||
owncloud_commit(ctx);
|
||||
SAFE_FREE(ctx->owncloud_context);
|
||||
ctx->owncloud_context = 0;
|
||||
}
|
||||
|
||||
int owncloud_set_property(CSYNC* ctx, const char *key, void *data) {
|
||||
#define READ_STRING_PROPERTY(P) \
|
||||
if (c_streq(key, #P)) { \
|
||||
SAFE_FREE(dav_session.P); \
|
||||
dav_session.P = c_strdup((const char*)data); \
|
||||
SAFE_FREE(ctx->owncloud_context->dav_session.P); \
|
||||
ctx->owncloud_context->dav_session.P = c_strdup((const char*)data); \
|
||||
return 0; \
|
||||
}
|
||||
READ_STRING_PROPERTY(session_key)
|
||||
@@ -1027,48 +836,43 @@ int owncloud_set_property(const char *key, void *data) {
|
||||
#undef READ_STRING_PROPERTY
|
||||
|
||||
if (c_streq(key, "proxy_port")) {
|
||||
dav_session.proxy_port = *(int*)(data);
|
||||
ctx->owncloud_context->dav_session.proxy_port = *(int*)(data);
|
||||
return 0;
|
||||
}
|
||||
if (c_streq(key, "read_timeout") || c_streq(key, "timeout")) {
|
||||
dav_session.read_timeout = *(int*)(data);
|
||||
return 0;
|
||||
}
|
||||
if( c_streq(key, "csync_context")) {
|
||||
dav_session.csync_ctx = data;
|
||||
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 = dav_session.ctx;
|
||||
*(ne_session**)data = ctx->owncloud_context->dav_session.ctx;
|
||||
return 0;
|
||||
}
|
||||
if( c_streq(key, "no_recursive_propfind")) {
|
||||
dav_session.no_recursive_propfind = *(bool*)(data);
|
||||
ctx->owncloud_context->dav_session.no_recursive_propfind = *(bool*)(data);
|
||||
return 0;
|
||||
}
|
||||
if( c_streq(key, "redirect_callback")) {
|
||||
if (data) {
|
||||
csync_owncloud_redirect_callback_t* cb_wrapper = data;
|
||||
|
||||
dav_session.redir_callback = *cb_wrapper;
|
||||
ctx->owncloud_context->dav_session.redir_callback = *cb_wrapper;
|
||||
} else {
|
||||
dav_session.redir_callback = NULL;
|
||||
ctx->owncloud_context->dav_session.redir_callback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void owncloud_init(void *userdata) {
|
||||
void owncloud_init(CSYNC* ctx) {
|
||||
|
||||
_userdata = userdata;
|
||||
_connected = 0; /* triggers dav_connect to go through the whole neon setup */
|
||||
|
||||
memset(&dav_session, 0, sizeof(dav_session));
|
||||
ctx->owncloud_context = c_malloc( sizeof( struct csync_owncloud_ctx_s ));
|
||||
ctx->owncloud_context->csync_ctx = ctx; // back reference
|
||||
ctx->owncloud_context->is_first_propfind = true;
|
||||
|
||||
/* Disable it, Mirall can enable it for the first sync (= no DB)*/
|
||||
dav_session.no_recursive_propfind = true;
|
||||
ctx->owncloud_context->dav_session.no_recursive_propfind = true;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et cindent: */
|
||||
|
||||
@@ -21,159 +21,18 @@
|
||||
#ifndef CSYNC_OWNCLOUD_H
|
||||
#define CSYNC_OWNCLOUD_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "config_csync.h"
|
||||
#ifdef NEON_WITH_LFS /* Switch on LFS in libneon. Never remove the NE_LFS! */
|
||||
#define NE_LFS
|
||||
#endif
|
||||
|
||||
#include <neon/ne_basic.h>
|
||||
#include <neon/ne_socket.h>
|
||||
#include <neon/ne_session.h>
|
||||
#include <neon/ne_request.h>
|
||||
#include <neon/ne_props.h>
|
||||
#include <neon/ne_auth.h>
|
||||
#include <neon/ne_dates.h>
|
||||
#include <neon/ne_compress.h>
|
||||
#include <neon/ne_redirect.h>
|
||||
|
||||
|
||||
#include "c_rbtree.h"
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "csync.h"
|
||||
#include "csync_misc.h"
|
||||
#include "csync_macros.h"
|
||||
#include "c_private.h"
|
||||
#include "httpbf.h"
|
||||
|
||||
#include "vio/csync_vio_file_stat.h"
|
||||
#include "vio/csync_vio.h"
|
||||
|
||||
#include "csync_log.h"
|
||||
|
||||
|
||||
#define DEBUG_WEBDAV(...) csync_log( 9, "oc_module", __VA_ARGS__);
|
||||
|
||||
enum resource_type {
|
||||
resr_normal = 0,
|
||||
resr_collection,
|
||||
resr_reference,
|
||||
resr_error
|
||||
};
|
||||
|
||||
/* Struct to store data for each resource found during an opendir operation.
|
||||
* It represents a single file entry.
|
||||
*/
|
||||
|
||||
typedef struct resource {
|
||||
char *uri; /* The complete uri */
|
||||
char *name; /* The filename only */
|
||||
|
||||
enum resource_type type;
|
||||
int64_t size;
|
||||
time_t modtime;
|
||||
char* md5;
|
||||
char file_id[FILE_ID_BUF_SIZE+1];
|
||||
|
||||
struct resource *next;
|
||||
} resource;
|
||||
|
||||
/* Struct to hold the context of a WebDAV PropFind operation to fetch
|
||||
* a directory listing from the server.
|
||||
*/
|
||||
struct listdir_context {
|
||||
struct resource *list; /* The list of result resources */
|
||||
struct resource *currResource; /* A pointer to the current resource */
|
||||
char *target; /* Request-URI of the PROPFIND */
|
||||
unsigned int result_count; /* number of elements stored in list */
|
||||
int ref; /* reference count, only destroy when it reaches 0 */
|
||||
};
|
||||
|
||||
|
||||
/* Our cache, key is a char* */
|
||||
extern c_rbtree_t *propfind_recursive_cache;
|
||||
/* Values are propfind_recursive_element: */
|
||||
struct propfind_recursive_element {
|
||||
struct resource *self;
|
||||
struct resource *children;
|
||||
struct propfind_recursive_element *parent;
|
||||
};
|
||||
typedef struct propfind_recursive_element propfind_recursive_element_t;
|
||||
void clear_propfind_recursive_cache(void);
|
||||
struct listdir_context *get_listdir_context_from_recursive_cache(const char *curi);
|
||||
void fill_recursive_propfind_cache(const char *uri, const char *curi);
|
||||
struct listdir_context *get_listdir_context_from_cache(const char *curi);
|
||||
void fetch_resource_list_recursive(const char *uri, const char *curi);
|
||||
|
||||
typedef int (*csync_owncloud_redirect_callback_t)(CSYNC* ctx, const char* uri);
|
||||
|
||||
/* Struct with the WebDAV session */
|
||||
struct dav_session_s {
|
||||
ne_session *ctx;
|
||||
char *user;
|
||||
char *pwd;
|
||||
|
||||
char *proxy_type;
|
||||
char *proxy_host;
|
||||
int proxy_port;
|
||||
char *proxy_user;
|
||||
char *proxy_pwd;
|
||||
|
||||
char *session_key;
|
||||
|
||||
char *error_string;
|
||||
|
||||
int read_timeout;
|
||||
|
||||
CSYNC *csync_ctx;
|
||||
|
||||
bool no_recursive_propfind;
|
||||
|
||||
csync_owncloud_redirect_callback_t redir_callback;
|
||||
};
|
||||
extern struct dav_session_s dav_session;
|
||||
|
||||
/* The list of properties that is fetched in PropFind on a collection */
|
||||
static const ne_propname ls_props[] = {
|
||||
{ "DAV:", "getlastmodified" },
|
||||
{ "DAV:", "getcontentlength" },
|
||||
{ "DAV:", "resourcetype" },
|
||||
{ "DAV:", "getetag"},
|
||||
{ "http://owncloud.org/ns", "id"},
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
void set_errno_from_http_errcode( int err );
|
||||
void set_error_message( const char *msg );
|
||||
void set_errno_from_neon_errcode( int neon_code );
|
||||
int http_result_code_from_session(void);
|
||||
void set_errno_from_session(void);
|
||||
|
||||
time_t oc_httpdate_parse( const char *date );
|
||||
|
||||
char *_cleanPath( const char* uri );
|
||||
|
||||
int _stat_perms( int type );
|
||||
csync_vio_file_stat_t *resourceToFileStat( struct resource *res );
|
||||
|
||||
// Public API from vio
|
||||
csync_vio_handle_t *owncloud_opendir(const char *uri);
|
||||
csync_vio_file_stat_t *owncloud_readdir(csync_vio_handle_t *dhandle);
|
||||
int owncloud_closedir(csync_vio_handle_t *dhandle);
|
||||
int owncloud_stat(const char *uri, csync_vio_file_stat_t *buf);
|
||||
int owncloud_commit(void);
|
||||
char *owncloud_error_string(void);
|
||||
void owncloud_init(void *userdata);
|
||||
int owncloud_set_property(const char *key, void *data);
|
||||
// Public API used by csync
|
||||
csync_vio_handle_t *owncloud_opendir(CSYNC* ctx, const char *uri);
|
||||
csync_vio_file_stat_t *owncloud_readdir(CSYNC* ctx, csync_vio_handle_t *dhandle);
|
||||
int owncloud_closedir(CSYNC* ctx, csync_vio_handle_t *dhandle);
|
||||
int owncloud_commit(CSYNC* ctx);
|
||||
void owncloud_destroy(CSYNC* ctx);
|
||||
char *owncloud_error_string(CSYNC* ctx);
|
||||
void owncloud_init(CSYNC* ctx);
|
||||
int owncloud_set_property(CSYNC* ctx, const char *key, void *data);
|
||||
|
||||
#endif /* CSYNC_OWNCLOUD_H */
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2011 by Andreas Schneider <asn@cryptomilk.org>
|
||||
* Copyright (c) 2012 by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef CSYNC_OWNCLOUD_PRIVATE_H
|
||||
#define CSYNC_OWNCLOUD_PRIVATE_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "config_csync.h"
|
||||
#ifdef NEON_WITH_LFS /* Switch on LFS in libneon. Never remove the NE_LFS! */
|
||||
#define NE_LFS
|
||||
#endif
|
||||
|
||||
#include <neon/ne_basic.h>
|
||||
#include <neon/ne_socket.h>
|
||||
#include <neon/ne_session.h>
|
||||
#include <neon/ne_request.h>
|
||||
#include <neon/ne_props.h>
|
||||
#include <neon/ne_auth.h>
|
||||
#include <neon/ne_dates.h>
|
||||
#include <neon/ne_compress.h>
|
||||
#include <neon/ne_redirect.h>
|
||||
|
||||
|
||||
#include "c_rbtree.h"
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "csync.h"
|
||||
#include "csync_misc.h"
|
||||
#include "csync_macros.h"
|
||||
#include "c_private.h"
|
||||
#include "httpbf.h"
|
||||
|
||||
#include "vio/csync_vio_file_stat.h"
|
||||
#include "vio/csync_vio.h"
|
||||
|
||||
#include "csync_log.h"
|
||||
|
||||
#include "csync_owncloud.h"
|
||||
|
||||
|
||||
#define DEBUG_WEBDAV(...) csync_log( 9, "oc_module", __VA_ARGS__);
|
||||
|
||||
typedef int (*csync_owncloud_redirect_callback_t)(CSYNC* ctx, const char* uri);
|
||||
|
||||
/* Struct with the WebDAV session */
|
||||
struct dav_session_s {
|
||||
ne_session *ctx;
|
||||
char *user;
|
||||
char *pwd;
|
||||
|
||||
char *proxy_type;
|
||||
char *proxy_host;
|
||||
int proxy_port;
|
||||
char *proxy_user;
|
||||
char *proxy_pwd;
|
||||
|
||||
char *session_key;
|
||||
|
||||
char *error_string;
|
||||
|
||||
int read_timeout;
|
||||
|
||||
bool no_recursive_propfind;
|
||||
|
||||
csync_owncloud_redirect_callback_t redir_callback;
|
||||
};
|
||||
|
||||
struct csync_owncloud_ctx_s {
|
||||
CSYNC *csync_ctx;
|
||||
|
||||
// For the PROPFIND results
|
||||
bool is_first_propfind;
|
||||
struct listdir_context *propfind_cache;
|
||||
c_rbtree_t *propfind_recursive_cache;
|
||||
int propfind_recursive_cache_depth;
|
||||
int propfind_recursive_cache_file_count;
|
||||
int propfind_recursive_cache_folder_count;
|
||||
|
||||
// For the WebDAV connection
|
||||
struct dav_session_s dav_session; /* The DAV Session, initialised in dav_connect */
|
||||
int _connected; /* flag to indicate if a connection exists, ie.
|
||||
the dav_session is valid */
|
||||
};
|
||||
typedef struct csync_owncloud_ctx_s csync_owncloud_ctx_t;
|
||||
//typedef csync_owncloud_ctx_t* csync_owncloud_ctx_p;
|
||||
|
||||
enum resource_type {
|
||||
resr_normal = 0,
|
||||
resr_collection,
|
||||
resr_reference,
|
||||
resr_error
|
||||
};
|
||||
|
||||
/* The list of properties that is fetched in PropFind on a collection */
|
||||
static const ne_propname ls_props[] = {
|
||||
{ "DAV:", "getlastmodified" },
|
||||
{ "DAV:", "getcontentlength" },
|
||||
{ "DAV:", "resourcetype" },
|
||||
{ "DAV:", "getetag"},
|
||||
{ "http://owncloud.org/ns", "id"},
|
||||
{ "http://owncloud.org/ns", "dDU"},
|
||||
{ "http://owncloud.org/ns", "dDC"},
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* Struct to store data for each resource found during an opendir operation.
|
||||
* It represents a single file entry.
|
||||
*/
|
||||
typedef struct resource {
|
||||
char *uri; /* The complete uri */
|
||||
char *name; /* The filename only */
|
||||
|
||||
enum resource_type type;
|
||||
int64_t size;
|
||||
time_t modtime;
|
||||
char* md5;
|
||||
char file_id[FILE_ID_BUF_SIZE+1];
|
||||
// Those two are optional from the server. We can use those URL to download the file directly
|
||||
// without going through the ownCloud instance.
|
||||
char *directDownloadUrl;
|
||||
char *directDownloadCookies;
|
||||
|
||||
struct resource *next;
|
||||
} resource;
|
||||
|
||||
/* Struct to hold the context of a WebDAV PropFind operation to fetch
|
||||
* a directory listing from the server.
|
||||
*/
|
||||
struct listdir_context {
|
||||
struct resource *list; /* The list of result resources */
|
||||
struct resource *currResource; /* A pointer to the current resource */
|
||||
char *target; /* Request-URI of the PROPFIND */
|
||||
unsigned int result_count; /* number of elements stored in list */
|
||||
int ref; /* reference count, only destroy when it reaches 0 */
|
||||
};
|
||||
|
||||
|
||||
/* Values are propfind_recursive_element: */
|
||||
struct propfind_recursive_element {
|
||||
struct resource *self;
|
||||
struct resource *children;
|
||||
struct propfind_recursive_element *parent;
|
||||
};
|
||||
typedef struct propfind_recursive_element propfind_recursive_element_t;
|
||||
|
||||
void clear_propfind_recursive_cache(csync_owncloud_ctx_t *ctx);
|
||||
struct listdir_context *get_listdir_context_from_recursive_cache(csync_owncloud_ctx_t *ctx, const char *curi);
|
||||
void fill_recursive_propfind_cache(csync_owncloud_ctx_t *ctx, const char *uri, const char *curi);
|
||||
struct listdir_context *get_listdir_context_from_cache(csync_owncloud_ctx_t *ctx, const char *curi);
|
||||
void fetch_resource_list_recursive(csync_owncloud_ctx_t *ctx, const char *uri, const char *curi);
|
||||
|
||||
void set_errno_from_http_errcode( int err );
|
||||
void set_error_message( csync_owncloud_ctx_t *ctx, const char *msg );
|
||||
void set_errno_from_neon_errcode(csync_owncloud_ctx_t *ctx, int neon_code );
|
||||
int http_result_code_from_session(csync_owncloud_ctx_t *ctx);
|
||||
void set_errno_from_session(csync_owncloud_ctx_t *ctx);
|
||||
|
||||
time_t oc_httpdate_parse( const char *date );
|
||||
|
||||
char *_cleanPath( const char* uri );
|
||||
|
||||
int _stat_perms( int type );
|
||||
void resourceToFileStat( csync_vio_file_stat_t *lfs, struct resource *res );
|
||||
void resource_free(struct resource* o);
|
||||
struct resource* resource_dup(struct resource* o);
|
||||
void free_fetchCtx( struct listdir_context *ctx );
|
||||
|
||||
const char* csync_owncloud_get_platform(void);
|
||||
|
||||
#endif // CSYNC_OWNCLOUD_PRIVATE_H
|
||||
@@ -20,42 +20,7 @@
|
||||
*/
|
||||
|
||||
#include "csync_owncloud.h"
|
||||
|
||||
c_rbtree_t *propfind_recursive_cache = NULL;
|
||||
int propfind_recursive_cache_depth = 0;
|
||||
int propfind_recursive_cache_file_count = 0;
|
||||
int propfind_recursive_cache_folder_count = 0;
|
||||
|
||||
|
||||
static struct resource* resource_dup(struct resource* o) {
|
||||
struct resource *r = c_malloc (sizeof( struct resource ));
|
||||
ZERO_STRUCTP(r);
|
||||
|
||||
r->uri = c_strdup(o->uri);
|
||||
r->name = c_strdup(o->name);
|
||||
r->type = o->type;
|
||||
r->size = o->size;
|
||||
r->modtime = o->modtime;
|
||||
if( o->md5 ) {
|
||||
r->md5 = c_strdup(o->md5);
|
||||
}
|
||||
r->next = o->next;
|
||||
csync_vio_set_file_id(r->file_id, o->file_id);
|
||||
|
||||
return r;
|
||||
}
|
||||
static void resource_free(struct resource* o) {
|
||||
struct resource* old = NULL;
|
||||
while (o)
|
||||
{
|
||||
old = o;
|
||||
o = o->next;
|
||||
SAFE_FREE(old->uri);
|
||||
SAFE_FREE(old->name);
|
||||
SAFE_FREE(old->md5);
|
||||
SAFE_FREE(old);
|
||||
}
|
||||
}
|
||||
#include "csync_owncloud_private.h"
|
||||
|
||||
static void _tree_destructor(void *data) {
|
||||
propfind_recursive_element_t *element = data;
|
||||
@@ -64,27 +29,27 @@ static void _tree_destructor(void *data) {
|
||||
SAFE_FREE(element);
|
||||
}
|
||||
|
||||
void clear_propfind_recursive_cache(void)
|
||||
void clear_propfind_recursive_cache(csync_owncloud_ctx_t *ctx)
|
||||
{
|
||||
if (propfind_recursive_cache) {
|
||||
if (ctx->propfind_recursive_cache) {
|
||||
DEBUG_WEBDAV("clear_propfind_recursive_cache Invalidating..");
|
||||
c_rbtree_destroy(propfind_recursive_cache, _tree_destructor);
|
||||
propfind_recursive_cache = NULL;
|
||||
c_rbtree_destroy(ctx->propfind_recursive_cache, _tree_destructor);
|
||||
ctx->propfind_recursive_cache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct listdir_context *get_listdir_context_from_recursive_cache(const char *curi)
|
||||
struct listdir_context *get_listdir_context_from_recursive_cache(csync_owncloud_ctx_t *ctx, const char *curi)
|
||||
{
|
||||
propfind_recursive_element_t *element = NULL;
|
||||
struct listdir_context *fetchCtx = NULL;
|
||||
struct resource *iterator, *r;
|
||||
|
||||
if (!propfind_recursive_cache) {
|
||||
if (!ctx->propfind_recursive_cache) {
|
||||
DEBUG_WEBDAV("get_listdir_context_from_recursive_cache No cache");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
element = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache, curi));
|
||||
element = c_rbtree_node_data(c_rbtree_find(ctx->propfind_recursive_cache, curi));
|
||||
if (!element) {
|
||||
DEBUG_WEBDAV("get_listdir_context_from_recursive_cache No element %s in cache found", curi);
|
||||
return NULL;
|
||||
@@ -128,27 +93,29 @@ static int _data_cmp(const void *a, const void *b) {
|
||||
const propfind_recursive_element_t *elementB = b;
|
||||
return ne_path_compare(elementA->self->uri, elementB->self->uri);
|
||||
}
|
||||
static void propfind_results_recursive(void *userdata,
|
||||
static void propfind_results_recursive_callback(void *userdata,
|
||||
const ne_uri *uri,
|
||||
const ne_prop_result_set *set)
|
||||
{
|
||||
struct resource *newres = 0;
|
||||
const char *clength, *modtime, *file_id = NULL;
|
||||
const char *directDownloadUrl = NULL;
|
||||
const char *directDownloadCookies = NULL;
|
||||
const char *resourcetype = NULL;
|
||||
const char *md5sum = NULL;
|
||||
const ne_status *status = NULL;
|
||||
char *path = ne_path_unescape( uri->path );
|
||||
char *parentPath;
|
||||
char *propfindRootUri = (char*) userdata;
|
||||
propfind_recursive_element_t *element = NULL;
|
||||
propfind_recursive_element_t *pElement = NULL;
|
||||
int depth = 0;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
|
||||
|
||||
(void) status;
|
||||
(void) propfindRootUri;
|
||||
|
||||
if (!propfind_recursive_cache) {
|
||||
c_rbtree_create(&propfind_recursive_cache, _key_cmp, _data_cmp);
|
||||
if (!ctx->propfind_recursive_cache) {
|
||||
c_rbtree_create(&ctx->propfind_recursive_cache, _key_cmp, _data_cmp);
|
||||
}
|
||||
|
||||
/* Fill the resource structure with the data about the file */
|
||||
@@ -163,14 +130,16 @@ static void propfind_results_recursive(void *userdata,
|
||||
resourcetype = ne_propset_value( set, &ls_props[2] );
|
||||
md5sum = ne_propset_value( set, &ls_props[3] );
|
||||
file_id = ne_propset_value( set, &ls_props[4] );
|
||||
directDownloadUrl = ne_propset_value( set, &ls_props[5] );
|
||||
directDownloadCookies = ne_propset_value( set, &ls_props[6] );
|
||||
|
||||
newres->type = resr_normal;
|
||||
if( resourcetype && strncmp( resourcetype, "<DAV:collection>", 16 ) == 0) {
|
||||
newres->type = resr_collection;
|
||||
propfind_recursive_cache_folder_count++;
|
||||
ctx->propfind_recursive_cache_folder_count++;
|
||||
} else {
|
||||
/* DEBUG_WEBDAV("propfind_results_recursive %s [%d]", newres->uri, newres->type); */
|
||||
propfind_recursive_cache_file_count++;
|
||||
ctx->propfind_recursive_cache_file_count++;
|
||||
}
|
||||
|
||||
if (modtime) {
|
||||
@@ -193,18 +162,26 @@ static void propfind_results_recursive(void *userdata,
|
||||
DEBUG_WEBDAV("propfind_results_recursive %s [%s] %s", newres->uri, newres->type == resr_collection ? "collection" : "file", newres->md5);
|
||||
*/
|
||||
|
||||
if (directDownloadUrl) {
|
||||
newres->directDownloadUrl = c_strdup(directDownloadUrl);
|
||||
}
|
||||
if (directDownloadCookies) {
|
||||
newres->directDownloadCookies = c_strdup(directDownloadCookies);
|
||||
}
|
||||
|
||||
/* Create new item in rb tree */
|
||||
if (newres->type == resr_collection) {
|
||||
DEBUG_WEBDAV("propfind_results_recursive %s is a folder", newres->uri);
|
||||
/* Check if in rb tree */
|
||||
element = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache,uri->path));
|
||||
element = c_rbtree_node_data(c_rbtree_find(ctx->propfind_recursive_cache,uri->path));
|
||||
/* If not, create a new item and insert it */
|
||||
if (!element) {
|
||||
element = c_malloc(sizeof(propfind_recursive_element_t));
|
||||
element->self = resource_dup(newres);
|
||||
element->self->next = 0;
|
||||
element->children = NULL;
|
||||
element->parent = NULL;
|
||||
c_rbtree_insert(propfind_recursive_cache, element);
|
||||
c_rbtree_insert(ctx->propfind_recursive_cache, element);
|
||||
/* DEBUG_WEBDAV("results_recursive Added collection %s", newres->uri); */
|
||||
}
|
||||
}
|
||||
@@ -214,7 +191,7 @@ static void propfind_results_recursive(void *userdata,
|
||||
if (parentPath) {
|
||||
propfind_recursive_element_t *parentElement = NULL;
|
||||
|
||||
parentElement = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache,parentPath));
|
||||
parentElement = c_rbtree_node_data(c_rbtree_find(ctx->propfind_recursive_cache,parentPath));
|
||||
free(parentPath);
|
||||
|
||||
if (parentElement) {
|
||||
@@ -230,9 +207,9 @@ static void propfind_results_recursive(void *userdata,
|
||||
depth++;
|
||||
pElement = pElement->parent;
|
||||
}
|
||||
if (depth > propfind_recursive_cache_depth) {
|
||||
if (depth > ctx->propfind_recursive_cache_depth) {
|
||||
DEBUG_WEBDAV("propfind_results_recursive %s new maximum tree depth %d", newres->uri, depth);
|
||||
propfind_recursive_cache_depth = depth;
|
||||
ctx->propfind_recursive_cache_depth = depth;
|
||||
}
|
||||
|
||||
/* DEBUG_WEBDAV("results_recursive Added child %s to collection %s", newres->uri, element->self->uri); */
|
||||
@@ -245,7 +222,7 @@ static void propfind_results_recursive(void *userdata,
|
||||
|
||||
}
|
||||
|
||||
void fetch_resource_list_recursive(const char *uri, const char *curi)
|
||||
void fetch_resource_list_recursive(csync_owncloud_ctx_t *ctx, const char *uri, const char *curi)
|
||||
{
|
||||
int ret = 0;
|
||||
ne_propfind_handler *hdl = NULL;
|
||||
@@ -257,10 +234,10 @@ void fetch_resource_list_recursive(const char *uri, const char *curi)
|
||||
DEBUG_WEBDAV("fetch_resource_list_recursive Starting recursive propfind %s %s", uri, curi);
|
||||
|
||||
/* do a propfind request and parse the results in the results function, set as callback */
|
||||
hdl = ne_propfind_create(dav_session.ctx, curi, depth);
|
||||
hdl = ne_propfind_create(ctx->dav_session.ctx, curi, depth);
|
||||
|
||||
if(hdl) {
|
||||
ret = ne_propfind_named(hdl, ls_props, propfind_results_recursive, (void*)curi);
|
||||
ret = ne_propfind_named(hdl, ls_props, propfind_results_recursive_callback, ctx);
|
||||
request = ne_propfind_get_request( hdl );
|
||||
req_status = ne_get_status( request );
|
||||
}
|
||||
@@ -272,14 +249,14 @@ void fetch_resource_list_recursive(const char *uri, const char *curi)
|
||||
DEBUG_WEBDAV("ERROR: Request failed: status %d (%s)", req_status->code,
|
||||
req_status->reason_phrase);
|
||||
ret = NE_CONNECT;
|
||||
set_error_message(req_status->reason_phrase);
|
||||
set_error_message(ctx, req_status->reason_phrase);
|
||||
}
|
||||
DEBUG_WEBDAV("Recursive propfind result code %d.", req_status ? req_status->code : 0);
|
||||
} else {
|
||||
if( ret == NE_ERROR && req_status->code == 404) {
|
||||
errno = ENOENT;
|
||||
} else {
|
||||
set_errno_from_neon_errcode(ret);
|
||||
set_errno_from_neon_errcode(ctx, ret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,7 +271,7 @@ void fetch_resource_list_recursive(const char *uri, const char *curi)
|
||||
DEBUG_WEBDAV("ERROR: Content type of propfind request not XML: %s.",
|
||||
content_type ? content_type: "<empty>");
|
||||
errno = ERRNO_WRONG_CONTENT;
|
||||
set_error_message("Server error: PROPFIND reply is not XML formatted!");
|
||||
set_error_message(ctx, "Server error: PROPFIND reply is not XML formatted!");
|
||||
ret = NE_CONNECT;
|
||||
}
|
||||
}
|
||||
@@ -302,7 +279,7 @@ void fetch_resource_list_recursive(const char *uri, const char *curi)
|
||||
if( ret != NE_OK ) {
|
||||
const char *err = NULL;
|
||||
|
||||
err = ne_get_error( dav_session.ctx );
|
||||
err = ne_get_error( ctx->dav_session.ctx );
|
||||
DEBUG_WEBDAV("WRN: propfind named failed with %d, request error: %s", ret, err ? err : "<nil>");
|
||||
}
|
||||
|
||||
@@ -317,22 +294,21 @@ void fetch_resource_list_recursive(const char *uri, const char *curi)
|
||||
}
|
||||
|
||||
/* Called by owncloud_opendir()->fetch_resource_list() to fill the cache */
|
||||
extern struct listdir_context *propfind_cache;
|
||||
void fill_recursive_propfind_cache(const char *uri, const char *curi) {
|
||||
fetch_resource_list_recursive(uri, curi);
|
||||
void fill_recursive_propfind_cache(csync_owncloud_ctx_t *ctx, const char *uri, const char *curi) {
|
||||
fetch_resource_list_recursive(ctx, uri, curi);
|
||||
|
||||
if (propfind_recursive_cache_depth <= 2) {
|
||||
if (ctx->propfind_recursive_cache_depth <= 2) {
|
||||
DEBUG_WEBDAV("fill_recursive_propfind_cache %s Server maybe did not give us an 'infinity' depth result", curi);
|
||||
/* transform the cache to the normal cache in propfind_cache */
|
||||
propfind_cache = get_listdir_context_from_recursive_cache(curi);
|
||||
ctx->propfind_cache = get_listdir_context_from_recursive_cache(ctx, curi);
|
||||
/* clear the cache, it is bogus since the server returned only results for Depth 1 */
|
||||
clear_propfind_recursive_cache();
|
||||
clear_propfind_recursive_cache(ctx);
|
||||
} else {
|
||||
DEBUG_WEBDAV("fill_recursive_propfind_cache %s We received %d elements deep for 'infinity' depth (%d folders, %d files)",
|
||||
curi,
|
||||
propfind_recursive_cache_depth,
|
||||
propfind_recursive_cache_folder_count,
|
||||
propfind_recursive_cache_file_count);
|
||||
ctx->propfind_recursive_cache_depth,
|
||||
ctx->propfind_recursive_cache_folder_count,
|
||||
ctx->propfind_recursive_cache_file_count);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,13 +20,15 @@
|
||||
*/
|
||||
|
||||
#include "csync_owncloud.h"
|
||||
#include "csync_owncloud_private.h"
|
||||
|
||||
#include "csync_misc.h"
|
||||
|
||||
void set_error_message( const char *msg )
|
||||
void set_error_message( csync_owncloud_ctx_t *ctx, const char *msg )
|
||||
{
|
||||
SAFE_FREE(dav_session.error_string);
|
||||
SAFE_FREE(ctx->dav_session.error_string);
|
||||
if( msg )
|
||||
dav_session.error_string = c_strdup(msg);
|
||||
ctx->dav_session.error_string = c_strdup(msg);
|
||||
}
|
||||
|
||||
void set_errno_from_http_errcode( int err ) {
|
||||
@@ -104,12 +106,12 @@ void set_errno_from_http_errcode( int err ) {
|
||||
errno = new_errno;
|
||||
}
|
||||
|
||||
int http_result_code_from_session() {
|
||||
const char *p = ne_get_error( dav_session.ctx );
|
||||
int http_result_code_from_session(csync_owncloud_ctx_t *ctx) {
|
||||
const char *p = ne_get_error( ctx->dav_session.ctx );
|
||||
char *q;
|
||||
int err;
|
||||
|
||||
set_error_message(p); /* remember the error message */
|
||||
set_error_message(ctx, p); /* remember the error message */
|
||||
|
||||
err = strtol(p, &q, 10);
|
||||
if (p == q) {
|
||||
@@ -118,8 +120,8 @@ int http_result_code_from_session() {
|
||||
return err;
|
||||
}
|
||||
|
||||
void set_errno_from_session() {
|
||||
int err = http_result_code_from_session();
|
||||
void set_errno_from_session(csync_owncloud_ctx_t *ctx) {
|
||||
int err = http_result_code_from_session(ctx);
|
||||
|
||||
if( err == EIO || err == ERRNO_ERROR_STRING) {
|
||||
errno = err;
|
||||
@@ -128,7 +130,7 @@ void set_errno_from_session() {
|
||||
}
|
||||
}
|
||||
|
||||
void set_errno_from_neon_errcode( int neon_code ) {
|
||||
void set_errno_from_neon_errcode(csync_owncloud_ctx_t *ctx, int neon_code ) {
|
||||
|
||||
if( neon_code != NE_OK ) {
|
||||
DEBUG_WEBDAV("Neon error code was %d", neon_code);
|
||||
@@ -137,7 +139,7 @@ void set_errno_from_neon_errcode( int neon_code ) {
|
||||
switch(neon_code) {
|
||||
case NE_OK: /* Success, but still the possiblity of problems */
|
||||
case NE_ERROR: /* Generic error; use ne_get_error(session) for message */
|
||||
set_errno_from_session(); /* Something wrong with http communication */
|
||||
set_errno_from_session(ctx); /* Something wrong with http communication */
|
||||
break;
|
||||
case NE_LOOKUP: /* Server or proxy hostname lookup failed */
|
||||
errno = ERRNO_LOOKUP_ERROR;
|
||||
@@ -279,19 +281,9 @@ time_t oc_httpdate_parse( const char *date ) {
|
||||
/*
|
||||
* helper: convert a resource struct to file_stat struct.
|
||||
*/
|
||||
csync_vio_file_stat_t *resourceToFileStat( struct resource *res )
|
||||
void resourceToFileStat(csync_vio_file_stat_t *lfs, struct resource *res )
|
||||
{
|
||||
csync_vio_file_stat_t *lfs = NULL;
|
||||
|
||||
if( ! res ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lfs = c_malloc(sizeof(csync_vio_file_stat_t));
|
||||
if (lfs == NULL) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
ZERO_STRUCTP(lfs);
|
||||
|
||||
lfs->name = c_strdup( res->name );
|
||||
|
||||
@@ -306,17 +298,29 @@ csync_vio_file_stat_t *resourceToFileStat( struct resource *res )
|
||||
DEBUG_WEBDAV("ERROR: Unknown resource type %d", res->type);
|
||||
}
|
||||
|
||||
// FIXME Those are defaults, we'll have to use the real ownCloud WebDAV permissions soon
|
||||
lfs->mode = _stat_perms( lfs->type );
|
||||
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS;
|
||||
|
||||
lfs->mtime = res->modtime;
|
||||
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;
|
||||
lfs->size = res->size;
|
||||
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
|
||||
if( res->md5 ) {
|
||||
lfs->etag = c_strdup(res->md5);
|
||||
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG;
|
||||
}
|
||||
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG;
|
||||
|
||||
csync_vio_file_stat_set_file_id(lfs, res->file_id);
|
||||
|
||||
return lfs;
|
||||
if (res->directDownloadUrl) {
|
||||
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADURL;
|
||||
lfs->directDownloadUrl = c_strdup(res->directDownloadUrl);
|
||||
}
|
||||
if (res->directDownloadCookies) {
|
||||
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADCOOKIES;
|
||||
lfs->directDownloadCookies = c_strdup(res->directDownloadCookies);
|
||||
}
|
||||
}
|
||||
|
||||
/* WebDAV does not deliver permissions. Set a default here. */
|
||||
@@ -339,3 +343,93 @@ int _stat_perms( int type ) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct resource* resource_dup(struct resource* o) {
|
||||
struct resource *r = c_malloc (sizeof( struct resource ));
|
||||
ZERO_STRUCTP(r);
|
||||
|
||||
r->uri = c_strdup(o->uri);
|
||||
r->name = c_strdup(o->name);
|
||||
r->type = o->type;
|
||||
r->size = o->size;
|
||||
r->modtime = o->modtime;
|
||||
if( o->md5 ) {
|
||||
r->md5 = c_strdup(o->md5);
|
||||
}
|
||||
if (o->directDownloadUrl) {
|
||||
r->directDownloadUrl = c_strdup(o->directDownloadUrl);
|
||||
}
|
||||
if (o->directDownloadCookies) {
|
||||
r->directDownloadCookies = c_strdup(o->directDownloadCookies);
|
||||
}
|
||||
r->next = o->next;
|
||||
csync_vio_set_file_id(r->file_id, o->file_id);
|
||||
|
||||
return r;
|
||||
}
|
||||
void resource_free(struct resource* o) {
|
||||
struct resource* old = NULL;
|
||||
while (o)
|
||||
{
|
||||
old = o;
|
||||
o = o->next;
|
||||
SAFE_FREE(old->uri);
|
||||
SAFE_FREE(old->name);
|
||||
SAFE_FREE(old->md5);
|
||||
SAFE_FREE(old->directDownloadUrl);
|
||||
SAFE_FREE(old->directDownloadCookies);
|
||||
SAFE_FREE(old);
|
||||
}
|
||||
}
|
||||
|
||||
void free_fetchCtx( struct listdir_context *ctx )
|
||||
{
|
||||
struct resource *newres, *res;
|
||||
if( ! ctx ) return;
|
||||
newres = ctx->list;
|
||||
res = newres;
|
||||
|
||||
ctx->ref--;
|
||||
if (ctx->ref > 0) return;
|
||||
|
||||
SAFE_FREE(ctx->target);
|
||||
|
||||
while( res ) {
|
||||
SAFE_FREE(res->uri);
|
||||
SAFE_FREE(res->name);
|
||||
SAFE_FREE(res->md5);
|
||||
memset( res->file_id, 0, FILE_ID_BUF_SIZE+1 );
|
||||
SAFE_FREE(res->directDownloadUrl);
|
||||
SAFE_FREE(res->directDownloadCookies);
|
||||
|
||||
newres = res->next;
|
||||
SAFE_FREE(res);
|
||||
res = newres;
|
||||
}
|
||||
SAFE_FREE(ctx);
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
@@ -61,18 +61,6 @@
|
||||
*/
|
||||
#define MAX_DEPTH 50
|
||||
|
||||
/**
|
||||
* Maximum time difference between two replicas in seconds
|
||||
*/
|
||||
#define MAX_TIME_DIFFERENCE 10
|
||||
|
||||
/**
|
||||
* Maximum size of a buffer for transfer
|
||||
*/
|
||||
#ifndef MAX_XFER_BUF_SIZE
|
||||
#define MAX_XFER_BUF_SIZE (16 * 1024)
|
||||
#endif
|
||||
|
||||
#define CSYNC_STATUS_INIT 1 << 0
|
||||
#define CSYNC_STATUS_UPDATE 1 << 1
|
||||
#define CSYNC_STATUS_RECONCILE 1 << 2
|
||||
@@ -90,6 +78,8 @@ enum csync_replica_e {
|
||||
|
||||
typedef struct csync_file_stat_s csync_file_stat_t;
|
||||
|
||||
struct csync_owncloud_ctx_s; // csync_owncloud.c
|
||||
|
||||
/**
|
||||
* @brief csync public structure
|
||||
*/
|
||||
@@ -130,8 +120,6 @@ struct csync_s {
|
||||
|
||||
struct {
|
||||
int sync_symbolic_links;
|
||||
char *config_dir;
|
||||
bool local_only_mode;
|
||||
int timeout;
|
||||
#if defined(HAVE_ICONV) && defined(WITH_ICONV)
|
||||
iconv_t iconv_cd;
|
||||
@@ -162,6 +150,8 @@ struct csync_s {
|
||||
volatile int abort;
|
||||
void *rename_info;
|
||||
int read_from_db_disabled;
|
||||
|
||||
struct csync_owncloud_ctx_s *owncloud_context;
|
||||
};
|
||||
|
||||
|
||||
@@ -185,6 +175,9 @@ struct csync_file_stat_s {
|
||||
char *destpath; /* for renames */
|
||||
const char *etag;
|
||||
char file_id[FILE_ID_BUF_SIZE+1]; /* the ownCloud file id is fixed width of 21 byte. */
|
||||
char *directDownloadUrl;
|
||||
char *directDownloadCookies;
|
||||
|
||||
CSYNC_STATUS error_status;
|
||||
|
||||
enum csync_instructions_e instruction; /* u32 */
|
||||
|
||||
@@ -249,8 +249,12 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) {
|
||||
cur->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
other->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
|
||||
if( !cur->etag && other->etag ) cur->etag = c_strdup(other->etag);
|
||||
cur->should_update_etag = true; /* update DB */
|
||||
/* update DB with new etag from remote */
|
||||
if (ctx->current == LOCAL_REPLICA) {
|
||||
other->should_update_etag = true;
|
||||
} else {
|
||||
cur->should_update_etag = true;
|
||||
}
|
||||
} else if(ctx->current == REMOTE_REPLICA) {
|
||||
cur->instruction = CSYNC_INSTRUCTION_CONFLICT;
|
||||
other->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "csync_private.h"
|
||||
@@ -57,29 +58,6 @@ int csync_get_statedb_exists(CSYNC *ctx) {
|
||||
return ctx->statedb.exists;
|
||||
}
|
||||
|
||||
/* Set the hide attribute in win32. That makes it invisible in normal explorers */
|
||||
static void _csync_win32_hide_file( const char *file ) {
|
||||
#ifdef _WIN32
|
||||
mbchar_t *fileName;
|
||||
DWORD dwAttrs;
|
||||
|
||||
if( !file ) return;
|
||||
|
||||
fileName = c_utf8_to_locale( file );
|
||||
dwAttrs = GetFileAttributesW(fileName);
|
||||
|
||||
if (dwAttrs==INVALID_FILE_ATTRIBUTES) return;
|
||||
|
||||
if (!(dwAttrs & FILE_ATTRIBUTE_HIDDEN)) {
|
||||
SetFileAttributesW(fileName, dwAttrs | FILE_ATTRIBUTE_HIDDEN );
|
||||
}
|
||||
|
||||
c_free_locale_string(fileName);
|
||||
#else
|
||||
(void) file;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int _csync_check_db_integrity(sqlite3 *db) {
|
||||
c_strlist_t *result = NULL;
|
||||
int rc = -1;
|
||||
@@ -166,7 +144,7 @@ static int _csync_statedb_check(const char *statedb) {
|
||||
rc = sqlite3_open(statedb, &db);
|
||||
if (rc == SQLITE_OK) {
|
||||
sqlite3_close(db);
|
||||
_csync_win32_hide_file(statedb);
|
||||
csync_win32_set_file_hidden(statedb, true);
|
||||
return 1;
|
||||
}
|
||||
sqlite3_close(db);
|
||||
@@ -529,7 +507,7 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
||||
if( rc != SQLITE_DONE ) {
|
||||
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
|
||||
} else {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "%ld entries read below path %s from db.", cnt, path);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "%" PRId64 " entries read below path %s from db.", cnt, path);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
SAFE_FREE(likepath);
|
||||
|
||||
@@ -361,8 +361,6 @@ out:
|
||||
st->mode = fs->mode;
|
||||
st->size = fs->size;
|
||||
st->modtime = fs->mtime;
|
||||
st->uid = fs->uid;
|
||||
st->gid = fs->gid;
|
||||
st->nlink = fs->nlink;
|
||||
st->type = type;
|
||||
st->etag = NULL;
|
||||
@@ -371,6 +369,15 @@ out:
|
||||
st->etag = c_strdup(fs->etag);
|
||||
}
|
||||
csync_vio_set_file_id(st->file_id, fs->file_id);
|
||||
if (fs->fields & CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADURL) {
|
||||
SAFE_FREE(st->directDownloadUrl);
|
||||
st->directDownloadUrl = c_strdup(fs->directDownloadUrl);
|
||||
}
|
||||
if (fs->fields & CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADCOOKIES) {
|
||||
SAFE_FREE(st->directDownloadCookies);
|
||||
st->directDownloadCookies = c_strdup(fs->directDownloadCookies);
|
||||
}
|
||||
|
||||
|
||||
fastout: /* target if the file information is read from database into st */
|
||||
st->phash = h;
|
||||
@@ -586,9 +593,14 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
continue;
|
||||
}
|
||||
|
||||
/* == see if really stat has to be called. */
|
||||
fs = csync_vio_file_stat_new();
|
||||
res = csync_vio_stat(ctx, filename, fs);
|
||||
/* Only for the local replica we have to stat(), for the remote one we have all data already */
|
||||
if (ctx->replica == LOCAL_REPLICA) {
|
||||
fs = csync_vio_file_stat_new();
|
||||
res = csync_vio_stat(ctx, filename, fs);
|
||||
} else {
|
||||
fs = dirent;
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if( res == 0) {
|
||||
switch (fs->type) {
|
||||
@@ -643,7 +655,10 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
previous_fs->child_modified = ctx->current_fs->child_modified;
|
||||
}
|
||||
|
||||
csync_vio_file_stat_destroy(fs);
|
||||
/* Only for the local replica we have to destroy stat(), for the remote one it is a pointer to dirent */
|
||||
if (ctx->replica == LOCAL_REPLICA) {
|
||||
csync_vio_file_stat_destroy(fs);
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
if (CSYNC_STATUS_IS_OK(ctx->status_code)) {
|
||||
|
||||
@@ -128,59 +128,6 @@ void csync_win32_set_file_hidden( const char *file, bool h ) {
|
||||
#endif
|
||||
}
|
||||
|
||||
csync_vio_file_stat_t *csync_vio_convert_file_stat(csync_file_stat_t *st) {
|
||||
csync_vio_file_stat_t *vfs = NULL;
|
||||
|
||||
if (st == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vfs = csync_vio_file_stat_new();
|
||||
if (vfs == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
vfs->acl = NULL;
|
||||
if (st->pathlen > 0) {
|
||||
vfs->name = c_strdup(st->path);
|
||||
}
|
||||
vfs->uid = st->uid;
|
||||
vfs->gid = st->gid;
|
||||
|
||||
vfs->atime = 0;
|
||||
vfs->mtime = st->modtime;
|
||||
vfs->ctime = 0;
|
||||
|
||||
vfs->size = st->size;
|
||||
vfs->blksize = 0; /* Depricated. */
|
||||
vfs->blkcount = 0;
|
||||
|
||||
vfs->mode = st->mode;
|
||||
vfs->device = 0;
|
||||
vfs->inode = st->inode;
|
||||
vfs->nlink = st->nlink;
|
||||
|
||||
/* fields. */
|
||||
vfs->fields = CSYNC_VIO_FILE_STAT_FIELDS_TYPE
|
||||
+ CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS
|
||||
+ CSYNC_VIO_FILE_STAT_FIELDS_INODE
|
||||
+ CSYNC_VIO_FILE_STAT_FIELDS_LINK_COUNT
|
||||
+ CSYNC_VIO_FILE_STAT_FIELDS_SIZE
|
||||
+ CSYNC_VIO_FILE_STAT_FIELDS_MTIME
|
||||
+ CSYNC_VIO_FILE_STAT_FIELDS_UID
|
||||
+ CSYNC_VIO_FILE_STAT_FIELDS_GID;
|
||||
|
||||
if (st->type == CSYNC_FTW_TYPE_DIR)
|
||||
vfs->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
|
||||
else if (st->type == CSYNC_FTW_TYPE_FILE)
|
||||
vfs->type = CSYNC_VIO_FILE_TYPE_REGULAR;
|
||||
else if (st->type == CSYNC_FTW_TYPE_SLINK)
|
||||
vfs->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK;
|
||||
else
|
||||
vfs->type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
|
||||
|
||||
return vfs;
|
||||
}
|
||||
|
||||
bool (*csync_file_locked_or_open_ext) (const char*) = 0; // filled in by library user
|
||||
void set_csync_file_locked_or_open_ext(bool (*f) (const char*));
|
||||
void set_csync_file_locked_or_open_ext(bool (*f) (const char*)) {
|
||||
|
||||
@@ -32,8 +32,5 @@ void csync_memstat_check(void);
|
||||
|
||||
void csync_win32_set_file_hidden( const char *file, bool hidden );
|
||||
|
||||
/* Convert a csync_file_stat_t to csync_vio_file_stat_t */
|
||||
csync_vio_file_stat_t *csync_vio_convert_file_stat(csync_file_stat_t *st);
|
||||
|
||||
bool csync_file_locked_or_open( const char *dir, const char *fname);
|
||||
#endif /* _CSYNC_UTIL_H */
|
||||
|
||||
@@ -20,8 +20,6 @@ set(CSTDLIB_LINK_LIBRARIES
|
||||
|
||||
set(cstdlib_SRCS
|
||||
c_alloc.c
|
||||
c_dir.c
|
||||
c_file.c
|
||||
c_list.c
|
||||
c_path.c
|
||||
c_rbtree.c
|
||||
|
||||
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* cynapses libc functions
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* 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 <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "c_private.h"
|
||||
#include "c_macro.h"
|
||||
#include "c_alloc.h"
|
||||
#include "c_dir.h"
|
||||
#include "c_string.h"
|
||||
|
||||
int c_mkdirs(const char *path, mode_t mode) {
|
||||
int tmp;
|
||||
csync_stat_t sb;
|
||||
mbchar_t *wpath = c_utf8_to_locale(path);
|
||||
mbchar_t *swpath = NULL;
|
||||
|
||||
if (path == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_tstat(wpath, &sb) == 0) {
|
||||
if (! S_ISDIR(sb.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
c_free_locale_string(wpath);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
tmp = strlen(path);
|
||||
while(tmp > 0 && path[tmp - 1] == '/') --tmp;
|
||||
while(tmp > 0 && path[tmp - 1] != '/') --tmp;
|
||||
while(tmp > 0 && path[tmp - 1] == '/') --tmp;
|
||||
|
||||
if (tmp > 0) {
|
||||
char subpath[tmp + 1];
|
||||
memcpy(subpath, path, tmp);
|
||||
subpath[tmp] = '\0';
|
||||
swpath = c_utf8_to_locale(subpath);
|
||||
if (_tstat(swpath, &sb) == 0) {
|
||||
if (! S_ISDIR(sb.st_mode)) {
|
||||
c_free_locale_string(swpath);
|
||||
c_free_locale_string(wpath);
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
}
|
||||
} else if (errno != ENOENT) {
|
||||
c_free_locale_string(wpath);
|
||||
c_free_locale_string(swpath);
|
||||
return -1;
|
||||
} else if (c_mkdirs(subpath, mode) < 0) {
|
||||
c_free_locale_string(swpath);
|
||||
c_free_locale_string(wpath);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
tmp = _tmkdir(wpath, mode);
|
||||
|
||||
c_free_locale_string(swpath);
|
||||
c_free_locale_string(wpath);
|
||||
|
||||
if ((tmp < 0) && (errno == EEXIST)) {
|
||||
return 0;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
int c_rmdirs(const char *path) {
|
||||
_TDIR *d;
|
||||
struct _tdirent *dp;
|
||||
csync_stat_t sb;
|
||||
char *fname = NULL;
|
||||
mbchar_t *wfname = NULL;
|
||||
mbchar_t *wpath = c_utf8_to_locale(path);
|
||||
char *rd_name = NULL;
|
||||
|
||||
if ((d = _topendir(wpath)) != NULL) {
|
||||
while( _tstat(wpath, &sb) == 0) {
|
||||
/* if we can remove the directory we're done */
|
||||
if (_trmdir(wpath) == 0) {
|
||||
break;
|
||||
}
|
||||
switch (errno) {
|
||||
case ENOTEMPTY:
|
||||
case EEXIST:
|
||||
case EBADF:
|
||||
break; /* continue */
|
||||
default:
|
||||
_tclosedir(d);
|
||||
c_free_locale_string(wpath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((dp = _treaddir(d)) != NULL) {
|
||||
size_t len;
|
||||
rd_name = c_utf8_from_locale(dp->d_name);
|
||||
/* skip '.' and '..' */
|
||||
if( c_streq( rd_name, "." ) || c_streq( rd_name, ".." ) ) {
|
||||
c_free_locale_string(rd_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
len = strlen(path) + strlen(rd_name) + 2;
|
||||
fname = c_malloc(len);
|
||||
if (fname == NULL) {
|
||||
_tclosedir(d);
|
||||
c_free_locale_string(rd_name);
|
||||
c_free_locale_string(wpath);
|
||||
return -1;
|
||||
}
|
||||
snprintf(fname, len, "%s/%s", path, rd_name);
|
||||
wfname = c_utf8_to_locale(fname);
|
||||
|
||||
/* stat the file */
|
||||
if (_tstat(wfname, &sb) != -1) {
|
||||
#ifdef __unix__
|
||||
if (S_ISDIR(sb.st_mode) && !S_ISLNK(sb.st_mode)) {
|
||||
#else
|
||||
if (S_ISDIR(sb.st_mode)) {
|
||||
#endif
|
||||
if (_trmdir(wfname) < 0) { /* can't be deleted */
|
||||
if (errno == EACCES) {
|
||||
_tclosedir(d);
|
||||
SAFE_FREE(fname);
|
||||
c_free_locale_string(wfname);
|
||||
c_free_locale_string(rd_name);
|
||||
c_free_locale_string(wpath);
|
||||
return -1;
|
||||
}
|
||||
c_rmdirs(fname);
|
||||
}
|
||||
} else {
|
||||
_tunlink(wfname);
|
||||
}
|
||||
} /* lstat */
|
||||
SAFE_FREE(fname);
|
||||
c_free_locale_string(wfname);
|
||||
c_free_locale_string(rd_name);
|
||||
} /* readdir */
|
||||
|
||||
_trewinddir(d);
|
||||
}
|
||||
} else {
|
||||
c_free_locale_string(wpath);
|
||||
return -1;
|
||||
}
|
||||
c_free_locale_string(wpath);
|
||||
_tclosedir(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int c_isdir(const char *path) {
|
||||
csync_stat_t sb;
|
||||
mbchar_t *wpath = c_utf8_to_locale(path);
|
||||
int re = 0;
|
||||
|
||||
if (path != NULL) {
|
||||
if (_tstat (wpath, &sb) == 0 && S_ISDIR(sb.st_mode)) {
|
||||
re = 1;
|
||||
}
|
||||
}
|
||||
c_free_locale_string(wpath);
|
||||
return re;
|
||||
}
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* cynapses libc functions
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c_dir.h
|
||||
*
|
||||
* @brief Interface of the cynapses libc directory function
|
||||
*
|
||||
* @defgroup cynDirInternals cynapses libc directory functions
|
||||
* @ingroup cynLibraryAPI
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _C_DIR_H
|
||||
#define _C_DIR_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create parent directories as needed.
|
||||
*
|
||||
* The newly created directory will be owned by the effective user ID of the
|
||||
* process.
|
||||
*
|
||||
* @param path The path to the directory to create.
|
||||
*
|
||||
* @param mode Specifies the permissions to use. It is modified
|
||||
* by the process's umask in the usual way: the
|
||||
* permissions of the created file are (mode & ~umask).
|
||||
*
|
||||
* @return 0 on success, < 0 on error with errno set:
|
||||
* - EACCES The parent directory does not allow write
|
||||
* permission to the process, or one of the directories
|
||||
* - ENOTDIR if durl is not a directory
|
||||
* - EINVAL NULL durl passed or smbc_init not called.
|
||||
* - ENOMEM Insufficient memory was available.
|
||||
*
|
||||
* @see mkdir()
|
||||
*/
|
||||
int c_mkdirs(const char *path, mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Remove the directory and subdirectories including the content.
|
||||
*
|
||||
* This removes all directories and files recursivly.
|
||||
*
|
||||
* @param dir The directory to remove recusively.
|
||||
*
|
||||
* @return 0 on success, < 0 on error with errno set.
|
||||
*/
|
||||
int c_rmdirs(const char *dir);
|
||||
|
||||
/**
|
||||
* @brief Check if a path is a directory.
|
||||
*
|
||||
* @param path The path to check.
|
||||
*
|
||||
* @return 1 if the path is a directory, 0 if the path doesn't exist, is a
|
||||
* file or can't be accessed.
|
||||
*/
|
||||
int c_isdir(const char *path);
|
||||
|
||||
/**
|
||||
* }@
|
||||
*/
|
||||
#endif /* _CDIR_H */
|
||||
|
||||
@@ -1,346 +0,0 @@
|
||||
/*
|
||||
* cynapses libc functions
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
* Copyright (c) 2012-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
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "c_file.h"
|
||||
#include "c_string.h"
|
||||
|
||||
#include "c_private.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
/* check if path is a symlink */
|
||||
int c_islink(const char *path) {
|
||||
int re = 0;
|
||||
|
||||
mbchar_t *wpath = 0;
|
||||
DWORD dwAttrs;
|
||||
WIN32_FIND_DATAW FindFileData;
|
||||
HANDLE hFind;
|
||||
|
||||
wpath = c_utf8_to_locale(path);
|
||||
|
||||
dwAttrs = GetFileAttributesW(wpath);
|
||||
if (dwAttrs != INVALID_FILE_ATTRIBUTES) {
|
||||
|
||||
if ((dwAttrs & FILE_ATTRIBUTE_REPARSE_POINT)) {
|
||||
hFind = FindFirstFileW(wpath, &FindFileData );
|
||||
if (hFind != INVALID_HANDLE_VALUE) {
|
||||
if( (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
|
||||
(FindFileData.dwReserved0 & IO_REPARSE_TAG_SYMLINK) ) {
|
||||
re = 1;
|
||||
}
|
||||
}
|
||||
FindClose(hFind);
|
||||
}
|
||||
}
|
||||
c_free_locale_string(wpath);
|
||||
return re;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check if path is a file */
|
||||
int c_isfile(const char *path) {
|
||||
csync_stat_t sb;
|
||||
mbchar_t *wpath = c_utf8_to_locale(path);
|
||||
|
||||
int re = _tstat(wpath, &sb);
|
||||
c_free_locale_string(wpath);
|
||||
|
||||
if (re< 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __unix__
|
||||
if (S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode)) {
|
||||
#else
|
||||
if (S_ISREG(sb.st_mode)) {
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* copy file from src to dst, overwrites dst */
|
||||
#ifdef _WIN32
|
||||
int c_copy(const char* src, const char *dst, mode_t mode) {
|
||||
int rc = -1;
|
||||
mbchar_t *wsrc = 0;
|
||||
mbchar_t *wdst = 0;
|
||||
(void) mode; /* unused on win32 */
|
||||
if(src && dst) {
|
||||
wsrc = c_utf8_to_locale(src);
|
||||
wdst = c_utf8_to_locale(dst);
|
||||
if (CopyFileW(wsrc, wdst, FALSE)) {
|
||||
rc = 0;
|
||||
}
|
||||
c_free_locale_string(wsrc);
|
||||
c_free_locale_string(wdst);
|
||||
if( rc < 0 ) {
|
||||
errno = GetLastError();
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#else
|
||||
int c_copy(const char* src, const char *dst, mode_t mode) {
|
||||
int srcfd = -1;
|
||||
int dstfd = -1;
|
||||
int rc = -1;
|
||||
ssize_t bread, bwritten;
|
||||
csync_stat_t sb;
|
||||
char buf[4096];
|
||||
|
||||
if (c_streq(src, dst)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
srcfd = open(src, O_RDONLY, 0);
|
||||
if (srcfd < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = _tfstat(srcfd, &sb);
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (S_ISDIR(sb.st_mode)) {
|
||||
errno = EISDIR;
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mode == 0) {
|
||||
mode = sb.st_mode;
|
||||
}
|
||||
|
||||
dstfd = open(dst, O_CREAT|O_WRONLY|O_TRUNC, mode);
|
||||
if (dstfd < 0) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = _tfstat(dstfd, &sb);
|
||||
if (rc == 0) {
|
||||
if (S_ISDIR(sb.st_mode)) {
|
||||
errno = EISDIR;
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
bread = read(srcfd, buf, sizeof(buf));
|
||||
if (bread == 0) {
|
||||
/* done */
|
||||
break;
|
||||
} else if (bread < 0) {
|
||||
errno = ENODATA;
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bwritten = write(dstfd, buf, bread);
|
||||
if (bwritten < 0) {
|
||||
errno = ENODATA;
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bread != bwritten) {
|
||||
errno = EFAULT;
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __unix__
|
||||
fsync(dstfd);
|
||||
#endif
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
if (srcfd >= 0) {
|
||||
close(srcfd);
|
||||
}
|
||||
if (dstfd >= 0) {
|
||||
close(dstfd);
|
||||
}
|
||||
if (rc < 0 && c_isfile(dst)) {
|
||||
unlink(dst);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
int c_rename( const char *src, const char *dst ) {
|
||||
mbchar_t *nuri = NULL;
|
||||
mbchar_t *ouri = NULL;
|
||||
int rc = 0;
|
||||
|
||||
nuri = c_utf8_to_locale(dst);
|
||||
if (nuri == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ouri = c_utf8_to_locale(src);
|
||||
if (ouri == NULL) {
|
||||
c_free_locale_string(nuri);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
#define MAX_TRIES_RENAME 3
|
||||
int err = 0;
|
||||
int cnt = 0;
|
||||
|
||||
do {
|
||||
BOOL ok;
|
||||
ok = MoveFileExW(ouri,
|
||||
nuri,
|
||||
MOVEFILE_COPY_ALLOWED +
|
||||
MOVEFILE_REPLACE_EXISTING +
|
||||
MOVEFILE_WRITE_THROUGH);
|
||||
if (!ok) {
|
||||
/* error */
|
||||
err = GetLastError();
|
||||
if( (err == ERROR_ACCESS_DENIED ||
|
||||
err == ERROR_LOCK_VIOLATION ||
|
||||
err == ERROR_SHARING_VIOLATION) && cnt < MAX_TRIES_RENAME ) {
|
||||
cnt++;
|
||||
Sleep(cnt*100);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} while( 1 );
|
||||
if( err != 0 ) {
|
||||
errno = err;
|
||||
rc = -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
rc = rename(ouri, nuri);
|
||||
#endif
|
||||
|
||||
c_free_locale_string(nuri);
|
||||
c_free_locale_string(ouri);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int c_compare_file( const char *f1, const char *f2 ) {
|
||||
mbchar_t *wf1, *wf2;
|
||||
int fd1 = -1, fd2 = -1;
|
||||
size_t size1, size2;
|
||||
char buffer1[BUFFER_SIZE];
|
||||
char buffer2[BUFFER_SIZE];
|
||||
csync_stat_t stat1;
|
||||
csync_stat_t stat2;
|
||||
|
||||
int rc = -1;
|
||||
|
||||
if(f1 == NULL || f2 == NULL) return -1;
|
||||
|
||||
wf1 = c_utf8_to_locale(f1);
|
||||
if(wf1 == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
wf2 = c_utf8_to_locale(f2);
|
||||
if(wf2 == NULL) {
|
||||
c_free_locale_string(wf1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
_fmode = _O_BINARY;
|
||||
#endif
|
||||
|
||||
fd1 = _topen(wf1, O_RDONLY);
|
||||
if(fd1 < 0) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd2 = _topen(wf2, O_RDONLY);
|
||||
if(fd2 < 0) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* compare size first. */
|
||||
rc = _tfstat(fd1, &stat1);
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = _tfstat(fd2, &stat2);
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* if sizes are different, the files can not be equal. */
|
||||
if (stat1.st_size != stat2.st_size) {
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
while( (size1 = read(fd1, buffer1, BUFFER_SIZE)) > 0 ) {
|
||||
size2 = read( fd2, buffer2, BUFFER_SIZE );
|
||||
|
||||
if( size1 != size2 ) {
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
if(memcmp(buffer1, buffer2, size1) != 0) {
|
||||
/* buffers are different */
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
rc = 1;
|
||||
|
||||
out:
|
||||
|
||||
if(fd1 > -1) close(fd1);
|
||||
if(fd2 > -1) close(fd2);
|
||||
|
||||
c_free_locale_string( wf1 );
|
||||
c_free_locale_string( wf2 );
|
||||
return rc;
|
||||
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* cynapses libc functions
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
* Copyright (c) 2012-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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c_file.h
|
||||
*
|
||||
* @brief Interface of the cynapses libc file function
|
||||
*
|
||||
* @defgroup cynFileInternals cynapses libc file functions
|
||||
* @ingroup cynLibraryAPI
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _C_FILE_H
|
||||
#define _C_FILE_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef BUFFER_SIZE
|
||||
#define BUFFER_SIZE (16 * 1024)
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
/**
|
||||
* @brief Check if a path is a link.
|
||||
*
|
||||
* @param path The path to check.
|
||||
*
|
||||
* @return 1 if the path is a symbolic link, 0 if the path doesn't
|
||||
* exist or is something else.
|
||||
*/
|
||||
int c_islink(const char *path);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Check if a path is a regular file or a link.
|
||||
*
|
||||
* @param path The path to check.
|
||||
*
|
||||
* @return 1 if the path is a file, 0 if the path doesn't exist, is
|
||||
* something else or can't be accessed.
|
||||
*/
|
||||
int c_isfile(const char *path);
|
||||
|
||||
/**
|
||||
* @brief copy a file from source to destination.
|
||||
*
|
||||
* @param src Path to the source file
|
||||
* @param dst Path to the destination file
|
||||
* @param mode File creation mode of the destination. If mode is 0 then the
|
||||
* mode from the source will be used.
|
||||
*
|
||||
* @return 0 on success, less than 0 on error with errno set.
|
||||
* EISDIR if src or dst is a file.
|
||||
*/
|
||||
int c_copy(const char *src, const char *dst, mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Compare the content of two files byte by byte.
|
||||
* @param f1 Path of file 1
|
||||
* @param f2 Path of file 2
|
||||
*
|
||||
* @return 0 if the files differ, 1 if the files are equal or -1 on
|
||||
* error with errno set.
|
||||
*/
|
||||
int c_compare_file( const char *f1, const char *f2 );
|
||||
|
||||
/**
|
||||
* @brief move a file from source to destination.
|
||||
*
|
||||
* @param src Path to the source file
|
||||
* @param dst Path to the destination file
|
||||
*
|
||||
* @return 0 on success, less than 0 on error with errno set.
|
||||
*/
|
||||
int c_rename( const char *src, const char *dst );
|
||||
|
||||
/**
|
||||
* }@
|
||||
*/
|
||||
#endif /* _C_FILE_H */
|
||||
|
||||
@@ -23,45 +23,9 @@
|
||||
|
||||
#include "c_macro.h"
|
||||
#include "c_alloc.h"
|
||||
#include "c_dir.h"
|
||||
#include "c_file.h"
|
||||
#include "c_list.h"
|
||||
#include "c_path.h"
|
||||
#include "c_rbtree.h"
|
||||
#include "c_string.h"
|
||||
#include "c_time.h"
|
||||
#include "c_private.h"
|
||||
|
||||
#ifndef UNIT_TESTING
|
||||
#ifdef malloc
|
||||
#undef malloc
|
||||
#endif
|
||||
#define malloc(x) DO_NOT_CALL_MALLOC__USE_C_MALLOC_INSTEAD
|
||||
|
||||
#ifdef calloc
|
||||
#undef calloc
|
||||
#endif
|
||||
#define calloc(x,y) DO_NOT_CALL_CALLOC__USE_C_CALLOC_INSTEAD
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef realloc
|
||||
#undef realloc
|
||||
#endif
|
||||
#define realloc(x,y) DO_NOT_CALL_REALLOC__USE_C_REALLOC_INSTEAD
|
||||
|
||||
#ifdef dirname
|
||||
#undef dirname
|
||||
#endif
|
||||
#define dirname(x) DO_NOT_CALL_MALLOC__USE_C_DIRNAME_INSTEAD
|
||||
|
||||
#ifdef basename
|
||||
#undef basename
|
||||
#endif
|
||||
#define basename(x) DO_NOT_CALL_MALLOC__USE_C_BASENAME_INSTEAD
|
||||
|
||||
#ifdef strdup
|
||||
#undef strdup
|
||||
#endif
|
||||
#define strdup(x) DO_NOT_CALL_STRDUP__USE_C_STRDUP_INSTEAD
|
||||
|
||||
|
||||
@@ -117,81 +117,6 @@ char *c_basename (const char *path) {
|
||||
return newbuf;
|
||||
}
|
||||
|
||||
|
||||
char *c_tmpname(const char *templ) {
|
||||
char *tmp = NULL;
|
||||
char *target = NULL;
|
||||
int rc;
|
||||
int i = 0;
|
||||
|
||||
if (!templ) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* If the template does not contain the XXXXXX it will be appended. */
|
||||
if( !strstr( templ, "XXXXXX" )) {
|
||||
/* split up the path */
|
||||
char *path = c_dirname(templ);
|
||||
char *base = c_basename(templ);
|
||||
|
||||
if (!base) {
|
||||
if (path) {
|
||||
SAFE_FREE(path);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
/* Create real hidden files for unixoide. */
|
||||
if( path ) {
|
||||
#ifdef _WIN32
|
||||
rc = asprintf(&target, "%s/%s.~XXXXXX", path, base);
|
||||
#else
|
||||
rc = asprintf(&target, "%s/.%s.~XXXXXX", path, base);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef _WIN32
|
||||
rc = asprintf(&target, "%s.~XXXXXX", base);
|
||||
#else
|
||||
rc = asprintf(&target, ".%s.~XXXXXX", base);
|
||||
#endif
|
||||
|
||||
}
|
||||
SAFE_FREE(path);
|
||||
SAFE_FREE(base);
|
||||
|
||||
if (rc < 0) {
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
target = c_strdup(templ);
|
||||
}
|
||||
|
||||
if (!target) {
|
||||
goto err;
|
||||
}
|
||||
tmp = strstr( target, "XXXXXX" );
|
||||
if (!tmp) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; ++i) {
|
||||
#ifdef _WIN32
|
||||
/* in win32 MAX_RAND is 32767, thus we can not shift that far,
|
||||
* otherwise the last three chars are 0
|
||||
*/
|
||||
int hexdigit = (rand() >> (i * 2)) & 0x1f;
|
||||
#else
|
||||
int hexdigit = (rand() >> (i * 5)) & 0x1f;
|
||||
#endif
|
||||
tmp[i] = hexdigit > 9 ? hexdigit + 'a' - 10 : hexdigit + '0';
|
||||
}
|
||||
|
||||
return target;
|
||||
|
||||
err:
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int c_parse_uri(const char *uri,
|
||||
char **scheme,
|
||||
char **user, char **passwd,
|
||||
@@ -470,84 +395,3 @@ int c_parse_uri(const char *uri,
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* http://refactormycode.com/codes/1345-extracting-directory-filename-and-extension-from-a-path
|
||||
* Allocate a block of memory that holds the PATHINFO at the beginning
|
||||
* followed by the actual path. Two extra bytes are allocated (+3 instead
|
||||
* of just +1) to deal with shifting the filename and extension to protect the trailing '/'
|
||||
* and the leading '.'. These extra bytes also double as the empty string, as
|
||||
* well as a pad to keep from reading past the memory block.
|
||||
*
|
||||
*/
|
||||
C_PATHINFO * c_split_path(const char* pathSrc)
|
||||
{
|
||||
size_t length = strlen(pathSrc);
|
||||
size_t len=0;
|
||||
C_PATHINFO * pathinfo = (C_PATHINFO *) c_malloc(sizeof(C_PATHINFO) + length + 3);
|
||||
|
||||
if (pathinfo)
|
||||
{
|
||||
char * path = (char *) &pathinfo[1]; // copy of the path
|
||||
char * theEnd = &path[length + 1]; // second null terminator
|
||||
char * extension;
|
||||
char * lastSep;
|
||||
|
||||
// Copy the original string and double null terminate it.
|
||||
strcpy(path, pathSrc);
|
||||
*theEnd = '\0';
|
||||
pathinfo->directory = theEnd; // Assume no path
|
||||
pathinfo->extension = theEnd; // Assume no extension
|
||||
pathinfo->filename = path; // Assume filename only
|
||||
|
||||
lastSep = strrchr(path, '/');
|
||||
if (lastSep)
|
||||
{
|
||||
pathinfo->directory = path; // Pick up the path
|
||||
|
||||
memmove(lastSep + 1, lastSep, strlen(lastSep));
|
||||
*lastSep++ ='/';
|
||||
*lastSep++ ='\0'; // Truncate directory
|
||||
|
||||
pathinfo->filename = lastSep; // Pick up name after path
|
||||
}
|
||||
|
||||
// Start at the second character of the filename to handle
|
||||
// filenames that start with '.' like ".login".
|
||||
// We don't overrun the buffer in the cases of an empty path
|
||||
// or a path that looks like "/usr/bin/" because of the extra
|
||||
// byte.
|
||||
|
||||
|
||||
extension = strrchr(&pathinfo->filename[1], '.');
|
||||
if (extension)
|
||||
{
|
||||
// Shift the extension over to protect the leading '.' since
|
||||
// we need to truncate the filename.
|
||||
memmove(extension + 1, extension, strlen(extension));
|
||||
pathinfo->extension = extension + 1;
|
||||
|
||||
*extension = '\0'; // Truncate filename
|
||||
}
|
||||
else
|
||||
{
|
||||
len=strlen(pathinfo->filename);
|
||||
if(len>1)
|
||||
{
|
||||
//tmp files from kate/kwrite "somefile~": '~' should be the extension
|
||||
if(pathinfo->filename[len-1]=='~')
|
||||
{
|
||||
extension = &pathinfo->filename[len-1];
|
||||
memmove(extension + 1, extension, strlen(extension));
|
||||
pathinfo->extension = extension + 1;
|
||||
*extension = '\0'; // Truncate filename
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return pathinfo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -66,19 +66,6 @@ char *c_dirname(const char *path);
|
||||
*/
|
||||
char *c_basename (const char *path);
|
||||
|
||||
/**
|
||||
* @brief Make a temporary filename.
|
||||
*
|
||||
* @param templ The template to replace. If the template contains six X like
|
||||
* 'XXXXXX', these are replaced by a random string. If not, the
|
||||
* templ is interpreted as a path, and a name to a hidden file
|
||||
* with six random is returned.
|
||||
* The caller has to free the memory.
|
||||
*
|
||||
* @return a poitner to the random hidden filename or NULL.
|
||||
*/
|
||||
char *c_tmpname(const char *templ);
|
||||
|
||||
/**
|
||||
* @brief parse a uri and split it into components.
|
||||
*
|
||||
@@ -120,15 +107,6 @@ typedef struct
|
||||
char * extension;
|
||||
} C_PATHINFO;
|
||||
|
||||
/**
|
||||
* @brief Extracting directory, filename and extension from a path.
|
||||
*
|
||||
* @param pathSrc The path to parse.
|
||||
*
|
||||
* @return Returns a C_PATHINFO structure that should be freed using SAFE_FREE().
|
||||
*/
|
||||
C_PATHINFO * c_split_path(const char* pathSrc);
|
||||
|
||||
|
||||
/**
|
||||
* }@
|
||||
|
||||
@@ -239,69 +239,6 @@ void c_strlist_destroy(c_strlist_t *strlist) {
|
||||
SAFE_FREE(strlist);
|
||||
}
|
||||
|
||||
char *c_strreplace(char *src, const char *pattern, const char *repl) {
|
||||
char *p = NULL;
|
||||
|
||||
while ((p = strstr(src, pattern)) != NULL) {
|
||||
size_t of = p - src;
|
||||
size_t l = strlen(src);
|
||||
size_t pl = strlen(pattern);
|
||||
size_t rl = strlen(repl);
|
||||
|
||||
if (rl > pl) {
|
||||
src = (char *) c_realloc(src, strlen(src) + rl - pl + 1);
|
||||
}
|
||||
|
||||
if (rl != pl) {
|
||||
memmove(src + of + rl, src + of + pl, l - of - pl + 1);
|
||||
}
|
||||
|
||||
strncpy(src + of, repl, rl);
|
||||
}
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
char *c_uppercase(const char* str) {
|
||||
char *new;
|
||||
char *p;
|
||||
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new = c_strdup(str);
|
||||
if (new == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (p = new; *p; p++) {
|
||||
*p = toupper(*p);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
char *c_lowercase(const char* str) {
|
||||
char *new;
|
||||
char *p;
|
||||
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new = c_strdup(str);
|
||||
if (new == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (p = new; *p; p++) {
|
||||
*p = tolower(*p);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
/* Convert a wide multibyte String to UTF8 */
|
||||
char* c_utf8_from_locale(const mbchar_t *wstr)
|
||||
{
|
||||
|
||||
@@ -119,37 +119,6 @@ void c_strlist_clear(c_strlist_t *strlist);
|
||||
*/
|
||||
void c_strlist_destroy(c_strlist_t *strlist);
|
||||
|
||||
/**
|
||||
* @breif Replace a string with another string in a source string.
|
||||
*
|
||||
* @param src String to search for pattern.
|
||||
*
|
||||
* @param pattern Pattern to search for in the source string.
|
||||
*
|
||||
* @param repl The string which which should replace pattern if found.
|
||||
*
|
||||
* @return Return a pointer to the source string.
|
||||
*/
|
||||
char *c_strreplace(char *src, const char *pattern, const char *repl);
|
||||
|
||||
/**
|
||||
* @brief Uppercase a string.
|
||||
*
|
||||
* @param str The String to uppercase.
|
||||
*
|
||||
* @return The malloced uppered string or NULL on error.
|
||||
*/
|
||||
char *c_uppercase(const char* str);
|
||||
|
||||
/**
|
||||
* @brief Lowercase a string.
|
||||
*
|
||||
* @param str The String to lowercase.
|
||||
*
|
||||
* @return The malloced lowered string or NULL on error.
|
||||
*/
|
||||
char *c_lowercase(const char* str);
|
||||
|
||||
/**
|
||||
* @brief Convert a platform locale string to utf8.
|
||||
*
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "csync_private.h"
|
||||
#include "csync_util.h"
|
||||
@@ -44,7 +45,7 @@ csync_vio_handle_t *csync_vio_opendir(CSYNC *ctx, const char *name) {
|
||||
if(ctx->remote.read_from_db) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Read from db flag is true, should not!" );
|
||||
}
|
||||
return owncloud_opendir(name);
|
||||
return owncloud_opendir(ctx, name);
|
||||
break;
|
||||
case LOCAL_REPLICA:
|
||||
return csync_vio_local_opendir(name);
|
||||
@@ -69,7 +70,7 @@ int csync_vio_closedir(CSYNC *ctx, csync_vio_handle_t *dhandle) {
|
||||
if( ctx->remote.read_from_db ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Remote ReadFromDb is true, should not!");
|
||||
}
|
||||
rc = owncloud_closedir(dhandle);
|
||||
rc = owncloud_closedir(ctx, dhandle);
|
||||
break;
|
||||
case LOCAL_REPLICA:
|
||||
rc = csync_vio_local_closedir(dhandle);
|
||||
@@ -87,7 +88,7 @@ csync_vio_file_stat_t *csync_vio_readdir(CSYNC *ctx, csync_vio_handle_t *dhandle
|
||||
if( ctx->remote.read_from_db ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Remote readfromdb is true, should not!");
|
||||
}
|
||||
return owncloud_readdir(dhandle);
|
||||
return owncloud_readdir(ctx, dhandle);
|
||||
break;
|
||||
case LOCAL_REPLICA:
|
||||
return csync_vio_local_readdir(dhandle);
|
||||
@@ -106,7 +107,8 @@ int csync_vio_stat(CSYNC *ctx, const char *uri, csync_vio_file_stat_t *buf) {
|
||||
|
||||
switch(ctx->replica) {
|
||||
case REMOTE_REPLICA:
|
||||
rc = owncloud_stat(uri, buf);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "ERROR: Cannot call remote stat, not implemented");
|
||||
assert(ctx->replica != REMOTE_REPLICA);
|
||||
break;
|
||||
case LOCAL_REPLICA:
|
||||
rc = csync_vio_local_stat(uri, buf);
|
||||
@@ -121,21 +123,9 @@ int csync_vio_stat(CSYNC *ctx, const char *uri, csync_vio_file_stat_t *buf) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *csync_vio_get_status_string(CSYNC *ctx) {
|
||||
if(ctx->error_string) {
|
||||
return ctx->error_string;
|
||||
}
|
||||
return owncloud_error_string();
|
||||
}
|
||||
|
||||
int csync_vio_set_property(CSYNC* ctx, const char* key, void* data) {
|
||||
(void) ctx;
|
||||
return owncloud_set_property(key, data);
|
||||
}
|
||||
|
||||
int csync_vio_commit(CSYNC *ctx) {
|
||||
(void) ctx;
|
||||
return owncloud_commit();
|
||||
return owncloud_error_string(ctx);
|
||||
}
|
||||
|
||||
@@ -39,10 +39,7 @@ csync_vio_file_stat_t *csync_vio_readdir(CSYNC *ctx, csync_vio_handle_t *dhandle
|
||||
|
||||
int csync_vio_stat(CSYNC *ctx, const char *uri, csync_vio_file_stat_t *buf);
|
||||
|
||||
int csync_vio_set_property(CSYNC *ctx, const char *key, void *data);
|
||||
|
||||
char *csync_vio_get_status_string(CSYNC *ctx);
|
||||
|
||||
int csync_vio_commit(CSYNC *ctx);
|
||||
|
||||
#endif /* _CSYNC_VIO_H */
|
||||
|
||||
@@ -22,14 +22,8 @@
|
||||
#include "vio/csync_vio_file_stat.h"
|
||||
|
||||
csync_vio_file_stat_t *csync_vio_file_stat_new(void) {
|
||||
csync_vio_file_stat_t *file_stat = NULL;
|
||||
|
||||
file_stat = (csync_vio_file_stat_t *) c_malloc(sizeof(csync_vio_file_stat_t));
|
||||
if (file_stat == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
file_stat->etag = NULL;
|
||||
memset(file_stat->file_id, 0, FILE_ID_BUF_SIZE+1);
|
||||
csync_vio_file_stat_t *file_stat = (csync_vio_file_stat_t *) c_malloc(sizeof(csync_vio_file_stat_t));
|
||||
ZERO_STRUCTP(file_stat);
|
||||
return file_stat;
|
||||
}
|
||||
|
||||
@@ -39,15 +33,11 @@ void csync_vio_file_stat_destroy(csync_vio_file_stat_t *file_stat) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (file_stat->fields & CSYNC_VIO_FILE_STAT_FIELDS_SYMLINK_NAME) {
|
||||
SAFE_FREE(file_stat->u.symlink_name);
|
||||
}
|
||||
if (file_stat->fields & CSYNC_VIO_FILE_STAT_FIELDS_CHECKSUM) {
|
||||
SAFE_FREE(file_stat->u.checksum);
|
||||
}
|
||||
if (file_stat->fields & CSYNC_VIO_FILE_STAT_FIELDS_ETAG) {
|
||||
SAFE_FREE(file_stat->etag);
|
||||
}
|
||||
SAFE_FREE(file_stat->directDownloadUrl);
|
||||
SAFE_FREE(file_stat->directDownloadCookies);
|
||||
SAFE_FREE(file_stat->name);
|
||||
SAFE_FREE(file_stat);
|
||||
}
|
||||
|
||||
@@ -62,42 +62,35 @@ enum csync_vio_file_stat_fields_e {
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_INODE = 1 << 4,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_LINK_COUNT = 1 << 5,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_SIZE = 1 << 6,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_BLOCK_COUNT = 1 << 7, /* will be removed */
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_BLOCK_SIZE = 1 << 8, /* will be removed */
|
||||
// CSYNC_VIO_FILE_STAT_FIELDS_BLOCK_COUNT = 1 << 7, /* will be removed */
|
||||
// CSYNC_VIO_FILE_STAT_FIELDS_BLOCK_SIZE = 1 << 8, /* will be removed */
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_ATIME = 1 << 9,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_MTIME = 1 << 10,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_CTIME = 1 << 11,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_SYMLINK_NAME = 1 << 12,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_CHECKSUM = 1 << 13,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_ACL = 1 << 14,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_UID = 1 << 15,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_GID = 1 << 16,
|
||||
// CSYNC_VIO_FILE_STAT_FIELDS_SYMLINK_NAME = 1 << 12,
|
||||
// CSYNC_VIO_FILE_STAT_FIELDS_CHECKSUM = 1 << 13,
|
||||
// CSYNC_VIO_FILE_STAT_FIELDS_ACL = 1 << 14,
|
||||
// CSYNC_VIO_FILE_STAT_FIELDS_UID = 1 << 15,
|
||||
// CSYNC_VIO_FILE_STAT_FIELDS_GID = 1 << 16,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_ETAG = 1 << 17,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_FILE_ID = 1 << 18
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_FILE_ID = 1 << 18,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADURL = 1 << 19,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADCOOKIES = 1 << 20
|
||||
};
|
||||
|
||||
|
||||
struct csync_vio_file_stat_s {
|
||||
union {
|
||||
char *symlink_name;
|
||||
char *checksum;
|
||||
} u;
|
||||
|
||||
void *acl;
|
||||
char *name;
|
||||
char *etag;
|
||||
char file_id[FILE_ID_BUF_SIZE+1];
|
||||
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
char *directDownloadUrl;
|
||||
char *directDownloadCookies;
|
||||
|
||||
time_t atime;
|
||||
time_t mtime;
|
||||
time_t ctime;
|
||||
|
||||
int64_t size;
|
||||
int64_t blksize; /* will be removed in future, not used in csync */
|
||||
unsigned long blkcount; /* will be removed in future, not used in csync */
|
||||
|
||||
mode_t mode;
|
||||
|
||||
@@ -109,10 +102,6 @@ struct csync_vio_file_stat_s {
|
||||
enum csync_vio_file_type_e type;
|
||||
|
||||
enum csync_vio_file_flags_e flags;
|
||||
|
||||
void *reserved1;
|
||||
void *reserved2;
|
||||
void *reserved3;
|
||||
};
|
||||
|
||||
csync_vio_file_stat_t *csync_vio_file_stat_new(void);
|
||||
|
||||
@@ -331,11 +331,6 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
buf->inode = sb.st_ino;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_INODE;
|
||||
|
||||
/* Both values are only initialized to zero as they are not used in csync */
|
||||
/* They are deprecated and will be rmemoved later. */
|
||||
buf->blksize = 0;
|
||||
buf->blkcount = 0;
|
||||
|
||||
buf->atime = sb.st_atime;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ATIME;
|
||||
|
||||
@@ -348,12 +343,6 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
buf->nlink = sb.st_nlink;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_LINK_COUNT;
|
||||
|
||||
buf->uid = sb.st_uid;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_UID;
|
||||
|
||||
buf->gid = sb.st_gid;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_GID;
|
||||
|
||||
buf->size = sb.st_size;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
|
||||
|
||||
|
||||
@@ -21,8 +21,6 @@ set(TEST_TARGET_LIBRARIES ${TORTURE_LIBRARY})
|
||||
|
||||
# std
|
||||
add_cmocka_test(check_std_c_alloc std_tests/check_std_c_alloc.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_std_c_dir std_tests/check_std_c_dir.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_std_c_file std_tests/check_std_c_file.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_std_c_jhash std_tests/check_std_c_jhash.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_std_c_list std_tests/check_std_c_list.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_std_c_path std_tests/check_std_c_path.c ${TEST_TARGET_LIBRARIES})
|
||||
|
||||
@@ -36,9 +36,6 @@ static void setup(void **state) {
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = csync_set_config_dir(csync, "/tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = csync;
|
||||
}
|
||||
|
||||
@@ -55,9 +52,6 @@ static void setup_module(void **state) {
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "dummy://foo/bar");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = csync_set_config_dir(csync, "/tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = csync_init(csync);
|
||||
*state = csync;
|
||||
}
|
||||
|
||||
@@ -46,9 +46,6 @@ static void check_csync_create(void **state)
|
||||
rc = csync_create(&csync, "/tmp/csync1", "/tmp/csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
snprintf(confdir, sizeof(confdir), "%s/%s", getenv("HOME"), CSYNC_CONF_DIR);
|
||||
assert_string_equal(csync->options.config_dir, confdir);
|
||||
|
||||
rc = csync_destroy(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
@@ -32,10 +32,6 @@ static void setup(void **state) {
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
free(csync->options.config_dir);
|
||||
csync->options.config_dir = c_strdup("/tmp/check_csync1/");
|
||||
assert_non_null(csync->options.config_dir);
|
||||
|
||||
*state = csync;
|
||||
}
|
||||
|
||||
@@ -46,10 +42,6 @@ static void setup_init(void **state) {
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
free(csync->options.config_dir);
|
||||
csync->options.config_dir = c_strdup("/tmp/check_csync1/");
|
||||
assert_non_null(csync->options.config_dir);
|
||||
|
||||
rc = csync_exclude_load(csync, SOURCEDIR "/../sync-exclude.lst");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
|
||||
@@ -36,9 +36,6 @@ static void setup(void **state) {
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = csync_set_config_dir(csync, "/tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = csync;
|
||||
}
|
||||
|
||||
@@ -55,9 +52,6 @@ static void setup_module(void **state) {
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "dummy://foo/bar");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = csync_set_config_dir(csync, "/tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = csync;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,9 +40,6 @@ static void setup(void **state) {
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = csync_set_config_dir(csync, "/tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = csync;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,8 +40,6 @@ static void setup(void **state) {
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_set_config_dir(csync, "/tmp/check_csync1/");
|
||||
|
||||
csync->statedb.file = c_strdup( TESTDB );
|
||||
*state = csync;
|
||||
}
|
||||
|
||||
@@ -44,8 +44,6 @@ static void setup(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = csync_set_config_dir(csync, "/tmp/check_csync/");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = csync_init(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
|
||||
@@ -36,8 +36,6 @@ static void setup(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = csync_set_config_dir(csync, "/tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = csync_init(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
|
||||
@@ -60,8 +58,6 @@ static void setup_ftw(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
rc = csync_create(&csync, "/tmp", "/tmp");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = csync_set_config_dir(csync, "/tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = csync_init(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
|
||||
@@ -146,17 +142,6 @@ static csync_vio_file_stat_t* create_fstat(const char *name,
|
||||
}
|
||||
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_LINK_COUNT;
|
||||
|
||||
fs->uid = 1000;
|
||||
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_UID;
|
||||
|
||||
fs->gid = 1000;
|
||||
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_GID;
|
||||
|
||||
fs->blkcount = 312;
|
||||
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_BLOCK_COUNT;
|
||||
|
||||
fs->blksize = 4096;
|
||||
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_BLOCK_SIZE;
|
||||
|
||||
if (mtime == 0) {
|
||||
fs->atime = fs->ctime = fs->mtime = time(&t);
|
||||
|
||||
@@ -46,6 +46,7 @@ glob_put( 'toremote1/rtl1/rtl11/*', "remoteToLocal1/rtl1/rtl11/" );
|
||||
glob_put( 'toremote1/rtl2/*', "remoteToLocal1/rtl2/" );
|
||||
glob_put( 'toremote1/rtl4/*', "remoteToLocal1/rtl4/" );
|
||||
|
||||
|
||||
# call csync, sync local t1 to remote t1
|
||||
csync();
|
||||
|
||||
@@ -74,9 +75,19 @@ foreach my $file ( <./tolocal1/*> ) {
|
||||
print "Copying $file to $locDir\n";
|
||||
copy( $file, $locDir );
|
||||
}
|
||||
|
||||
# Also add a file with symbols
|
||||
my $symbolName = "a\%b#c\$d-e";
|
||||
system( "echo \"my symbols\" >> $locDir/$symbolName" );
|
||||
|
||||
#Also on the server
|
||||
put_to_dir( "$locDir/$symbolName", 'remoteToLocal1' );
|
||||
|
||||
|
||||
csync( );
|
||||
print "\nAssert local and remote dirs.\n";
|
||||
assertLocalAndRemoteDir( '', 0);
|
||||
assert( ! -e localDir().$symbolName );
|
||||
|
||||
# move a local file
|
||||
printInfo( "Move a file locally." );
|
||||
|
||||
@@ -67,6 +67,13 @@ system( "rm -rf " . localDir() . 'remoteToLocal1' );
|
||||
system( "echo \"my file\" >> /tmp/myfile.txt" );
|
||||
put_to_dir( '/tmp/myfile.txt', 'remoteToLocal1/rtl1/rtl11' );
|
||||
|
||||
# Also add a file with symbols
|
||||
my $symbolName = "a\%b#c\$d-e";
|
||||
|
||||
system( "echo \"my symbols\" >> /tmp/$symbolName" );
|
||||
put_to_dir( "/tmp/$symbolName", 'remoteToLocal1/rtl1/rtl11' );
|
||||
|
||||
|
||||
my $fileid = remoteFileId( 'remoteToLocal1/rtl1/', 'rtl11' );
|
||||
my $fid2 = remoteFileId( 'remoteToLocal1/rtl1/', 'La ced' );
|
||||
assert($fid2 eq "" or $fileid ne $fid2, "File IDs are equal" );
|
||||
@@ -90,6 +97,9 @@ printInfo("Move file and create another one with the same name.");
|
||||
move( localDir() . 'newdir/myfile.txt', localDir() . 'newdir/oldfile.txt' );
|
||||
system( "echo \"super new\" >> " . localDir() . 'newdir/myfile.txt' );
|
||||
|
||||
#Move a file with symbols as well
|
||||
move( localDir() . "newdir/$symbolName", localDir() . "newdir/$symbolName.new" );
|
||||
|
||||
#Add some files for the next test.
|
||||
system( "echo \"un\" > " . localDir() . '1.txt' );
|
||||
system( "echo \"deux\" > " . localDir() . '2.txt' );
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* 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 <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
#include "std/c_private.h"
|
||||
#include "std/c_dir.h"
|
||||
#include "std/c_string.h"
|
||||
|
||||
const char *check_dir = "/tmp/check/c_mkdirs//with/check//";
|
||||
const char *check_file = "/tmp/check/c_mkdirs/with/check/foobar.txt";
|
||||
|
||||
static void setup(void **state) {
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = c_mkdirs(check_dir, 0755);
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("touch /tmp/check/c_mkdirs/with/check/foobar.txt");
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void teardown(void **state) {
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = c_rmdirs(check_dir);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static int test_dir(const char *path, mode_t mode) {
|
||||
csync_stat_t sb;
|
||||
if (lstat(path, &sb) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (! S_ISDIR(sb.st_mode)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* FIXME */
|
||||
if ((sb.st_mode & mode) == mode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void check_c_mkdirs_rmdirs(void **state)
|
||||
{
|
||||
csync_stat_t sb;
|
||||
int rc;
|
||||
mbchar_t *wcheck_dir;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = c_mkdirs(check_dir, 0755);
|
||||
assert_int_equal(rc, 0);
|
||||
rc = test_dir(check_dir, 0755);
|
||||
assert_int_equal(rc, 0);
|
||||
rc = c_rmdirs(check_dir);
|
||||
assert_int_equal(rc, 0);
|
||||
wcheck_dir = c_utf8_to_locale(check_dir);
|
||||
rc = _tstat(wcheck_dir, &sb);
|
||||
c_free_locale_string(wcheck_dir);
|
||||
assert_int_equal(rc, -1);
|
||||
}
|
||||
|
||||
static void check_c_mkdirs_mode(void **state)
|
||||
{
|
||||
csync_stat_t sb;
|
||||
int rc;
|
||||
mbchar_t *wcheck_dir;
|
||||
|
||||
(void) state; /* unused */
|
||||
rc = c_mkdirs(check_dir, 0700);
|
||||
assert_int_equal(rc, 0);
|
||||
rc = test_dir(check_dir, 0700);
|
||||
assert_int_equal(rc, 0);
|
||||
rc = c_rmdirs(check_dir);
|
||||
assert_int_equal(rc, 0);
|
||||
wcheck_dir = c_utf8_to_locale(check_dir);
|
||||
rc = _tstat(wcheck_dir, &sb);
|
||||
assert_int_equal(rc, -1);
|
||||
c_free_locale_string(wcheck_dir);
|
||||
}
|
||||
|
||||
static void check_c_mkdirs_existing_path(void **state)
|
||||
{
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = c_mkdirs(check_dir, 0755);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void check_c_mkdirs_file(void **state)
|
||||
{
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = c_mkdirs(check_file, 0755);
|
||||
assert_int_equal(rc, -1);
|
||||
assert_int_equal(errno, ENOTDIR);
|
||||
}
|
||||
|
||||
static void check_c_mkdirs_null(void **state)
|
||||
{
|
||||
(void) state; /* unused */
|
||||
|
||||
assert_int_equal(c_mkdirs(NULL, 0755), -1);
|
||||
}
|
||||
|
||||
static void check_c_isdir(void **state)
|
||||
{
|
||||
(void) state; /* unused */
|
||||
|
||||
assert_int_equal(c_isdir(check_dir), 1);
|
||||
}
|
||||
|
||||
static void check_c_isdir_on_file(void **state)
|
||||
{
|
||||
(void) state; /* unused */
|
||||
|
||||
assert_int_equal(c_isdir(check_file), 0);
|
||||
}
|
||||
|
||||
static void check_c_isdir_null(void **state)
|
||||
{
|
||||
(void) state; /* unused */
|
||||
|
||||
assert_int_equal(c_isdir(NULL), 0);
|
||||
}
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
unit_test(check_c_mkdirs_rmdirs),
|
||||
unit_test(check_c_mkdirs_mode),
|
||||
unit_test_setup_teardown(check_c_mkdirs_existing_path, setup, teardown),
|
||||
unit_test_setup_teardown(check_c_mkdirs_file, setup, teardown),
|
||||
unit_test(check_c_mkdirs_null),
|
||||
unit_test_setup_teardown(check_c_isdir, setup, teardown),
|
||||
unit_test_setup_teardown(check_c_isdir_on_file, setup, teardown),
|
||||
unit_test(check_c_isdir_null),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
}
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* 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 <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
#include "std/c_private.h"
|
||||
#include "std/c_file.h"
|
||||
#include "std/c_string.h"
|
||||
|
||||
const char *check_dir = "/tmp/check";
|
||||
const char *check_src_file = "/tmp/check/foo.txt";
|
||||
const char *check_dst_file = "/tmp/check/bar.txt";
|
||||
|
||||
static int test_file(const char *path, mode_t mode) {
|
||||
csync_stat_t sb;
|
||||
mbchar_t *mbpath = c_utf8_to_locale(path);
|
||||
int rc = _tstat(mbpath, &sb);
|
||||
c_free_locale_string(mbpath);
|
||||
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (! S_ISREG(sb.st_mode)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((sb.st_mode & mode) == mode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void setup(void **state) {
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = system("mkdir -p /tmp/check");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("echo 42 > /tmp/check/foo.txt");
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void teardown(void **state) {
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = system("rm -rf /tmp/check");
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void check_c_copy(void **state)
|
||||
{
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = c_copy(check_src_file, check_dst_file, 0644);
|
||||
assert_int_equal(rc, 0);
|
||||
rc = test_file(check_dst_file, 0644);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void check_c_copy_same_file(void **state)
|
||||
{
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = c_copy(check_src_file, check_src_file, 0644);
|
||||
assert_int_equal(rc, -1);
|
||||
}
|
||||
|
||||
static void check_c_copy_isdir(void **state)
|
||||
{
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = c_copy(check_src_file, check_dir, 0644);
|
||||
assert_int_equal(rc, -1);
|
||||
assert_int_equal(errno, EISDIR);
|
||||
|
||||
rc = c_copy(check_dir, check_dst_file, 0644);
|
||||
assert_int_equal(rc, -1);
|
||||
assert_int_equal(errno, ENOENT);
|
||||
}
|
||||
|
||||
static void check_c_compare_file(void **state)
|
||||
{
|
||||
int rc;
|
||||
(void) state;
|
||||
|
||||
rc = c_copy(check_src_file, check_dst_file, 0644);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = c_compare_file( check_src_file, check_dst_file );
|
||||
assert_int_equal(rc, 1);
|
||||
|
||||
/* Check error conditions */
|
||||
rc = c_compare_file( NULL, check_dst_file );
|
||||
assert_int_equal(rc, -1);
|
||||
rc = c_compare_file( check_dst_file, NULL );
|
||||
assert_int_equal(rc, -1);
|
||||
rc = c_compare_file( NULL, NULL );
|
||||
assert_int_equal(rc, -1);
|
||||
|
||||
rc = c_compare_file( check_src_file, "/I_do_not_exist_in_the_filesystem.dummy");
|
||||
assert_int_equal(rc, -1);
|
||||
rc = c_compare_file( "/I_do_not_exist_in_the_filesystem.dummy", check_dst_file);
|
||||
assert_int_equal(rc, -1);
|
||||
|
||||
rc = system("echo \"hallo42\" > /tmp/check/foo.txt");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("echo \"hallo52\" > /tmp/check/bar.txt");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = c_compare_file( check_src_file, check_dst_file );
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
/* Create two 1MB random files */
|
||||
rc = system("dd if=/dev/urandom of=/tmp/check/foo.txt bs=1024 count=1024");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("dd if=/dev/urandom of=/tmp/check/bar.txt bs=1024 count=1024");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = c_compare_file( check_src_file, check_dst_file );
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
/* Create two 1MB random files with different size */
|
||||
rc = system("dd if=/dev/urandom of=/tmp/check/foo.txt bs=1024 count=1024");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("dd if=/dev/urandom of=/tmp/check/bar.txt bs=1024 count=1020");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = c_compare_file( check_src_file, check_dst_file );
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
/* compare two big files which are equal */
|
||||
rc = c_copy(check_src_file, check_dst_file, 0644);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = c_compare_file( check_src_file, check_dst_file );
|
||||
assert_int_equal(rc, 1);
|
||||
}
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
unit_test_setup_teardown(check_c_copy, setup, teardown),
|
||||
unit_test(check_c_copy_same_file),
|
||||
unit_test_setup_teardown(check_c_copy_isdir, setup, teardown),
|
||||
unit_test_setup_teardown(check_c_compare_file, setup, teardown),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
}
|
||||
|
||||
@@ -130,32 +130,6 @@ static void check_c_dirname_uri(void **state)
|
||||
free(dname);
|
||||
}
|
||||
|
||||
static void check_c_tmpname(void **state)
|
||||
{
|
||||
char tmpl[22]={0};
|
||||
char prev[22]={0};
|
||||
char *tmp;
|
||||
int i = 0;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
srand((unsigned)time(NULL));
|
||||
|
||||
/* remember the last random value and compare the new one against.
|
||||
* They may never be the same. */
|
||||
for(i = 0; i < 100; i++){
|
||||
strcpy(tmpl, "check_tmpname.XXXXXX");
|
||||
tmp = c_tmpname(tmpl);
|
||||
assert_non_null(tmp);
|
||||
|
||||
if (strlen(prev)) {
|
||||
assert_string_not_equal(tmp, prev);
|
||||
}
|
||||
strcpy(prev, tmp);
|
||||
SAFE_FREE(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
static void check_c_parse_uri(void **state)
|
||||
{
|
||||
const char *test_scheme = "git+ssh";
|
||||
@@ -204,7 +178,6 @@ int torture_run_tests(void)
|
||||
unit_test(check_c_dirname),
|
||||
unit_test(check_c_dirname_uri),
|
||||
unit_test(check_c_parse_uri),
|
||||
unit_test(check_c_tmpname),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
|
||||
@@ -113,85 +113,6 @@ static void check_c_strlist_expand(void **state)
|
||||
c_strlist_destroy(strlist);
|
||||
}
|
||||
|
||||
static void check_c_strreplace(void **state)
|
||||
{
|
||||
char *str = strdup("/home/%(USER)");
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
str = c_strreplace(str, "%(USER)", "csync");
|
||||
assert_string_equal(str, "/home/csync");
|
||||
|
||||
free(str);
|
||||
}
|
||||
|
||||
static void check_c_lowercase(void **state)
|
||||
{
|
||||
char *str;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
str = c_lowercase("LoWeRcASE");
|
||||
assert_string_equal(str, "lowercase");
|
||||
|
||||
free(str);
|
||||
}
|
||||
|
||||
static void check_c_lowercase_empty(void **state)
|
||||
{
|
||||
char *str;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
str = c_lowercase("");
|
||||
assert_string_equal(str, "");
|
||||
|
||||
free(str);
|
||||
}
|
||||
|
||||
static void check_c_lowercase_null(void **state)
|
||||
{
|
||||
char *str;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
str = c_lowercase(NULL);
|
||||
assert_null(str);
|
||||
}
|
||||
|
||||
static void check_c_uppercase(void **state)
|
||||
{
|
||||
char *str;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
str = c_uppercase("upperCASE");
|
||||
assert_string_equal(str, "UPPERCASE");
|
||||
|
||||
free(str);
|
||||
}
|
||||
|
||||
static void check_c_uppercase_empty(void **state)
|
||||
{
|
||||
char *str;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
str = c_uppercase("");
|
||||
assert_string_equal(str, "");
|
||||
|
||||
free(str);
|
||||
}
|
||||
|
||||
static void check_c_uppercase_null(void **state)
|
||||
{
|
||||
char *str;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
str = c_uppercase(NULL);
|
||||
assert_null(str);
|
||||
}
|
||||
|
||||
|
||||
int torture_run_tests(void)
|
||||
@@ -203,13 +124,6 @@ int torture_run_tests(void)
|
||||
unit_test(check_c_strlist_new),
|
||||
unit_test(check_c_strlist_add),
|
||||
unit_test(check_c_strlist_expand),
|
||||
unit_test(check_c_strreplace),
|
||||
unit_test(check_c_lowercase),
|
||||
unit_test(check_c_lowercase_empty),
|
||||
unit_test(check_c_lowercase_null),
|
||||
unit_test(check_c_uppercase),
|
||||
unit_test(check_c_uppercase_empty),
|
||||
unit_test(check_c_uppercase_null),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
|
||||
@@ -4,7 +4,7 @@ if(SPHINX_FOUND)
|
||||
set(SPHINX_CACHE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees")
|
||||
# HTML output directory
|
||||
set(SPHINX_HTML_DIR "${CMAKE_CURRENT_BINARY_DIR}/html")
|
||||
set(SPHINX_MAN_DIR "${CMAKE_CURRENT_BINARY_DIR}/man")
|
||||
set(SPHINX_MAN_DIR "${CMAKE_CURRENT_BINARY_DIR}/man1")
|
||||
set(SPHINX_PDF_DIR "${CMAKE_CURRENT_BINARY_DIR}/latex")
|
||||
set(SPHINX_QCH_DIR "${CMAKE_CURRENT_BINARY_DIR}/qthelp")
|
||||
set(SPHINX_HTMLHELP_DIR "${CMAKE_CURRENT_BINARY_DIR}/htmlhelp")
|
||||
|
||||
|
Depois Largura: | Altura: | Tamanho: 34 KiB |
|
Depois Largura: | Altura: | Tamanho: 21 KiB |
|
Depois Largura: | Altura: | Tamanho: 19 KiB |
|
Depois Largura: | Altura: | Tamanho: 30 KiB |
|
Depois Largura: | Altura: | Tamanho: 25 KiB |
|
Depois Largura: | Altura: | Tamanho: 33 KiB |
|
Depois Largura: | Altura: | Tamanho: 28 KiB |
|
Depois Largura: | Altura: | Tamanho: 30 KiB |
|
Depois Largura: | Altura: | Tamanho: 33 KiB |
|
Depois Largura: | Altura: | Tamanho: 1.1 KiB |
|
Depois Largura: | Altura: | Tamanho: 7.0 KiB |
|
Depois Largura: | Altura: | Tamanho: 34 KiB |
|
Depois Largura: | Altura: | Tamanho: 33 KiB |
|
Depois Largura: | Altura: | Tamanho: 24 KiB |
|
Depois Largura: | Altura: | Tamanho: 1.6 KiB |
|
Depois Largura: | Altura: | Tamanho: 32 KiB |
|
Depois Largura: | Altura: | Tamanho: 40 KiB |
|
Depois Largura: | Altura: | Tamanho: 36 KiB |
|
Depois Largura: | Altura: | Tamanho: 32 KiB |
|
Depois Largura: | Altura: | Tamanho: 71 KiB |
|
Depois Largura: | Altura: | Tamanho: 46 KiB |
|
Depois Largura: | Altura: | Tamanho: 12 KiB |
|
Depois Largura: | Altura: | Tamanho: 13 KiB |
@@ -0,0 +1,83 @@
|
||||
import os
|
||||
import urllib
|
||||
import socket
|
||||
|
||||
from gi.repository import GObject, Nautilus
|
||||
|
||||
class ownCloudExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.InfoProvider):
|
||||
|
||||
nautilusVFSFile_table = {}
|
||||
|
||||
def __init__(self):
|
||||
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
self.sock.connect("/home/kf/.local/share/data/ownCloud/socket")
|
||||
self.sock.settimeout(15)
|
||||
|
||||
GObject.io_add_watch(self.sock, GObject.IO_IN, self.handle_notify)
|
||||
|
||||
def sendCommand(self, cmd):
|
||||
self.sock.send(cmd)
|
||||
|
||||
def find_item_for_file( self, path ):
|
||||
return self.nautilusVFSFile_table[path]
|
||||
|
||||
def callback_update_file( self, path ):
|
||||
print "Got an update callback for " + path
|
||||
|
||||
def askForOverlay(self, file):
|
||||
if os.path.isdir(file):
|
||||
folderStatus = self.sendCommand("RETRIEVE_FOLDER_STATUS:"+file+"\n");
|
||||
|
||||
if os.path.isfile(file):
|
||||
fileStatus = self.sendCommand("RETRIEVE_FILE_STATUS:"+file+"\n");
|
||||
|
||||
# Handles a single line of server respoonse and sets the emblem
|
||||
def handle_server_response(self, l):
|
||||
Emblems = { 'NOP': '',
|
||||
'NEED_SYNC':'view-refresh',
|
||||
'OK': 'dialog-ok' }
|
||||
|
||||
parts = l.split(':')
|
||||
if len(parts) > 2:
|
||||
if parts[0] == 'STATUS':
|
||||
emblem = Emblems[parts[1]]
|
||||
elif parts[0] == 'BROADCAST':
|
||||
emblem = Emblems[parts[1]]
|
||||
else:
|
||||
print "We got unknown status " + parts[0]
|
||||
|
||||
if emblem:
|
||||
item = self.nautilusVFSFile_table[parts[2]]
|
||||
if item:
|
||||
item.set_emblem(emblem)
|
||||
|
||||
# notify is the raw answer from the socket
|
||||
def handle_notify(self, source, condition):
|
||||
print "T "
|
||||
data = source.recv(1024)
|
||||
if len(data) > 0:
|
||||
for l in data.split('\n'):
|
||||
self.handle_server_response( l )
|
||||
|
||||
return True # run again
|
||||
|
||||
def get_local_path(self, path):
|
||||
return path.replace("file://", "")
|
||||
|
||||
def get_columns(self):
|
||||
return Nautilus.Column(name="NautilusPython::share_state_column",
|
||||
attribute="share_state",
|
||||
label="Share State",
|
||||
description="The ownCloud Share State"),
|
||||
|
||||
def update_file_info(self, item):
|
||||
if item.get_uri_scheme() != 'file':
|
||||
return
|
||||
|
||||
filename = urllib.unquote(item.get_uri()[7:])
|
||||
|
||||
self.nautilusVFSFile_table[filename] = item
|
||||
|
||||
print "XXX " + filename
|
||||
item.add_string_attribute('share_state', "share state")
|
||||
self.askForOverlay(filename)
|
||||
@@ -83,7 +83,12 @@ protected:
|
||||
QNetworkRequest req(request);
|
||||
req.setRawHeader(QByteArray("Authorization"), QByteArray("Basic ") + credHash);
|
||||
//qDebug() << "Request for " << req.url() << "with authorization" << QByteArray::fromBase64(credHash);
|
||||
req.setRawHeader(QByteArray("Cookie"), _cred->_token.toLocal8Bit());
|
||||
|
||||
// Append token cookie
|
||||
QList<QNetworkCookie> cookies = request.header(QNetworkRequest::CookieHeader).value<QList<QNetworkCookie> >();
|
||||
cookies.append(QNetworkCookie::parseCookies(_cred->_token.toUtf8()));
|
||||
req.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookies));
|
||||
|
||||
return MirallAccessManager::createRequest(op, req, outgoingData);
|
||||
}
|
||||
private:
|
||||
@@ -112,7 +117,7 @@ void TokenCredentials::syncContextPreInit (CSYNC* ctx)
|
||||
|
||||
void TokenCredentials::syncContextPreStart (CSYNC* ctx)
|
||||
{
|
||||
csync_set_module_property(ctx, "session_key", _token.toLocal8Bit().data());
|
||||
csync_set_module_property(ctx, "session_key", _token.toUtf8().data());
|
||||
}
|
||||
|
||||
bool TokenCredentials::changed(AbstractCredentials* credentials) const
|
||||
|
||||
@@ -99,10 +99,21 @@ bool Folder::init()
|
||||
return false;
|
||||
}
|
||||
|
||||
QString url = Utility::toCSyncScheme(remoteUrl().toString());
|
||||
// We need to reconstruct the url because the path need to be fully decoded, as csync will re-encode the path:
|
||||
// Remember that csync will just append the filename to the path and pass it to the vio plugin.
|
||||
// csync_owncloud will then re-encode everything.
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
QUrl url = remoteUrl();
|
||||
QString url_string = url.scheme() + QLatin1String("://") + url.authority(QUrl::EncodeDelimiters) + url.path(QUrl::FullyDecoded);
|
||||
#else
|
||||
// Qt4 was broken anyway as it did not encode the '#' as it should have done (it was actually a provlem when parsing the path from QUrl::setPath
|
||||
QString url_string = remoteUrl().toString();
|
||||
#endif
|
||||
url_string = Utility::toCSyncScheme(url_string);
|
||||
|
||||
QString localpath = path();
|
||||
|
||||
if( csync_create( &_csync_ctx, localpath.toUtf8().data(), url.toUtf8().data() ) < 0 ) {
|
||||
if( csync_create( &_csync_ctx, localpath.toUtf8().data(), url_string.toUtf8().data() ) < 0 ) {
|
||||
qDebug() << "Unable to create csync-context!";
|
||||
slotSyncError(tr("Unable to create csync-context"));
|
||||
_csync_ctx = 0;
|
||||
@@ -111,9 +122,7 @@ bool Folder::init()
|
||||
csync_set_log_level( 11 );
|
||||
|
||||
MirallConfigFile cfgFile;
|
||||
csync_set_config_dir( _csync_ctx, cfgFile.configPath().toUtf8() );
|
||||
|
||||
setIgnoredFiles();
|
||||
if (Account *account = AccountManager::instance()->account()) {
|
||||
account->credentials()->syncContextPreInit(_csync_ctx);
|
||||
} else {
|
||||
@@ -594,6 +603,7 @@ void Folder::startSync(const QStringList &pathList)
|
||||
connect(_engine.data(), SIGNAL(aboutToRemoveAllFiles(SyncFileItem::Direction,bool*)),
|
||||
SLOT(slotAboutToRemoveAllFiles(SyncFileItem::Direction,bool*)));
|
||||
connect(_engine.data(), SIGNAL(transmissionProgress(Progress::Info)), this, SLOT(slotTransmissionProgress(Progress::Info)));
|
||||
connect(_engine.data(), SIGNAL(jobCompleted(SyncFileItem)), this, SLOT(slotJobCompleted(SyncFileItem)));
|
||||
|
||||
QMetaObject::invokeMethod(_engine.data(), "startSync", Qt::QueuedConnection);
|
||||
|
||||
@@ -677,19 +687,24 @@ void Folder::slotEmitFinishedDelayed()
|
||||
// and hand the result over to the progress dispatcher.
|
||||
void Folder::slotTransmissionProgress(const Progress::Info &pi)
|
||||
{
|
||||
if (!pi._lastCompletedItem.isEmpty()
|
||||
&& Progress::isWarningKind(pi._lastCompletedItem._status)) {
|
||||
// Count all error conditions.
|
||||
_syncResult.setWarnCount(_syncResult.warnCount()+1);
|
||||
}
|
||||
|
||||
// remember problems happening to set the correct Sync status in slot slotCSyncFinished.
|
||||
if( pi._completedFileCount ) {
|
||||
// No job completed yet, this is the beginning of a sync, set the warning level to 0
|
||||
_syncResult.setWarnCount(0);
|
||||
}
|
||||
ProgressDispatcher::instance()->setProgressInfo(alias(), pi);
|
||||
}
|
||||
|
||||
// a job is completed: count the errors and forward to the ProgressDispatcher
|
||||
void Folder::slotJobCompleted(const SyncFileItem &item)
|
||||
{
|
||||
if (Progress::isWarningKind(item._status)) {
|
||||
// Count all error conditions.
|
||||
_syncResult.setWarnCount(_syncResult.warnCount()+1);
|
||||
}
|
||||
emit ProgressDispatcher::instance()->jobCompleted(alias(), item);
|
||||
}
|
||||
|
||||
|
||||
void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction direction, bool *cancel)
|
||||
{
|
||||
#ifndef TOKEN_AUTH_ONLY
|
||||
@@ -719,6 +734,38 @@ void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction direction, bool *
|
||||
#endif
|
||||
}
|
||||
|
||||
// compute the file status of a directory recursively. It returns either
|
||||
// "all in sync" or "needs update" or "error", no more details.
|
||||
SyncFileStatus Folder::recursiveFolderStatus( const QString& fileName )
|
||||
{
|
||||
QDir dir(path() + fileName);
|
||||
|
||||
const QStringList dirEntries = dir.entryList( QDir::AllEntries | QDir::NoDotAndDotDot );
|
||||
|
||||
foreach( const QString entry, dirEntries ) {
|
||||
QFileInfo fi(entry);
|
||||
SyncFileStatus sfs;
|
||||
if( fi.isDir() ) {
|
||||
sfs = recursiveFolderStatus( fileName + QLatin1Char('/') + entry );
|
||||
} else {
|
||||
QString fs( fileName + QLatin1Char('/') + entry );
|
||||
if( fileName.isEmpty() ) {
|
||||
// toplevel, no slash etc. needed.
|
||||
fs = entry;
|
||||
}
|
||||
sfs = fileStatus( fs );
|
||||
}
|
||||
|
||||
if( sfs == FILE_STATUS_STAT_ERROR || sfs == FILE_STATUS_ERROR ) {
|
||||
return FILE_STATUS_ERROR;
|
||||
}
|
||||
if( sfs != FILE_STATUS_SYNC) {
|
||||
return FILE_STATUS_EVAL;
|
||||
}
|
||||
}
|
||||
return FILE_STATUS_SYNC;
|
||||
}
|
||||
|
||||
SyncFileStatus Folder::fileStatus( const QString& fileName )
|
||||
{
|
||||
/*
|
||||
@@ -738,7 +785,11 @@ SyncFileStatus Folder::fileStatus( const QString& fileName )
|
||||
// FIXME: Find a way for STATUS_ERROR
|
||||
SyncFileStatus stat = FILE_STATUS_NONE;
|
||||
|
||||
QString file = path() + fileName;
|
||||
QString file = fileName;
|
||||
if( path() != QLatin1String("/") ) {
|
||||
file = path() + fileName;
|
||||
}
|
||||
|
||||
QFileInfo fi(file);
|
||||
|
||||
if( !fi.exists() ) {
|
||||
@@ -762,20 +813,25 @@ SyncFileStatus Folder::fileStatus( const QString& fileName )
|
||||
}
|
||||
}
|
||||
|
||||
SyncJournalFileRecord rec = _journal.getFileRecord(fileName);
|
||||
if( stat == FILE_STATUS_NONE && !rec.isValid() ) {
|
||||
stat = FILE_STATUS_NEW;
|
||||
}
|
||||
if( type == CSYNC_FTW_TYPE_DIR ) {
|
||||
// compute recursive status of the directory
|
||||
stat = recursiveFolderStatus( fileName );
|
||||
} else {
|
||||
if( stat == FILE_STATUS_NONE ) {
|
||||
SyncJournalFileRecord rec = _journal.getFileRecord(fileName);
|
||||
if( !rec.isValid() ) {
|
||||
stat = FILE_STATUS_NEW;
|
||||
}
|
||||
|
||||
// file was locally modified.
|
||||
if( stat == FILE_STATUS_NONE && fi.lastModified() != rec._modtime ) {
|
||||
stat = FILE_STATUS_EVAL;
|
||||
// file was locally modified.
|
||||
if( stat == FILE_STATUS_NONE && fi.lastModified() != rec._modtime ) {
|
||||
stat = FILE_STATUS_EVAL;
|
||||
}
|
||||
}
|
||||
if( stat == FILE_STATUS_NONE ) {
|
||||
stat = FILE_STATUS_SYNC;
|
||||
}
|
||||
}
|
||||
|
||||
if( stat == FILE_STATUS_NONE ) {
|
||||
stat = FILE_STATUS_SYNC;
|
||||
}
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +76,17 @@ public:
|
||||
*/
|
||||
SyncFileStatus fileStatus( const QString& );
|
||||
|
||||
/**
|
||||
* @brief recursiveFolderStatus
|
||||
* @param fileName - the relative file name to examine
|
||||
* @return the resulting status
|
||||
*
|
||||
* The resulting status can only be either SYNC which means all files
|
||||
* are in sync, ERROR if an error occured, or EVAL if something needs
|
||||
* to be synced underneath this dir.
|
||||
*/
|
||||
SyncFileStatus recursiveFolderStatus( const QString& fileName );
|
||||
|
||||
/**
|
||||
* alias or nickname
|
||||
*/
|
||||
@@ -174,6 +185,7 @@ private slots:
|
||||
void slotSyncFinished();
|
||||
|
||||
void slotTransmissionProgress(const Progress::Info& pi);
|
||||
void slotJobCompleted(const SyncFileItem&);
|
||||
|
||||
void slotPollTimerTimeout();
|
||||
void etagRetreived(const QString &);
|
||||
@@ -186,7 +198,6 @@ private slots:
|
||||
private:
|
||||
bool init();
|
||||
|
||||
|
||||
void setIgnoredFiles();
|
||||
|
||||
void bubbleUpSyncResult();
|
||||
|
||||
@@ -219,10 +219,23 @@ void OwncloudPropagator::start(const SyncFileItemVector& _syncedItems)
|
||||
QVector<PropagatorJob*> directoriesToRemove;
|
||||
QString removedDirectory;
|
||||
foreach(const SyncFileItem &item, items) {
|
||||
if (item._instruction == CSYNC_INSTRUCTION_REMOVE
|
||||
&& !removedDirectory.isEmpty() && item._file.startsWith(removedDirectory)) {
|
||||
//already taken care of. (by the removal of the parent directory)
|
||||
continue;
|
||||
|
||||
if (!removedDirectory.isEmpty() && item._file.startsWith(removedDirectory)) {
|
||||
// this is an item in a directory which is going to be removed.
|
||||
if (item._instruction == CSYNC_INSTRUCTION_REMOVE) {
|
||||
//already taken care of. (by the removal of the parent directory)
|
||||
continue;
|
||||
} else if (item._instruction == CSYNC_INSTRUCTION_NEW && item._isDirectory) {
|
||||
// create a new directory within a deleted directory? That can happen if the directory
|
||||
// etag were not fetched properly on the previous sync because the sync was aborted
|
||||
// while uploading this directory (which is now removed). We can ignore it.
|
||||
continue;
|
||||
} else if (item._instruction == CSYNC_INSTRUCTION_IGNORE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
qWarning() << "WARNING: Job within a removed directory? This should not happen!"
|
||||
<< item._file << item._instruction;
|
||||
}
|
||||
|
||||
while (!item.destination().startsWith(directories.top().first)) {
|
||||
@@ -233,11 +246,21 @@ void OwncloudPropagator::start(const SyncFileItemVector& _syncedItems)
|
||||
PropagateDirectory *dir = new PropagateDirectory(this, item);
|
||||
dir->_firstJob.reset(createJob(item));
|
||||
if (item._instruction == CSYNC_INSTRUCTION_REMOVE) {
|
||||
//We do the removal of directories at the end
|
||||
//We do the removal of directories at the end, because there might be moves from
|
||||
// this directories that will happen later.
|
||||
directoriesToRemove.append(dir);
|
||||
removedDirectory = item._file + "/";
|
||||
|
||||
// We should not update the etag of parent directories of the removed directory
|
||||
// since it would be done before the actual remove (issue #1845)
|
||||
// NOTE: Currently this means that we don't update those etag at all in this sync,
|
||||
// but it should not be a problem, they will be updated in the next sync.
|
||||
for (int i = 0; i < directories.size(); ++i) {
|
||||
directories[i].second->_item._should_update_etag = false;
|
||||
}
|
||||
} else {
|
||||
directories.top().second->append(dir);
|
||||
PropagateDirectory* currentDirJob = directories.top().second;
|
||||
currentDirJob->append(dir);
|
||||
}
|
||||
directories.push(qMakePair(item.destination() + "/" , dir));
|
||||
} else if (PropagateItemJob* current = createJob(item)) {
|
||||
|
||||
@@ -103,6 +103,7 @@ public:
|
||||
static ProgressDispatcher* instance();
|
||||
~ProgressDispatcher();
|
||||
|
||||
|
||||
signals:
|
||||
/**
|
||||
@brief Signals the progress of data transmission.
|
||||
@@ -113,6 +114,11 @@ signals:
|
||||
*/
|
||||
void progressInfo( const QString& folder, const Progress::Info& progress );
|
||||
|
||||
/**
|
||||
* @brief: the item's job is completed
|
||||
*/
|
||||
void jobCompleted(const QString &folder, const SyncFileItem & item);
|
||||
|
||||
protected:
|
||||
void setProgressInfo(const QString& folder, const Progress::Info& progress);
|
||||
|
||||
|
||||
@@ -494,6 +494,10 @@ void PropagateDownloadFileLegacy::start()
|
||||
_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;
|
||||
|
||||
|
||||
@@ -257,6 +257,12 @@ void PropagateUploadFileQNAM::slotPutFinished()
|
||||
errorString += QLatin1String(" (") + rx.cap(1) + QLatin1Char(')');
|
||||
}
|
||||
|
||||
if (_item._httpErrorCode == 412) {
|
||||
// Precondition Failed: Maybe the bad etag is in the database, we need to clear the
|
||||
// parent folder etag so we won't read from DB next sync.
|
||||
_propagator->_journal->avoidReadFromDbOnNextSync(_item._file);
|
||||
}
|
||||
|
||||
done(classifyError(err, _item._httpErrorCode), errorString);
|
||||
return;
|
||||
}
|
||||
@@ -358,13 +364,38 @@ void PropagateUploadFileQNAM::abort()
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// DOES NOT take owncership of the device.
|
||||
GETFileJob::GETFileJob(Account* account, const QString& path, QIODevice *device,
|
||||
const QMap<QByteArray, QByteArray> &headers, QByteArray expectedEtagForResume,
|
||||
QObject* parent)
|
||||
: AbstractNetworkJob(account, path, parent),
|
||||
_device(device), _headers(headers), _expectedEtagForResume(expectedEtagForResume),
|
||||
_errorStatus(SyncFileItem::NoStatus)
|
||||
{
|
||||
}
|
||||
|
||||
GETFileJob::GETFileJob(Account* account, const QUrl& url, QIODevice *device,
|
||||
const QMap<QByteArray, QByteArray> &headers,
|
||||
QObject* parent)
|
||||
: AbstractNetworkJob(account, url.toEncoded(), parent),
|
||||
_device(device), _headers(headers),
|
||||
_errorStatus(SyncFileItem::NoStatus), _directDownloadUrl(url)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void GETFileJob::start() {
|
||||
QNetworkRequest req;
|
||||
for(QMap<QByteArray, QByteArray>::const_iterator it = _headers.begin(); it != _headers.end(); ++it) {
|
||||
req.setRawHeader(it.key(), it.value());
|
||||
}
|
||||
|
||||
setReply(davRequest("GET", path(), req));
|
||||
if (_directDownloadUrl.isEmpty()) {
|
||||
setReply(davRequest("GET", path(), req));
|
||||
} else {
|
||||
// Use direct URL
|
||||
setReply(davRequest("GET", _directDownloadUrl, req));
|
||||
}
|
||||
setupConnections(reply());
|
||||
|
||||
if( reply()->error() != QNetworkReply::NoError ) {
|
||||
@@ -386,17 +417,21 @@ void GETFileJob::slotMetaDataChanged()
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray etag = parseEtag(reply()->rawHeader("Etag"));
|
||||
|
||||
if (etag.isEmpty()) {
|
||||
_etag = parseEtag(reply()->rawHeader("Etag"));
|
||||
if (!_directDownloadUrl.isEmpty() && !_etag.isEmpty()) {
|
||||
qDebug() << Q_FUNC_INFO << "Direct download used, ignoring server ETag" << _etag;
|
||||
_etag = QByteArray(); // reset received ETag
|
||||
} else if (!_directDownloadUrl.isEmpty()) {
|
||||
// All fine, ETag empty and directDownloadUrl used
|
||||
} else if (_etag.isEmpty()) {
|
||||
qDebug() << Q_FUNC_INFO << "No E-Tag reply by server, considering it invalid";
|
||||
_errorString = tr("No E-Tag received from server, check Proxy/Gateway");
|
||||
_errorStatus = SyncFileItem::NormalError;
|
||||
reply()->abort();
|
||||
return;
|
||||
} else if (!_expectedEtagForResume.isEmpty() && _expectedEtagForResume != etag) {
|
||||
} else if (!_expectedEtagForResume.isEmpty() && _expectedEtagForResume != _etag) {
|
||||
qDebug() << Q_FUNC_INFO << "We received a different E-Tag for resuming!"
|
||||
<< _expectedEtagForResume << "vs" << etag;
|
||||
<< _expectedEtagForResume << "vs" << _etag;
|
||||
_errorString = tr("We received a different E-Tag for resuming. Retrying next time.");
|
||||
_errorStatus = SyncFileItem::NormalError;
|
||||
reply()->abort();
|
||||
@@ -431,6 +466,13 @@ void GETFileJob::slotReadyRead()
|
||||
resetTimeout();
|
||||
}
|
||||
|
||||
void GETFileJob::slotTimeout()
|
||||
{
|
||||
_errorString = tr("Connection Timeout");
|
||||
_errorStatus = SyncFileItem::FatalError;
|
||||
reply()->abort();
|
||||
}
|
||||
|
||||
void PropagateDownloadFileQNAM::start()
|
||||
{
|
||||
if (_propagator->_abortRequested.fetchAndAddRelaxed(0))
|
||||
@@ -438,7 +480,7 @@ void PropagateDownloadFileQNAM::start()
|
||||
|
||||
qDebug() << Q_FUNC_INFO << _item._file << _propagator->_activeJobs;
|
||||
|
||||
// do a case clash check.
|
||||
// do a klaas' 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)) );
|
||||
@@ -490,8 +532,6 @@ void PropagateDownloadFileQNAM::start()
|
||||
|
||||
|
||||
QMap<QByteArray, QByteArray> headers;
|
||||
/* Allow compressed content by setting the header */
|
||||
//headers["Accept-Encoding"] = "gzip";
|
||||
|
||||
if (_tmpFile.size() > 0) {
|
||||
quint64 done = _tmpFile.size();
|
||||
@@ -506,9 +546,22 @@ void PropagateDownloadFileQNAM::start()
|
||||
_startSize = done;
|
||||
}
|
||||
|
||||
_job = new GETFileJob(AccountManager::instance()->account(),
|
||||
_propagator->_remoteFolder + _item._file,
|
||||
&_tmpFile, headers, expectedEtagForResume);
|
||||
if (_item._directDownloadUrl.isEmpty()) {
|
||||
// Normal job, download from oC instance
|
||||
_job = new GETFileJob(AccountManager::instance()->account(),
|
||||
_propagator->_remoteFolder + _item._file,
|
||||
&_tmpFile, headers, expectedEtagForResume);
|
||||
} else {
|
||||
// We were provided a direct URL, use that one
|
||||
if (!_item._directDownloadCookies.isEmpty()) {
|
||||
headers["Cookie"] = _item._directDownloadCookies.toUtf8();
|
||||
}
|
||||
QUrl url = QUrl::fromUserInput(_item._directDownloadUrl);
|
||||
_job = new GETFileJob(AccountManager::instance()->account(),
|
||||
url,
|
||||
&_tmpFile, headers);
|
||||
qDebug() << Q_FUNC_INFO << "directDownloadUrl given for " << _item._file << _item._directDownloadUrl;
|
||||
}
|
||||
_job->setTimeout(_propagator->httpTimeout() * 1000);
|
||||
connect(_job, SIGNAL(finishedSignal()), this, SLOT(slotGetFinished()));
|
||||
connect(_job, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(slotDownloadProgress(qint64,qint64)));
|
||||
@@ -546,7 +599,11 @@ void PropagateDownloadFileQNAM::slotGetFinished()
|
||||
return;
|
||||
}
|
||||
|
||||
_item._etag = parseEtag(job->reply()->rawHeader("Etag"));
|
||||
if (!job->etag().isEmpty()) {
|
||||
// The etag will be empty if we used a direct download URL.
|
||||
// (If it was really empty by the server, the GETFileJob will have errored
|
||||
_item._etag = parseEtag(job->etag());
|
||||
}
|
||||
_item._requestDuration = job->duration();
|
||||
_item._responseTimeStamp = job->responseTimestamp();
|
||||
|
||||
@@ -628,13 +685,4 @@ void PropagateDownloadFileQNAM::abort()
|
||||
_job->reply()->abort();
|
||||
}
|
||||
|
||||
void GETFileJob::slotTimeout()
|
||||
{
|
||||
_errorString = tr("Connection Timeout");
|
||||
_errorStatus = SyncFileItem::FatalError;
|
||||
reply()->abort();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -110,15 +110,18 @@ class GETFileJob : public AbstractNetworkJob {
|
||||
QString _errorString;
|
||||
QByteArray _expectedEtagForResume;
|
||||
SyncFileItem::Status _errorStatus;
|
||||
QUrl _directDownloadUrl;
|
||||
QByteArray _etag;
|
||||
public:
|
||||
|
||||
// DOES NOT take owncership of the device.
|
||||
explicit GETFileJob(Account* account, const QString& path, QIODevice *device,
|
||||
const QMap<QByteArray, QByteArray> &headers, QByteArray expectedEtagForResume,
|
||||
QObject* parent = 0)
|
||||
: AbstractNetworkJob(account, path, parent),
|
||||
_device(device), _headers(headers), _expectedEtagForResume(expectedEtagForResume),
|
||||
_errorStatus(SyncFileItem::NoStatus) {}
|
||||
QObject* parent = 0);
|
||||
// For directDownloadUrl:
|
||||
explicit GETFileJob(Account* account, const QUrl& url, QIODevice *device,
|
||||
const QMap<QByteArray, QByteArray> &headers,
|
||||
QObject* parent = 0);
|
||||
|
||||
virtual void start();
|
||||
virtual bool finished() {
|
||||
@@ -134,6 +137,8 @@ public:
|
||||
|
||||
virtual void slotTimeout();
|
||||
|
||||
QByteArray &etag() { return _etag; }
|
||||
|
||||
|
||||
signals:
|
||||
void finishedSignal();
|
||||
|
||||
@@ -226,16 +226,7 @@ void PropagateRemoteRename::start()
|
||||
return;
|
||||
|
||||
if (_item._file == _item._renameTarget) {
|
||||
if (!_item._isDirectory) {
|
||||
// The parents has been renamed already so there is nothing more to do.
|
||||
// But we still need to fetch the new ETAG
|
||||
// FIXME maybe do a recusrsive propfind after having moved the parent.
|
||||
// Note: we also update the mtime because the server do not keep the mtime when moving files
|
||||
QScopedPointer<char, QScopedPointerPodDeleter> uri2(
|
||||
ne_path_escape((_propagator->_remoteDir + _item._renameTarget).toUtf8()));
|
||||
if (!updateMTimeAndETag(uri2.data(), _item._modtime))
|
||||
return;
|
||||
}
|
||||
// The parents has been renamed already so there is nothing more to do.
|
||||
} else if (_item._file == QLatin1String("Shared") ) {
|
||||
// Check if it is the toplevel Shared folder and do not propagate it.
|
||||
if( QFile::rename( _propagator->_localDir + _item._renameTarget, _propagator->_localDir + QLatin1String("Shared")) ) {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "mirall/folderman.h"
|
||||
#include "mirall/folder.h"
|
||||
#include "mirall/utility.h"
|
||||
#include "mirall/theme.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QUrl>
|
||||
@@ -26,12 +27,11 @@
|
||||
#include <QLocalServer>
|
||||
#include <QMetaObject>
|
||||
#include <QStringList>
|
||||
#include <QScopedPointer>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QApplication>
|
||||
|
||||
#include "mirall/utility.h"
|
||||
|
||||
namespace Mirall {
|
||||
|
||||
#define DEBUG qDebug() << "SocketApi: "
|
||||
@@ -42,7 +42,8 @@ SocketApi::SocketApi(QObject* parent, const QUrl& localFile)
|
||||
{
|
||||
QString socketPath;
|
||||
if (Utility::isWindows()) {
|
||||
socketPath = QLatin1String("\\\\.\\pipe\\");
|
||||
socketPath = QLatin1String("\\\\.\\pipe\\")
|
||||
+ Theme::instance()->appName();
|
||||
} else {
|
||||
socketPath = localFile.toLocalFile();
|
||||
|
||||
@@ -51,14 +52,16 @@ SocketApi::SocketApi(QObject* parent, const QUrl& localFile)
|
||||
// setup socket
|
||||
_localServer = new QLocalServer(this);
|
||||
QLocalServer::removeServer(socketPath);
|
||||
if(!_localServer->listen(socketPath))
|
||||
if(!_localServer->listen(socketPath)) {
|
||||
DEBUG << "can't start server" << socketPath;
|
||||
else
|
||||
DEBUG << "server started" << socketPath;
|
||||
connect(_localServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
|
||||
} else {
|
||||
DEBUG << "server started, listening at " << socketPath;
|
||||
}
|
||||
connect(_localServer, SIGNAL(newConnection()), this, SLOT(slotNewConnection()));
|
||||
|
||||
// folder watcher
|
||||
connect(FolderMan::instance(), SIGNAL(folderSyncStateChange(QString)), SLOT(onSyncStateChanged(QString)));
|
||||
connect(FolderMan::instance(), SIGNAL(folderSyncStateChange(QString)), SLOT(slotSyncStateChanged(QString)));
|
||||
connect(ProgressDispatcher::instance(), SIGNAL(jobCompleted(QString,SyncFileItem)), SLOT(slotJobCompleted(QString,SyncFileItem)));
|
||||
}
|
||||
|
||||
SocketApi::~SocketApi()
|
||||
@@ -67,11 +70,14 @@ SocketApi::~SocketApi()
|
||||
_localServer->close();
|
||||
}
|
||||
|
||||
void SocketApi::onNewConnection()
|
||||
void SocketApi::slotNewConnection()
|
||||
{
|
||||
QLocalSocket* socket = _localServer->nextPendingConnection();
|
||||
if( ! socket ) {
|
||||
return;
|
||||
}
|
||||
DEBUG << "New connection " << socket;
|
||||
connect(socket, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
|
||||
connect(socket, SIGNAL(readyRead()), this, SLOT(slotReadSocket()));
|
||||
connect(socket, SIGNAL(disconnected()), this, SLOT(onLostConnection()));
|
||||
Q_ASSERT(socket->readAll().isEmpty());
|
||||
|
||||
@@ -87,13 +93,12 @@ void SocketApi::onLostConnection()
|
||||
}
|
||||
|
||||
|
||||
void SocketApi::onReadyRead()
|
||||
void SocketApi::slotReadSocket()
|
||||
{
|
||||
QLocalSocket* socket = qobject_cast<QLocalSocket*>(sender());
|
||||
Q_ASSERT(socket);
|
||||
|
||||
while(socket->canReadLine())
|
||||
{
|
||||
while(socket->canReadLine()) {
|
||||
QString line = QString::fromUtf8(socket->readLine()).trimmed();
|
||||
QString command = line.split(":").first();
|
||||
QString function = QString(QLatin1String("command_")).append(command);
|
||||
@@ -102,22 +107,36 @@ void SocketApi::onReadyRead()
|
||||
int indexOfMethod = this->metaObject()->indexOfMethod(functionWithArguments.toAscii());
|
||||
|
||||
QString argument = line.remove(0, command.length()+1).trimmed();
|
||||
if(indexOfMethod != -1)
|
||||
{
|
||||
if(indexOfMethod != -1) {
|
||||
QMetaObject::invokeMethod(this, function.toAscii(), Q_ARG(QString, argument), Q_ARG(QLocalSocket*, socket));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
DEBUG << "The command is not supported by this version of the client:" << command << "with argument:" << argument;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SocketApi::onSyncStateChanged(const QString&)
|
||||
void SocketApi::slotSyncStateChanged(const QString&)
|
||||
{
|
||||
broadcastMessage("UPDATE_VIEW");
|
||||
}
|
||||
|
||||
void SocketApi::slotJobCompleted(const QString &folder, const SyncFileItem &item)
|
||||
{
|
||||
Folder *f = FolderMan::instance()->folder(folder);
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
const QString path = f->path() + item.destination();
|
||||
|
||||
QString command = QLatin1String("OK");
|
||||
if (Progress::isWarningKind(item._status)) {
|
||||
command = QLatin1String("ERROR");
|
||||
}
|
||||
|
||||
broadcastMessage(QLatin1String("BROADCAST:") + command + QLatin1Char(':') + path);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SocketApi::sendMessage(QLocalSocket* socket, const QString& message)
|
||||
{
|
||||
@@ -138,66 +157,95 @@ void SocketApi::broadcastMessage(const QString& message)
|
||||
void SocketApi::command_RETRIEVE_FOLDER_STATUS(const QString& argument, QLocalSocket* socket)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << argument;
|
||||
//TODO: do security checks?!
|
||||
Folder* folder = FolderMan::instance()->folderForPath( argument );
|
||||
// this can happen in offline mode e.g.: nothing to worry about
|
||||
if(!folder)
|
||||
{
|
||||
DEBUG << "folder offline or not watched:" << argument;
|
||||
QString statusString;
|
||||
|
||||
if( !socket ) {
|
||||
qDebug() << "No valid socket object.";
|
||||
return;
|
||||
}
|
||||
|
||||
QDir dir(argument);
|
||||
foreach(QString entry, dir.entryList(QDir::AllEntries|QDir::NoDotAndDotDot))
|
||||
{
|
||||
QString absoluteFilePath = dir.absoluteFilePath(entry);
|
||||
QString statusString;
|
||||
SyncFileStatus fileStatus = folder->fileStatus(absoluteFilePath.mid(folder->path().length()));
|
||||
switch(fileStatus)
|
||||
{
|
||||
case FILE_STATUS_NONE:
|
||||
statusString = QLatin1String("STATUS_NONE");
|
||||
break;
|
||||
case FILE_STATUS_EVAL:
|
||||
statusString = QLatin1String("STATUS_EVAL");
|
||||
break;
|
||||
case FILE_STATUS_REMOVE:
|
||||
statusString = QLatin1String("STATUS_REMOVE");
|
||||
break;
|
||||
case FILE_STATUS_RENAME:
|
||||
statusString = QLatin1String("STATUS_RENAME");
|
||||
break;
|
||||
case FILE_STATUS_NEW:
|
||||
statusString = QLatin1String("STATUS_NEW");
|
||||
break;
|
||||
case FILE_STATUS_CONFLICT:
|
||||
statusString = QLatin1String("STATUS_CONFLICT");
|
||||
break;
|
||||
case FILE_STATUS_IGNORE:
|
||||
statusString = QLatin1String("STATUS_IGNORE");
|
||||
break;
|
||||
case FILE_STATUS_SYNC:
|
||||
statusString = QLatin1String("STATUS_SYNC");
|
||||
break;
|
||||
case FILE_STATUS_STAT_ERROR:
|
||||
statusString = QLatin1String("STATUS_STAT_ERROR");
|
||||
break;
|
||||
case FILE_STATUS_ERROR:
|
||||
statusString = QLatin1String("STATUS_ERROR");
|
||||
break;
|
||||
case FILE_STATUS_UPDATED:
|
||||
statusString = QLatin1String("STATUS_UPDATED");
|
||||
break;
|
||||
default:
|
||||
qWarning() << "not all SyncFileStatus items checked!";
|
||||
Q_ASSERT(false);
|
||||
statusString = QLatin1String("STATUS_NONE");
|
||||
|
||||
}
|
||||
QString message("%1:%2:%3");
|
||||
message = message.arg("STATUS").arg(statusString).arg(absoluteFilePath);
|
||||
sendMessage(socket, message);
|
||||
Folder* folder = FolderMan::instance()->folderForPath( argument );
|
||||
// this can happen in offline mode e.g.: nothing to worry about
|
||||
if (!folder) {
|
||||
DEBUG << "folder offline or not watched:" << argument;
|
||||
statusString = QLatin1String("NOP");
|
||||
}
|
||||
|
||||
QDir dir(argument);
|
||||
if( statusString.isEmpty() ) {
|
||||
const QStringList fileEntries = dir.entryList( QDir::Files );
|
||||
foreach(const QString file, fileEntries) {
|
||||
const QString absoluteFilePath = dir.absoluteFilePath(file);
|
||||
SyncFileStatus fileStatus = folder->fileStatus( absoluteFilePath.mid(folder->path().length()) );
|
||||
if( fileStatus == FILE_STATUS_STAT_ERROR ) {
|
||||
qDebug() << "XXXXXXXXXXXX FileStatus is STAT ERROR for " << absoluteFilePath;
|
||||
}
|
||||
if( fileStatus != FILE_STATUS_SYNC ) {
|
||||
qDebug() << "SyncFileStatus for " << absoluteFilePath << " is " << fileStatus;
|
||||
// we found something that is not in sync
|
||||
statusString = QLatin1String("NEED_SYNC");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( statusString.isEmpty() ) { // if it is still empty, we check the dirs recursively.
|
||||
const QStringList dirEntries = dir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot );
|
||||
|
||||
foreach(const QString entry, dirEntries) {
|
||||
QString absoluteFilePath = dir.absoluteFilePath(entry);
|
||||
SyncFileStatus sfs = folder->recursiveFolderStatus( absoluteFilePath.mid(folder->path().length()) );
|
||||
if( sfs != FILE_STATUS_SYNC ) {
|
||||
statusString = QLatin1String("NEED_SYNC");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( statusString.isEmpty() ) {
|
||||
statusString = QLatin1String("OK");
|
||||
}
|
||||
|
||||
QString message = QLatin1String("STATUS:")+statusString+QLatin1Char(':')+argument;
|
||||
sendMessage(socket, message);
|
||||
}
|
||||
|
||||
void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, QLocalSocket* socket)
|
||||
{
|
||||
if( !socket ) {
|
||||
qDebug() << "No valid socket object.";
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << Q_FUNC_INFO << argument;
|
||||
|
||||
QString statusString;
|
||||
|
||||
Folder* folder = FolderMan::instance()->folderForPath( argument );
|
||||
// this can happen in offline mode e.g.: nothing to worry about
|
||||
if (!folder) {
|
||||
DEBUG << "folder offline or not watched:" << argument;
|
||||
statusString = QLatin1String("NOP");
|
||||
}
|
||||
|
||||
if( statusString.isEmpty() ) {
|
||||
SyncFileStatus fileStatus = folder->fileStatus( argument.mid(folder->path().length()) );
|
||||
if( fileStatus == FILE_STATUS_STAT_ERROR ) {
|
||||
qDebug() << "XXXXXXXXXXXX FileStatus is STAT ERROR for " << argument;
|
||||
}
|
||||
if( fileStatus != FILE_STATUS_SYNC ) {
|
||||
qDebug() << "SyncFileStatus for " << argument << " is " << fileStatus;
|
||||
// we found something that is not in sync
|
||||
statusString = QLatin1String("NEED_SYNC");
|
||||
}
|
||||
}
|
||||
|
||||
if( statusString.isEmpty() ) {
|
||||
statusString = QLatin1String("OK");
|
||||
}
|
||||
|
||||
QString message = QLatin1String("STATUS:")+statusString+QLatin1Char(':')+argument;
|
||||
sendMessage(socket, message);
|
||||
}
|
||||
|
||||
} // namespace Mirall
|
||||
|
||||
@@ -25,6 +25,8 @@ class QStringList;
|
||||
|
||||
namespace Mirall {
|
||||
|
||||
class SyncFileItem;
|
||||
|
||||
class SocketApi : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -34,16 +36,18 @@ public:
|
||||
virtual ~SocketApi();
|
||||
|
||||
private slots:
|
||||
void onNewConnection();
|
||||
void slotNewConnection();
|
||||
void onLostConnection();
|
||||
void onReadyRead();
|
||||
void onSyncStateChanged(const QString&);
|
||||
void slotReadSocket();
|
||||
void slotSyncStateChanged(const QString&);
|
||||
void slotJobCompleted(const QString &, const SyncFileItem &);
|
||||
|
||||
private:
|
||||
void sendMessage(QLocalSocket* socket, const QString& message);
|
||||
void broadcastMessage(const QString& message);
|
||||
|
||||
Q_INVOKABLE void command_RETRIEVE_FOLDER_STATUS(const QString& argument, QLocalSocket* socket);
|
||||
Q_INVOKABLE void command_RETRIEVE_FILE_STATUS(const QString& argument, QLocalSocket* socket);
|
||||
|
||||
private:
|
||||
QLocalServer* _localServer;
|
||||
|
||||
@@ -263,6 +263,12 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
item._instruction = file->instruction;
|
||||
item._direction = SyncFileItem::None;
|
||||
item._fileId = file->file_id;
|
||||
if (file->directDownloadUrl) {
|
||||
item._directDownloadUrl = QString::fromUtf8( file->directDownloadUrl );
|
||||
}
|
||||
if (file->directDownloadCookies) {
|
||||
item._directDownloadCookies = QString::fromUtf8( file->directDownloadCookies );
|
||||
}
|
||||
|
||||
// record the seen files to be able to clean the journal later
|
||||
_seenFiles[item._file] = QString();
|
||||
@@ -287,7 +293,6 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
Q_ASSERT("Non handled error-status");
|
||||
/* No error string */
|
||||
}
|
||||
|
||||
item._isDirectory = file->type == CSYNC_FTW_TYPE_DIR;
|
||||
item._modtime = file->modtime;
|
||||
item._etag = file->etag;
|
||||
@@ -464,7 +469,6 @@ void SyncEngine::startSync()
|
||||
}
|
||||
}
|
||||
|
||||
csync_set_module_property(_csync_ctx, "csync_context", _csync_ctx);
|
||||
csync_set_userdata(_csync_ctx, this);
|
||||
// TODO: This should be a part of this method, but we don't have
|
||||
// any way to get "session_key" module property from csync. Had we
|
||||
|
||||
@@ -86,6 +86,8 @@ public:
|
||||
quint64 _inode;
|
||||
bool _should_update_etag;
|
||||
QByteArray _fileId;
|
||||
QString _directDownloadUrl;
|
||||
QString _directDownloadCookies;
|
||||
bool _blacklistedInDb;
|
||||
|
||||
// Variables usefull to report to the user
|
||||
|
||||
@@ -485,7 +485,7 @@ SyncJournalFileRecord SyncJournalDb::getFileRecord( const QString& filename )
|
||||
_getFileRecordQuery->finish();
|
||||
} else {
|
||||
QString err = _getFileRecordQuery->lastError().text();
|
||||
qDebug() << "Can not query " << _getFileRecordQuery->lastQuery() << ", Error:" << err;
|
||||
qDebug() << "No journal entry found for " << filename;
|
||||
}
|
||||
}
|
||||
return rec;
|
||||
@@ -835,6 +835,28 @@ void SyncJournalDb::avoidRenamesOnNextSync(const QString& path)
|
||||
}
|
||||
}
|
||||
|
||||
void SyncJournalDb::avoidReadFromDbOnNextSync(const QString& fileName)
|
||||
{
|
||||
//Make sure that on the next sync, filName is not read from the DB but use the PROPFIND to
|
||||
//get the info from the server
|
||||
// We achieve that by clearing the etag of the parents directory recursively
|
||||
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
||||
if( !checkConnect() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
QSqlQuery query(_db);
|
||||
// This query will match entries for whitch the path is a prefix of fileName
|
||||
query.prepare("UPDATE metadata SET md5='_invalid_' WHERE ? LIKE(path||'/%') AND type == 2"); // CSYNC_FTW_TYPE_DIR == 2
|
||||
query.bindValue(0, fileName);
|
||||
if( !query.exec() ) {
|
||||
qDebug() << "SQL error in avoidRenamesOnNextSync: "<< query.lastError().text();
|
||||
} else {
|
||||
qDebug() << query.executedQuery() << fileName;
|
||||
}
|
||||
}
|
||||
|
||||
void SyncJournalDb::commit(const QString& context, bool startTrans)
|
||||
{
|
||||
|
||||
@@ -73,6 +73,12 @@ public:
|
||||
SyncJournalBlacklistRecord blacklistEntry( const QString& );
|
||||
void avoidRenamesOnNextSync(const QString &path);
|
||||
|
||||
/**
|
||||
* Make sure that on the next sync, filName is not read from the DB but use the PROPFIND to
|
||||
* get the info from the server
|
||||
*/
|
||||
void avoidReadFromDbOnNextSync(const QString& fileName);
|
||||
|
||||
bool postSyncCleanup( const QHash<QString, QString>& items );
|
||||
|
||||
/* Because sqlite transactions is really slow, we encapsulate everything in big transactions
|
||||
|
||||
@@ -212,7 +212,7 @@ QString Theme::about() const
|
||||
"<p>Distributed by %4 and licensed under the GNU General Public License (GPL) Version 2.0.<br>"
|
||||
"%5 and the %5 logo are registered trademarks of %4 in the<br>"
|
||||
"United States, other countries, or both.</p>")
|
||||
.arg(MIRALL_VERSION_MAJOR).arg("http://" MIRALL_STRINGIFY(APPLICATION_DOMAIN))
|
||||
.arg(MIRALL_VERSION_STRING).arg("http://" MIRALL_STRINGIFY(APPLICATION_DOMAIN))
|
||||
.arg(MIRALL_STRINGIFY(APPLICATION_DOMAIN)).arg(APPLICATION_VENDOR).arg(APPLICATION_NAME);
|
||||
}
|
||||
|
||||
|
||||
@@ -260,100 +260,100 @@
|
||||
<context>
|
||||
<name>Mirall::Folder</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="107"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="118"/>
|
||||
<source>Unable to create csync-context</source>
|
||||
<translation>No s'ha pogut crear el context-csync</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="165"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="174"/>
|
||||
<source>Local folder %1 does not exist.</source>
|
||||
<translation>El fitxer local %1 no existeix.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="168"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="177"/>
|
||||
<source>%1 should be a directory but is not.</source>
|
||||
<translation>%1 hauria de ser una carpeta, però no ho és.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="171"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="180"/>
|
||||
<source>%1 is not readable.</source>
|
||||
<translation>No es pot llegir %1.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="323"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="332"/>
|
||||
<source>%1: %2</source>
|
||||
<translation>%1: %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="409"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="418"/>
|
||||
<source>%1 and %2 other files have been removed.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>%1 i %2 altres fitxers s'han esborrat</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="411"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="420"/>
|
||||
<source>%1 has been removed.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>S'ha esborrat '%1'</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="416"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="425"/>
|
||||
<source>%1 and %2 other files have been downloaded.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>%1 i %2 altres fitxers s'han descarregat.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="418"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="427"/>
|
||||
<source>%1 has been downloaded.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>S'ha descarregat %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="423"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="432"/>
|
||||
<source>%1 and %2 other files have been updated.</source>
|
||||
<translation>%1 i %2 altres fitxer(s) s'han actualitzat.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="425"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="434"/>
|
||||
<source>%1 has been updated.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>S'ha actualitzat %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="430"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="439"/>
|
||||
<source>%1 has been renamed to %2 and %3 other files have been renamed.</source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="432"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="441"/>
|
||||
<source>%1 has been renamed to %2.</source>
|
||||
<comment>%1 and %2 name files.</comment>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="437"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="446"/>
|
||||
<source>%1 has been moved to %2 and %3 other files have been moved.</source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="439"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="448"/>
|
||||
<source>%1 has been moved to %2.</source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="447"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="456"/>
|
||||
<source>Sync Activity</source>
|
||||
<translation>Activitat de sincronització</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="697"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="712"/>
|
||||
<source>This sync would remove all the files in the local sync folder '%1'.
|
||||
If you or your administrator have reset your account on the server, choose "Keep files". If you want your data to be removed, choose "Remove all files".</source>
|
||||
<translation>Aquesta sincronització eliminarà tots els fitxers a la carpeta local de sincronització '%1'.
|
||||
Si vós o l'administrador heu reinicialitzat el compte en el servidor, escolliu "Mantenir fitxers". Si voleueliminar les dades, escolliu "Esborra tots els fitxers".</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="700"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="715"/>
|
||||
<source>This sync would remove all the files in the sync folder '%1'.
|
||||
This might be because the folder was silently reconfigured, or that all the file were manually removed.
|
||||
Are you sure you want to perform this operation?</source>
|
||||
@@ -362,17 +362,17 @@ Això podria ser perquè la carpeta ha estat reconfigurada silenciosament, o que
|
||||
Esteu segur que voleu executar aquesta operació?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="704"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="719"/>
|
||||
<source>Remove All Files?</source>
|
||||
<translation>Esborra tots els fitxers?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="706"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="721"/>
|
||||
<source>Remove all files</source>
|
||||
<translation>Esborra tots els fitxers</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="707"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="722"/>
|
||||
<source>Keep files</source>
|
||||
<translation>Mantén els fitxers</translation>
|
||||
</message>
|
||||
@@ -596,17 +596,17 @@ Esteu segur que voleu executar aquesta operació?</translation>
|
||||
<context>
|
||||
<name>Mirall::GETFileJob</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="393"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="428"/>
|
||||
<source>No E-Tag received from server, check Proxy/Gateway</source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="400"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="435"/>
|
||||
<source>We received a different E-Tag for resuming. Retrying next time.</source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="633"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="471"/>
|
||||
<source>Connection Timeout</source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
@@ -1278,7 +1278,7 @@ No és aconsellada usar-la.</translation>
|
||||
<context>
|
||||
<name>Mirall::PropagateDownloadFileQNAM</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="443"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="485"/>
|
||||
<source>File %1 can not be downloaded because of a local file name clash!</source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
@@ -1336,17 +1336,17 @@ No és aconsellada usar-la.</translation>
|
||||
<context>
|
||||
<name>Mirall::PropagateRemoteRename</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="242"/>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="233"/>
|
||||
<source>This folder must not be renamed. It is renamed back to its original name.</source>
|
||||
<translation>No s'ha de canviar el nom d'aquesta carpeta. Es reanomena de nou amb el seu nom original.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="244"/>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="235"/>
|
||||
<source>This folder must not be renamed. Please name it back to Shared.</source>
|
||||
<translation>Aquesta carpeta no es pot reanomenar. Reanomeneu-la de nou Shared.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="259"/>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="250"/>
|
||||
<source>The file was renamed but is part of a read only share. The original file was restored.</source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
@@ -1378,12 +1378,12 @@ No és aconsellada usar-la.</translation>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="272"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="278"/>
|
||||
<source>Local file changed during sync.</source>
|
||||
<translation>El fitxer local ha canviat durant la sincronització.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="282"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="288"/>
|
||||
<source>The server did not acknowledge the last chunk. (No e-tag were present)</source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
@@ -1537,12 +1537,12 @@ Proveu de sincronitzar-los de nou.</translation>
|
||||
<context>
|
||||
<name>Mirall::ShibbolethCredentials</name>
|
||||
<message>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="259"/>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="267"/>
|
||||
<source>Login Error</source>
|
||||
<translation>Error d'accés</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="259"/>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="267"/>
|
||||
<source>You must sign in as user %1</source>
|
||||
<translation>Cal identificar-se com a usuari %1</translation>
|
||||
</message>
|
||||
@@ -1925,27 +1925,27 @@ Proveu de sincronitzar-los de nou.</translation>
|
||||
<translation>L'element no s'ha sincronitzat degut a errors previs: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="274"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="280"/>
|
||||
<source>Symbolic links are not supported in syncing.</source>
|
||||
<translation>La sincronització d'enllaços simbòlics no està implementada.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="277"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="283"/>
|
||||
<source>File is listed on the ignore list.</source>
|
||||
<translation>El fitxer està a la llista d'ignorats.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="280"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="286"/>
|
||||
<source>File contains invalid characters that can not be synced cross platform.</source>
|
||||
<translation>El fitxer conté caràcters no vàlids que no es poden sincronitzar entre plataformes.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="448"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="453"/>
|
||||
<source>Unable to initialize a sync journal.</source>
|
||||
<translation>No es pot inicialitzar un periòdic de sincronització</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="545"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="549"/>
|
||||
<source>Cannot open the sync journal</source>
|
||||
<translation>No es pot obrir el diari de sincronització</translation>
|
||||
</message>
|
||||
|
||||
@@ -260,100 +260,100 @@
|
||||
<context>
|
||||
<name>Mirall::Folder</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="107"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="118"/>
|
||||
<source>Unable to create csync-context</source>
|
||||
<translation>Nepodařilo se vytvořit csync-context</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="165"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="174"/>
|
||||
<source>Local folder %1 does not exist.</source>
|
||||
<translation>Místní složka %1 neexistuje.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="168"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="177"/>
|
||||
<source>%1 should be a directory but is not.</source>
|
||||
<translation>%1 by měl být adresář, ale není.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="171"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="180"/>
|
||||
<source>%1 is not readable.</source>
|
||||
<translation>%1 není čitelný.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="323"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="332"/>
|
||||
<source>%1: %2</source>
|
||||
<translation>%1: %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="409"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="418"/>
|
||||
<source>%1 and %2 other files have been removed.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>%1 a %2 dalších souborů bylo odebráno.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="411"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="420"/>
|
||||
<source>%1 has been removed.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>%1 byl odebrán.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="416"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="425"/>
|
||||
<source>%1 and %2 other files have been downloaded.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>%1 a %2 dalších souborů bylo staženo.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="418"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="427"/>
|
||||
<source>%1 has been downloaded.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>%1 byl stažen.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="423"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="432"/>
|
||||
<source>%1 and %2 other files have been updated.</source>
|
||||
<translation>%1 a %2 dalších souborů bylo aktualizováno.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="425"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="434"/>
|
||||
<source>%1 has been updated.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>%1 byl aktualizován.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="430"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="439"/>
|
||||
<source>%1 has been renamed to %2 and %3 other files have been renamed.</source>
|
||||
<translation>%1 byl přejmenován na %2 a %3 dalších souborů bylo přejmenováno.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="432"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="441"/>
|
||||
<source>%1 has been renamed to %2.</source>
|
||||
<comment>%1 and %2 name files.</comment>
|
||||
<translation>%1 byl přejmenován na %2.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="437"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="446"/>
|
||||
<source>%1 has been moved to %2 and %3 other files have been moved.</source>
|
||||
<translation>%1 byl přesunut do %2 a %3 dalších souborů bylo přesunuto.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="439"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="448"/>
|
||||
<source>%1 has been moved to %2.</source>
|
||||
<translation>%1 byl přemístěn do %2.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="447"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="456"/>
|
||||
<source>Sync Activity</source>
|
||||
<translation>Průběh synchronizace</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="697"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="712"/>
|
||||
<source>This sync would remove all the files in the local sync folder '%1'.
|
||||
If you or your administrator have reset your account on the server, choose "Keep files". If you want your data to be removed, choose "Remove all files".</source>
|
||||
<translation>Tato synchronizace by smazala všechny soubory v místní složce '%1'
|
||||
Pokud jste vy nebo váš správce zresetovali účet na serveru, zvolte "Ponechat soubory". Pokud chcete místní data odstranit, zvolte "Odstranit všechny soubory".</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="700"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="715"/>
|
||||
<source>This sync would remove all the files in the sync folder '%1'.
|
||||
This might be because the folder was silently reconfigured, or that all the file were manually removed.
|
||||
Are you sure you want to perform this operation?</source>
|
||||
@@ -362,17 +362,17 @@ Toto může být způsobeno změnou v nastavení synchronizace složky nebo tím
|
||||
Opravdu chcete provést tuto akci?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="704"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="719"/>
|
||||
<source>Remove All Files?</source>
|
||||
<translation>Odstranit všechny soubory?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="706"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="721"/>
|
||||
<source>Remove all files</source>
|
||||
<translation>Odstranit všechny soubory</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="707"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="722"/>
|
||||
<source>Keep files</source>
|
||||
<translation>Ponechat soubory</translation>
|
||||
</message>
|
||||
@@ -513,7 +513,7 @@ Opravdu chcete provést tuto akci?</translation>
|
||||
<message>
|
||||
<location filename="../src/mirall/folderwizard.cpp" line="139"/>
|
||||
<source>The selected folder is a symbolic link. An already configured folder is contained in the folder this link is pointing to.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Vybraná složka je symbolický odkaz. Cílová složka tohoto odkazu již obsahuje nastavenou složku.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folderwizard.cpp" line="146"/>
|
||||
@@ -596,17 +596,17 @@ Opravdu chcete provést tuto akci?</translation>
|
||||
<context>
|
||||
<name>Mirall::GETFileJob</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="393"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="428"/>
|
||||
<source>No E-Tag received from server, check Proxy/Gateway</source>
|
||||
<translation>Ze serveru nebyl obdržen E-Tag, zkontrolujte proxy/bránu</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="400"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="435"/>
|
||||
<source>We received a different E-Tag for resuming. Retrying next time.</source>
|
||||
<translation>Obdrželi jsme jiný E-Tag pro pokračování. Zkusím znovu příště.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="633"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="471"/>
|
||||
<source>Connection Timeout</source>
|
||||
<translation>Spojení Vypršelo</translation>
|
||||
</message>
|
||||
@@ -1272,15 +1272,15 @@ Nedoporučuje se jí používat.</translation>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_legacy.cpp" line="449"/>
|
||||
<source>File %1 can not be downloaded because of a local file name clash!</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Soubor %1 nemohl být stažen z důvodu kolize názvu se souborem v místním systému.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Mirall::PropagateDownloadFileQNAM</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="443"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="485"/>
|
||||
<source>File %1 can not be downloaded because of a local file name clash!</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Soubor %1 nemohl být stažen z důvodu kolize názvu se souborem v místním systému.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@@ -1309,7 +1309,7 @@ Nedoporučuje se jí používat.</translation>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="80"/>
|
||||
<source>Could not remove %1 because of a local file name clash</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>%1 nebylo možno odstranit z důvodu kolize názvu se souborem v místním systému.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="87"/>
|
||||
@@ -1322,7 +1322,7 @@ Nedoporučuje se jí používat.</translation>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="196"/>
|
||||
<source>File %1 can not be renamed to %2 because of a local file name clash</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Soubor %1 nemohl být přejmenován na %2 z důvodu kolize názvu se souborem v místním systému.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@@ -1336,17 +1336,17 @@ Nedoporučuje se jí používat.</translation>
|
||||
<context>
|
||||
<name>Mirall::PropagateRemoteRename</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="242"/>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="233"/>
|
||||
<source>This folder must not be renamed. It is renamed back to its original name.</source>
|
||||
<translation>Tato složka nemůže být přejmenována. Byl jí vrácen původní název.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="244"/>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="235"/>
|
||||
<source>This folder must not be renamed. Please name it back to Shared.</source>
|
||||
<translation>Tato složka nemůže být přejmenována. Přejmenujte jí prosím zpět na Shared.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="259"/>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="250"/>
|
||||
<source>The file was renamed but is part of a read only share. The original file was restored.</source>
|
||||
<translation>Soubor byl přejmenován, ale je součástí sdílení pouze pro čtení. Původní soubor byl obnoven.</translation>
|
||||
</message>
|
||||
@@ -1378,12 +1378,12 @@ Nedoporučuje se jí používat.</translation>
|
||||
<translation>Soubor zde byl editován, ale je součástí sdílení pouze pro čtení. Původní soubor byl obnoven a editovaná verze je uložena v konfliktním souboru.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="272"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="278"/>
|
||||
<source>Local file changed during sync.</source>
|
||||
<translation>Místní soubor byl změněn během synchronizace.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="282"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="288"/>
|
||||
<source>The server did not acknowledge the last chunk. (No e-tag were present)</source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
@@ -1538,12 +1538,12 @@ Zkuste provést novou synchronizaci.
|
||||
<context>
|
||||
<name>Mirall::ShibbolethCredentials</name>
|
||||
<message>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="259"/>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="267"/>
|
||||
<source>Login Error</source>
|
||||
<translation>Chyba přihlášení</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="259"/>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="267"/>
|
||||
<source>You must sign in as user %1</source>
|
||||
<translation>Musíte se přihlásit jako uživatel %1</translation>
|
||||
</message>
|
||||
@@ -1558,12 +1558,12 @@ Zkuste provést novou synchronizaci.
|
||||
<message>
|
||||
<location filename="../src/creds/shibboleth/shibbolethwebview.cpp" line="62"/>
|
||||
<source>Reauthentication required</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Je vyžadováno opětovné ověření.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/creds/shibboleth/shibbolethwebview.cpp" line="62"/>
|
||||
<source>Your session has expired. You need to re-login to continue to use the client.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Vaše sezení vypršelo. Chcete-li pokračovat v práci musíte se znovu přihlásit.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/creds/shibboleth/shibbolethwebview.cpp" line="101"/>
|
||||
@@ -1926,27 +1926,27 @@ Zkuste provést novou synchronizaci.
|
||||
<translation>Položka nebyla synchronizována kvůli předchozí chybě: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="274"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="280"/>
|
||||
<source>Symbolic links are not supported in syncing.</source>
|
||||
<translation>Symbolické odkazy nejsou při synchronizaci podporovány.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="277"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="283"/>
|
||||
<source>File is listed on the ignore list.</source>
|
||||
<translation>Soubor se nachází na seznamu ignorovaných.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="280"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="286"/>
|
||||
<source>File contains invalid characters that can not be synced cross platform.</source>
|
||||
<translation>Soubor obsahuje alespoň jeden neplatný znak, který narušuje synchronizaci v prostředí více platforem.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="448"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="453"/>
|
||||
<source>Unable to initialize a sync journal.</source>
|
||||
<translation>Nemohu inicializovat synchronizační žurnál.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="545"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="549"/>
|
||||
<source>Cannot open the sync journal</source>
|
||||
<translation>Nelze otevřít synchronizační žurnál</translation>
|
||||
</message>
|
||||
|
||||
@@ -261,100 +261,100 @@ Diese Funktion ist nur für Wartungszwecke gedacht. Es werden keine Dateien entf
|
||||
<context>
|
||||
<name>Mirall::Folder</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="107"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="118"/>
|
||||
<source>Unable to create csync-context</source>
|
||||
<translation>Kann keinen CSync-Kontext erstellen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="165"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="174"/>
|
||||
<source>Local folder %1 does not exist.</source>
|
||||
<translation>Lokales Verzeichnis %1 existiert nicht.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="168"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="177"/>
|
||||
<source>%1 should be a directory but is not.</source>
|
||||
<translation>%1 sollte ein Verzeichnis sein, ist es aber nicht.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="171"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="180"/>
|
||||
<source>%1 is not readable.</source>
|
||||
<translation>%1 ist nicht lesbar.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="323"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="332"/>
|
||||
<source>%1: %2</source>
|
||||
<translation>%1: %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="409"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="418"/>
|
||||
<source>%1 and %2 other files have been removed.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>%1 und %2 andere Dateien wurden gelöscht.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="411"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="420"/>
|
||||
<source>%1 has been removed.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>%1 wurde gelöscht.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="416"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="425"/>
|
||||
<source>%1 and %2 other files have been downloaded.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>%1 und %2 andere Dateien wurden heruntergeladen.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="418"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="427"/>
|
||||
<source>%1 has been downloaded.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>%1 wurde heruntergeladen.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="423"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="432"/>
|
||||
<source>%1 and %2 other files have been updated.</source>
|
||||
<translation>%1 und %2 andere Dateien wurden aktualisiert.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="425"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="434"/>
|
||||
<source>%1 has been updated.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>%1 wurde aktualisiert.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="430"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="439"/>
|
||||
<source>%1 has been renamed to %2 and %3 other files have been renamed.</source>
|
||||
<translation>%1 wurde in %2 umbenannt und %3 andere Dateien wurden umbenannt.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="432"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="441"/>
|
||||
<source>%1 has been renamed to %2.</source>
|
||||
<comment>%1 and %2 name files.</comment>
|
||||
<translation>%1 wurde in %2 umbenannt.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="437"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="446"/>
|
||||
<source>%1 has been moved to %2 and %3 other files have been moved.</source>
|
||||
<translation>%1 wurde in %2 verschoben und %3 andere Dateien wurden verschoben.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="439"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="448"/>
|
||||
<source>%1 has been moved to %2.</source>
|
||||
<translation>%1 wurde in %2 verschoben.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="447"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="456"/>
|
||||
<source>Sync Activity</source>
|
||||
<translation>Synchronisierungsaktivität</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="697"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="712"/>
|
||||
<source>This sync would remove all the files in the local sync folder '%1'.
|
||||
If you or your administrator have reset your account on the server, choose "Keep files". If you want your data to be removed, choose "Remove all files".</source>
|
||||
<translation>Dieser Synchronisationsvorgang würde alle Dateien in dem lokalen Ordner '%1' entfernen.
|
||||
Wenn Sie oder Ihr Administrator Ihr Konto auf dem Server zurückgesetzt haben, wählen Sie "Dateien behalten". Wenn Sie ihre Daten löschen wollen, wählen Sie "Alle Dateien entfernen".</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="700"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="715"/>
|
||||
<source>This sync would remove all the files in the sync folder '%1'.
|
||||
This might be because the folder was silently reconfigured, or that all the file were manually removed.
|
||||
Are you sure you want to perform this operation?</source>
|
||||
@@ -363,17 +363,17 @@ Vielleicht wurde der Ordner neu konfiguriert, oder alle Dateien wurden händisch
|
||||
Sind Sie sicher, dass sie diese Operation durchführen wollen?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="704"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="719"/>
|
||||
<source>Remove All Files?</source>
|
||||
<translation>Alle Dateien löschen?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="706"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="721"/>
|
||||
<source>Remove all files</source>
|
||||
<translation>Lösche alle Dateien</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="707"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="722"/>
|
||||
<source>Keep files</source>
|
||||
<translation>Dateien behalten</translation>
|
||||
</message>
|
||||
@@ -597,17 +597,17 @@ Sind Sie sicher, dass sie diese Operation durchführen wollen?</translation>
|
||||
<context>
|
||||
<name>Mirall::GETFileJob</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="393"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="428"/>
|
||||
<source>No E-Tag received from server, check Proxy/Gateway</source>
|
||||
<translation>Kein E-Tag vom Server empfangen, bitte Proxy / Gateway überprüfen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="400"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="435"/>
|
||||
<source>We received a different E-Tag for resuming. Retrying next time.</source>
|
||||
<translation>Es wurde ein unterschiedlicher E-Tag zum Fortfahren empfangen. Bitte beim nächsten mal nochmal versuchen.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="633"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="471"/>
|
||||
<source>Connection Timeout</source>
|
||||
<translation>Zeitüberschreitung der Verbindung</translation>
|
||||
</message>
|
||||
@@ -1279,7 +1279,7 @@ Es ist nicht ratsam, diese zu benutzen.</translation>
|
||||
<context>
|
||||
<name>Mirall::PropagateDownloadFileQNAM</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="443"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="485"/>
|
||||
<source>File %1 can not be downloaded because of a local file name clash!</source>
|
||||
<translation>Die Datei %1 kann aufgrund eines Konfliktes mit dem lokalen Dateinamen nicht herunter geladen werden!</translation>
|
||||
</message>
|
||||
@@ -1337,17 +1337,17 @@ Es ist nicht ratsam, diese zu benutzen.</translation>
|
||||
<context>
|
||||
<name>Mirall::PropagateRemoteRename</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="242"/>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="233"/>
|
||||
<source>This folder must not be renamed. It is renamed back to its original name.</source>
|
||||
<translation>Dieser Ordner muss nicht umbenannt werden. Er wurde zurück zum Originalnamen umbenannt.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="244"/>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="235"/>
|
||||
<source>This folder must not be renamed. Please name it back to Shared.</source>
|
||||
<translation>Dieser Ordner muss nicht umbenannt werden. Bitte benennen Sie es zurück wie in der Freigabe.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="259"/>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="250"/>
|
||||
<source>The file was renamed but is part of a read only share. The original file was restored.</source>
|
||||
<translation>Die Datei wurde auf einer Nur-Lese-Freigabe umbenannt. Die Original-Datei wurde wiederhergestellt.</translation>
|
||||
</message>
|
||||
@@ -1379,12 +1379,12 @@ Es ist nicht ratsam, diese zu benutzen.</translation>
|
||||
<translation>Die Datei wurde von einer Nur-Lese-Freigabe lokal bearbeitet. Die Datei wurde wiederhergestellt und Ihre Bearbeitung ist in der Konflikte-Datei.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="272"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="278"/>
|
||||
<source>Local file changed during sync.</source>
|
||||
<translation>Eine lokale Datei wurde während der Synchronisation geändert.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="282"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="288"/>
|
||||
<source>The server did not acknowledge the last chunk. (No e-tag were present)</source>
|
||||
<translation>Der Server hat den letzten Block nicht bestätigt. (Der E-Tag war nicht vorhanden)</translation>
|
||||
</message>
|
||||
@@ -1538,12 +1538,12 @@ Versuchen Sie diese nochmals zu synchronisieren.</translation>
|
||||
<context>
|
||||
<name>Mirall::ShibbolethCredentials</name>
|
||||
<message>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="259"/>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="267"/>
|
||||
<source>Login Error</source>
|
||||
<translation>Log-In Fehler</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="259"/>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="267"/>
|
||||
<source>You must sign in as user %1</source>
|
||||
<translation>Sie müssen sich als %1 einloggen</translation>
|
||||
</message>
|
||||
@@ -1926,27 +1926,27 @@ Versuchen Sie diese nochmals zu synchronisieren.</translation>
|
||||
<translation>Das Element ist aufgrund vorheriger Fehler nicht synchronisiert: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="274"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="280"/>
|
||||
<source>Symbolic links are not supported in syncing.</source>
|
||||
<translation>Symbolische Verknüpfungen werden bei der Synchronisation nicht unterstützt.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="277"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="283"/>
|
||||
<source>File is listed on the ignore list.</source>
|
||||
<translation>Die Datei ist in der Ignorierliste geführt.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="280"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="286"/>
|
||||
<source>File contains invalid characters that can not be synced cross platform.</source>
|
||||
<translation>Die Datei beinhaltet ungültige Zeichen und kann nicht plattformübergreifend synchronisiert werden.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="448"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="453"/>
|
||||
<source>Unable to initialize a sync journal.</source>
|
||||
<translation>Synchronisationsbericht konnte nicht initialisiert werden.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="545"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="549"/>
|
||||
<source>Cannot open the sync journal</source>
|
||||
<translation>Synchronisationsbericht kann nicht geöffnet werden</translation>
|
||||
</message>
|
||||
|
||||
@@ -260,100 +260,100 @@
|
||||
<context>
|
||||
<name>Mirall::Folder</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="107"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="118"/>
|
||||
<source>Unable to create csync-context</source>
|
||||
<translation>Αδυναμία δημιουργίας πλαισίου csync</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="165"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="174"/>
|
||||
<source>Local folder %1 does not exist.</source>
|
||||
<translation>Δεν υπάρχει ο τοπικός φάκελος %1.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="168"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="177"/>
|
||||
<source>%1 should be a directory but is not.</source>
|
||||
<translation>%1 επρεπε να ειναι χωρος αποθηκευσης αλλα δεν ειναι.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="171"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="180"/>
|
||||
<source>%1 is not readable.</source>
|
||||
<translation> %1 δεν είναι αναγνώσιμο. </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="323"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="332"/>
|
||||
<source>%1: %2</source>
|
||||
<translation>%1: %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="409"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="418"/>
|
||||
<source>%1 and %2 other files have been removed.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>Το %1 και άλλα %2 αρχεία διαγράφηκαν.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="411"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="420"/>
|
||||
<source>%1 has been removed.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>Το %1 έχει διαγραφεί.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="416"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="425"/>
|
||||
<source>%1 and %2 other files have been downloaded.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>Το αρχείο %1 και άλλα %2 αρχεία έχουν μεταφορτωθεί.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="418"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="427"/>
|
||||
<source>%1 has been downloaded.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>Το αρχείο %1 έχει μεταφορτωθεί.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="423"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="432"/>
|
||||
<source>%1 and %2 other files have been updated.</source>
|
||||
<translation>Το αρχείο %1 και %2 άλλα αρχεία έχουν ενημερωθεί.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="425"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="434"/>
|
||||
<source>%1 has been updated.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation>Το αρχείο %1 έχει ενημερωθεί.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="430"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="439"/>
|
||||
<source>%1 has been renamed to %2 and %3 other files have been renamed.</source>
|
||||
<translation>Το αρχείο %1 έχει μετονομαστεί σε %2 και άλλα %3 αρχεία έχουν μετονομαστεί.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="432"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="441"/>
|
||||
<source>%1 has been renamed to %2.</source>
|
||||
<comment>%1 and %2 name files.</comment>
|
||||
<translation>Το αρχείο %1 έχει μετονομαστεί σε %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="437"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="446"/>
|
||||
<source>%1 has been moved to %2 and %3 other files have been moved.</source>
|
||||
<translation>Το αρχείο %1 έχει μετακινηθεί στο %2 και %3 άλλα αρχεία έχουν μετακινηθεί.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="439"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="448"/>
|
||||
<source>%1 has been moved to %2.</source>
|
||||
<translation>Το αρχείο %1 έχει μετακινηθεί στο %2.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="447"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="456"/>
|
||||
<source>Sync Activity</source>
|
||||
<translation>Δραστηριότητα Συγχρονισμού</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="697"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="712"/>
|
||||
<source>This sync would remove all the files in the local sync folder '%1'.
|
||||
If you or your administrator have reset your account on the server, choose "Keep files". If you want your data to be removed, choose "Remove all files".</source>
|
||||
<translation>Αυτός ο συγχρονισμός θα αφαιρέσει όλα τα αρχεία στον τοπικό φάκελο συγχρονισμού '%1'.
|
||||
Εάν εσείς ή ο διαχειριστής σας επαναφέρατε τον λογαριασμό σας στο διακομιστή, επιλέξτε "Διατήρηση αρχείων". Εάν θέλετε να αφαιρεθούν τα δεδομένα σας, επιλέξτε "Αφαίρεση όλων των αρχείων".</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="700"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="715"/>
|
||||
<source>This sync would remove all the files in the sync folder '%1'.
|
||||
This might be because the folder was silently reconfigured, or that all the file were manually removed.
|
||||
Are you sure you want to perform this operation?</source>
|
||||
@@ -362,17 +362,17 @@ Are you sure you want to perform this operation?</source>
|
||||
Είστε σίγουροι ότι θέλετε να πραγματοποιήσετε αυτή εντολή;</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="704"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="719"/>
|
||||
<source>Remove All Files?</source>
|
||||
<translation>Αφαίρεση Όλων των Αρχείων;</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="706"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="721"/>
|
||||
<source>Remove all files</source>
|
||||
<translation>Αφαίρεση όλων των αρχείων</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="707"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="722"/>
|
||||
<source>Keep files</source>
|
||||
<translation>Διατήρηση αρχείων</translation>
|
||||
</message>
|
||||
@@ -596,17 +596,17 @@ Are you sure you want to perform this operation?</source>
|
||||
<context>
|
||||
<name>Mirall::GETFileJob</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="393"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="428"/>
|
||||
<source>No E-Tag received from server, check Proxy/Gateway</source>
|
||||
<translation>Δεν ελήφθη E-Tag από τον διακομιστή, ελέγξτε τον διακομιστή μεσολάβησης/πύλη</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="400"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="435"/>
|
||||
<source>We received a different E-Tag for resuming. Retrying next time.</source>
|
||||
<translation>Ελήφθη διαφορετικό E-Tag για συνέχιση. Επανάληψη την επόμενη φορά.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="633"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="471"/>
|
||||
<source>Connection Timeout</source>
|
||||
<translation>Χρονικό όριο σύνδεσης</translation>
|
||||
</message>
|
||||
@@ -1278,7 +1278,7 @@ It is not advisable to use it.</source>
|
||||
<context>
|
||||
<name>Mirall::PropagateDownloadFileQNAM</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="443"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="485"/>
|
||||
<source>File %1 can not be downloaded because of a local file name clash!</source>
|
||||
<translation>Το αρχείο %1 δεν είναι δυνατό να μεταφορτωθεί λόγω διένεξης με το όνομα ενός τοπικού ονόματος αρχείου!</translation>
|
||||
</message>
|
||||
@@ -1336,17 +1336,17 @@ It is not advisable to use it.</source>
|
||||
<context>
|
||||
<name>Mirall::PropagateRemoteRename</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="242"/>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="233"/>
|
||||
<source>This folder must not be renamed. It is renamed back to its original name.</source>
|
||||
<translation>Αυτός ο φάκελος δεν πρέπει να μετονομαστεί. Μετονομάζεται πίσω στο αρχικό του όνομα.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="244"/>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="235"/>
|
||||
<source>This folder must not be renamed. Please name it back to Shared.</source>
|
||||
<translation>Αυτός ο φάκελος δεν πρέπει να μετονομαστεί. Παρακαλώ ονομάστε το ξανά Κοινόχρηστος.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="259"/>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="250"/>
|
||||
<source>The file was renamed but is part of a read only share. The original file was restored.</source>
|
||||
<translation>Το αρχείο μετονομάστηκε αλλά είναι τμήμα ενός διαμοιρασμένου καταλόγου μόνο για ανάγνωση. Το αρχικό αρχείο επαναφέρθηκε.</translation>
|
||||
</message>
|
||||
@@ -1378,12 +1378,12 @@ It is not advisable to use it.</source>
|
||||
<translation>Το αρχείο υπέστη επεξεργασία τοπικά αλλά είναι τμήμα ενός διαμοιρασμένου καταλόγου μόνο για ανάγνωση. Επαναφέρθηκε και η επεξεργασία σας βρίσκεται στο αρχείο συγκρούσεων.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="272"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="278"/>
|
||||
<source>Local file changed during sync.</source>
|
||||
<translation>Το τοπικό αρχείο τροποποιήθηκε κατά τον συγχρονισμό.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="282"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="288"/>
|
||||
<source>The server did not acknowledge the last chunk. (No e-tag were present)</source>
|
||||
<translation>Ο διακομιστής δεν επιβεβαίωσε το τελευταίο τμήμα. (Δεν υπήρχε E-Tag)</translation>
|
||||
</message>
|
||||
@@ -1537,12 +1537,12 @@ It is not advisable to use it.</source>
|
||||
<context>
|
||||
<name>Mirall::ShibbolethCredentials</name>
|
||||
<message>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="259"/>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="267"/>
|
||||
<source>Login Error</source>
|
||||
<translation>Σφάλμα σύνδεσης</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="259"/>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="267"/>
|
||||
<source>You must sign in as user %1</source>
|
||||
<translation>Πρέπει να εισέλθετε σαν χρήστης %1</translation>
|
||||
</message>
|
||||
@@ -1925,27 +1925,27 @@ It is not advisable to use it.</source>
|
||||
<translation>Το αντικείμενο δεν είναι συγχρονισμένο λόγω προηγούμενων σφαλμάτων: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="274"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="280"/>
|
||||
<source>Symbolic links are not supported in syncing.</source>
|
||||
<translation>Οι συμβολικού σύνδεσμοι δεν υποστηρίζονται για το συγχρονισμό.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="277"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="283"/>
|
||||
<source>File is listed on the ignore list.</source>
|
||||
<translation>Το αρχείο περιέχεται στη λίστα αρχείων προς αγνόηση.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="280"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="286"/>
|
||||
<source>File contains invalid characters that can not be synced cross platform.</source>
|
||||
<translation>Το αρχείο περιέχει άκυρους χαρακτήρες που δεν μπορούν να συγχρονιστούν σε όλα τα συστήματα.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="448"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="453"/>
|
||||
<source>Unable to initialize a sync journal.</source>
|
||||
<translation>Αδυναμία προετοιμασίας αρχείου συγχρονισμού.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="545"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="549"/>
|
||||
<source>Cannot open the sync journal</source>
|
||||
<translation>Αποτυχία ανοίγματος του ημερολογίου συγχρονισμού.</translation>
|
||||
</message>
|
||||
@@ -2111,7 +2111,7 @@ It is not advisable to use it.</source>
|
||||
<message>
|
||||
<location filename="../src/wizard/owncloudadvancedsetuppage.ui" line="85"/>
|
||||
<source>pbSelectLocalFolder</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>pbSelectLocalFolder</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/wizard/owncloudadvancedsetuppage.ui" line="107"/>
|
||||
@@ -2395,7 +2395,7 @@ Klaas Freitag, Daniel Molkentin, Jan-Christoph Borchardt, ownCloud Inc.
|
||||
<message>
|
||||
<location filename="../src/mirall/progressdispatcher.cpp" line="42"/>
|
||||
<source>Ignored</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Αγνοήθηκε</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/progressdispatcher.cpp" line="44"/>
|
||||
@@ -2436,7 +2436,7 @@ Klaas Freitag, Daniel Molkentin, Jan-Christoph Borchardt, ownCloud Inc.
|
||||
<message>
|
||||
<location filename="../src/mirall/progressdispatcher.cpp" line="71"/>
|
||||
<source>ignoring</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>αγνοείται</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/progressdispatcher.cpp" line="73"/>
|
||||
|
||||
@@ -262,116 +262,116 @@
|
||||
<context>
|
||||
<name>Mirall::Folder</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="107"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="118"/>
|
||||
<source>Unable to create csync-context</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="165"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="174"/>
|
||||
<source>Local folder %1 does not exist.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="168"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="177"/>
|
||||
<source>%1 should be a directory but is not.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="171"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="180"/>
|
||||
<source>%1 is not readable.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="323"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="332"/>
|
||||
<source>%1: %2</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="409"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="418"/>
|
||||
<source>%1 and %2 other files have been removed.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="411"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="420"/>
|
||||
<source>%1 has been removed.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="416"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="425"/>
|
||||
<source>%1 and %2 other files have been downloaded.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="418"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="427"/>
|
||||
<source>%1 has been downloaded.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="423"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="432"/>
|
||||
<source>%1 and %2 other files have been updated.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="425"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="434"/>
|
||||
<source>%1 has been updated.</source>
|
||||
<comment>%1 names a file.</comment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="430"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="439"/>
|
||||
<source>%1 has been renamed to %2 and %3 other files have been renamed.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="432"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="441"/>
|
||||
<source>%1 has been renamed to %2.</source>
|
||||
<comment>%1 and %2 name files.</comment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="437"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="446"/>
|
||||
<source>%1 has been moved to %2 and %3 other files have been moved.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="439"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="448"/>
|
||||
<source>%1 has been moved to %2.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="447"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="456"/>
|
||||
<source>Sync Activity</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="697"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="712"/>
|
||||
<source>This sync would remove all the files in the local sync folder '%1'.
|
||||
If you or your administrator have reset your account on the server, choose "Keep files". If you want your data to be removed, choose "Remove all files".</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="700"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="715"/>
|
||||
<source>This sync would remove all the files in the sync folder '%1'.
|
||||
This might be because the folder was silently reconfigured, or that all the file were manually removed.
|
||||
Are you sure you want to perform this operation?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="704"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="719"/>
|
||||
<source>Remove All Files?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="706"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="721"/>
|
||||
<source>Remove all files</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/folder.cpp" line="707"/>
|
||||
<location filename="../src/mirall/folder.cpp" line="722"/>
|
||||
<source>Keep files</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -595,17 +595,17 @@ Are you sure you want to perform this operation?</source>
|
||||
<context>
|
||||
<name>Mirall::GETFileJob</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="393"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="428"/>
|
||||
<source>No E-Tag received from server, check Proxy/Gateway</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="400"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="435"/>
|
||||
<source>We received a different E-Tag for resuming. Retrying next time.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="633"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="471"/>
|
||||
<source>Connection Timeout</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -1273,7 +1273,7 @@ It is not advisable to use it.</source>
|
||||
<context>
|
||||
<name>Mirall::PropagateDownloadFileQNAM</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="443"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="485"/>
|
||||
<source>File %1 can not be downloaded because of a local file name clash!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -1331,17 +1331,17 @@ It is not advisable to use it.</source>
|
||||
<context>
|
||||
<name>Mirall::PropagateRemoteRename</name>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="242"/>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="233"/>
|
||||
<source>This folder must not be renamed. It is renamed back to its original name.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="244"/>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="235"/>
|
||||
<source>This folder must not be renamed. Please name it back to Shared.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="259"/>
|
||||
<location filename="../src/mirall/propagatorjobs.cpp" line="250"/>
|
||||
<source>The file was renamed but is part of a read only share. The original file was restored.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -1373,12 +1373,12 @@ It is not advisable to use it.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="272"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="278"/>
|
||||
<source>Local file changed during sync.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="282"/>
|
||||
<location filename="../src/mirall/propagator_qnam.cpp" line="288"/>
|
||||
<source>The server did not acknowledge the last chunk. (No e-tag were present)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -1531,12 +1531,12 @@ It is not advisable to use it.</source>
|
||||
<context>
|
||||
<name>Mirall::ShibbolethCredentials</name>
|
||||
<message>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="259"/>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="267"/>
|
||||
<source>Login Error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="259"/>
|
||||
<location filename="../src/creds/shibbolethcredentials.cpp" line="267"/>
|
||||
<source>You must sign in as user %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -1917,27 +1917,27 @@ It is not advisable to use it.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="274"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="280"/>
|
||||
<source>Symbolic links are not supported in syncing.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="277"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="283"/>
|
||||
<source>File is listed on the ignore list.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="280"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="286"/>
|
||||
<source>File contains invalid characters that can not be synced cross platform.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="448"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="453"/>
|
||||
<source>Unable to initialize a sync journal.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="545"/>
|
||||
<location filename="../src/mirall/syncengine.cpp" line="549"/>
|
||||
<source>Cannot open the sync journal</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||