Comparar commits

..

62 Commits

Autor SHA1 Mensagem Data
Mark Barnard f380852986 Adding thumbs.db 2014-06-12 13:20:59 -04:00
Mark Barnard d13ac31e08 Adding images
Adding screen captures for installation instructions.
2014-06-12 13:10:44 -04:00
Jenkins for ownCloud 3f543b881d [tx-robot] updated from transifex 2014-06-11 02:06:11 -04:00
Jenkins for ownCloud 4a1d0eb80e [tx-robot] updated from transifex 2014-06-11 01:25:22 -04:00
Klaas Freitag 760ecd71fc Theme: Show the stringified app version rather than the major version.
This was a regression, we changed that by accident in 1.6.0.
2014-06-10 13:48:27 +02:00
Jenkins for ownCloud 04f1026cd8 [tx-robot] updated from transifex 2014-06-10 01:25:24 -04:00
Jenkins for ownCloud b03c4cc62e [tx-robot] updated from transifex 2014-06-08 01:25:21 -04:00
Jenkins for ownCloud e497b6d458 [tx-robot] updated from transifex 2014-06-07 02:06:12 -04:00
Jenkins for ownCloud 2e4320ee05 [tx-robot] updated from transifex 2014-06-07 01:25:22 -04:00
Klaas Freitag 14a5ff6747 overlayIcons: First version of the nautilus overlay python module 2014-06-06 17:49:19 +02:00
Olivier Goffart abf0f90a13 SocketAPI: broadcast change when an item is done 2014-06-06 15:52:55 +02:00
Klaas Freitag 4d5c74c019 SocketAPI: Add another API call for stat of file and folder separately. 2014-06-06 15:38:20 +02:00
Jenkins for ownCloud ef3b4956ad [tx-robot] updated from transifex 2014-06-06 01:25:21 -04:00
Markus Goetz fd4642d827 Folder: Don't add ignored files on startup
Before each sync is enough.
(We could do it at startup only, but so far it is good to have
it at each sync so we can easier see stuff in the log)
2014-06-05 17:50:18 +02:00
Olivier Goffart 6dd248e527 csync: fix warnings
warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
2014-06-05 15:48:53 +02:00
Olivier Goffart 7d00c3646a csync: remove unused variable 2014-06-05 15:45:15 +02:00
Olivier Goffart e355e12385 Fix crash in tests 2014-06-05 15:43:27 +02:00
Markus Goetz 34b31c0146 CSync: Fix test compile
The previously applied pull request apparantly broke the compile
because it re-ordered entries in the CMakeLists
2014-06-05 14:22:10 +02:00
Daniel Molkentin 3934fa019e SocketAPI: proper name for pipe on windows 2014-06-05 12:02:57 +02:00
Daniel Molkentin dc53e96f92 [Janitor] Bump version on master to 1.7.0prealpha 2014-06-05 12:02:00 +02:00
Daniel Molkentin 7fcf6f9f79 Merge branch '1.6' 2014-06-05 12:01:50 +02:00
Daniel Molkentin b814b45e50 Add version and product information to installer properties 2014-06-05 11:51:12 +02:00
Daniel Molkentin ded8914df2 [Janitor] Bump version to 1.6.1pre 2014-06-05 11:51:12 +02:00
Olivier Goffart bd48ab23c3 Merge pull request #1835 from zizzfizzix/cmake_fixes
A little CMake cleanup
2014-06-05 11:48:40 +02:00
Markus Goetz 4e28ba73bb Windows: Fix build harder. 2014-06-05 10:13:20 +02:00
Jenkins for ownCloud 16cb37ecd0 [tx-robot] updated from transifex 2014-06-05 01:25:23 -04:00
Olivier Goffart 7a7b0e8939 propagator: Ignore new directory inside removed directory.
This fixes te bug if one create a tree of folders and subfolders
and delete them while they are uploading. Some folder would
reappears
2014-06-04 16:37:46 +02:00
Markus Goetz d4d630b2e9 Windows: Fix build 2014-06-04 12:47:17 +02:00
Olivier Goffart a4f6370774 propagator: do not update perent directory etag before sub directories are removed
Direcotries are removed at the end, and we don't want to update
parent directory etag before the delete is performed, or the next
sync may read from db and think the files are not removed.

Issue #1845
2014-06-04 12:31:30 +02:00
Markus Goetz 2ff27cdd63 Merge pull request #1844 from owncloud/csyncStdlibReduction
Csync reduction

Reviewed offline by @dragotin
2014-06-04 11:28:35 +02:00
Markus Goetz 2f81167164 CSync: Remove more unused things 2014-06-04 11:19:09 +02:00
Markus Goetz 6897c5d41f CSync: Always have statedb enabled 2014-06-04 11:06:41 +02:00
Markus Goetz 233450d850 CSync: Remove config dir setting 2014-06-04 10:56:56 +02:00
Markus Goetz 7428a8fa63 CSync: Remove unused std functions 2014-06-04 10:33:19 +02:00
Markus Goetz 18359d7871 StateDB: Remove _csync_win32_hide_file and use other implementation 2014-06-04 09:46:31 +02:00
Jenkins for ownCloud df12a58e3d [tx-robot] updated from transifex 2014-06-04 01:25:24 -04:00
Kuba Serafinowski 4b3d124b5a put man docs in the correct /man1 directory
man doesn't work here when the docs are in a /man directory
2014-06-04 00:10:18 +03:00
Kuba Serafinowski 51e941e7b5 look for Sparkle only on OS X 2014-06-04 00:10:17 +03:00
Kuba Serafinowski 62ea6f316f don't look for CMocka if we're not building unit tests 2014-06-04 00:10:16 +03:00
Olivier Goffart 6605a89990 csync_statedb: Fix wrong % code in debug output
%ld is for long, but int64_t is larger than long on windows
2014-06-03 18:28:31 +02:00
Olivier Goffart 4cb9b3a85b Test: fix compilation 2014-06-03 17:54:43 +02:00
Olivier Goffart 806ab8ea46 csync: remove the local mode
It is no longer used for a long time
2014-06-03 17:52:07 +02:00
Olivier Goffart 582a8fe7fd Merge branch '1.6' 2014-06-03 17:27:12 +02:00
Olivier Goffart 08ca8b54b1 test fles with '%' and '#' 2014-06-03 17:27:06 +02:00
Olivier Goffart abafbef985 Optimize move
Do not send the mtime for each file without a directory, because the server now keeps it
2014-06-03 17:27:06 +02:00
Olivier Goffart 6e10b8c5c4 Propagator: Recover from 'precondition failed' error
When we detect a precondition failed, it is possible that it is
because the etag in the database is wrong.  We must therefore not
read from the database on the next sync.  In order to avoid that, we
reset the etag of parent directories to invalid values

Fixes #1767
2014-06-03 17:22:40 +02:00
Markus Goetz 06863ca9c6 Merge pull request #1839 from owncloud/directDownload
Direct download URL support + global variable refactoring

Reviewed offline by @dragotin
2014-06-03 16:44:05 +02:00
Markus Goetz e49b8981dd CSync: Shorten WebDAV property name 2014-06-03 16:41:57 +02:00
Olivier Goffart 24616bead4 Fix syncing a folder with '#' in the name
Or an url with '#'

Fixes #1838

The problem is a bug fixed in Qt5 now breaks.
In Qt4, QUrl::setPath() did not properly handle path with '#' in them
and QUrl::toString would restitute the '#'.

But csync will blindly do  "uri + path" before passing the path to
VIO.  because csync_update has no idea that the VIO plugin need special
encoding, the encoding cannot be done there.  But csync_owncloud then
encodes the full path.  So if the uri contains '#', it must not be already
encoded or there will be two encoding.
2014-06-03 15:45:10 +02:00
Markus Goetz 2e91557c28 CSync: Rename callback functions 2014-06-03 15:01:35 +02:00
Markus Goetz 4d4eab8b1c CSync & Propagator: Support a direct download URL
This is for server file backends that support sending a
direct URL.
2014-06-03 14:55:34 +02:00
Olivier Goffart 13f9970257 Fix some possible "Precondition Failed" bug
The problem was if there was a false conflict: the file has been touched
both on the server and the client.
 - etag has changed on the server
 - mtime has changed on the server and the client and is the same
 - and file size is the same on both the server and the client

This may also happen if the file is uploaded on the server, but the client
looses connection (or crashes) before it get notified of the etag.

In both tree, the instruction is EVAL, but we reduce it to a NONE because
we detected that the conflict is 'false'.  Still, we need to update the db
with the new etag.  (_should_update_db)
The problem was that we would set the flag on the wrong tree.
This was not a problem when the file was NEW on both side since  we checked
for null etag and used the other one then.
2014-06-03 12:23:30 +02:00
Markus Goetz 4d4ae9374b CSync: Remove old defines 2014-06-03 11:51:12 +02:00
Markus Goetz b8e20b412c CSync: We can access the context directly 2014-06-03 11:51:12 +02:00
Markus Goetz e36f3c5b10 CSync: Remove one VIO layering 2014-06-03 11:51:12 +02:00
Markus Goetz 8a55f831f4 CSync: Use context instead of global variable 2014-06-03 11:51:12 +02:00
Markus Goetz 0dcc9be5c1 CSync: Remove owncloud_stat
We get already all metadata with the readdir
2014-06-03 11:51:12 +02:00
Markus Goetz 5ee00a8df7 CSync: Simplify csync_owncloud stat/resource handling 2014-06-03 11:51:12 +02:00
Klaas Freitag 1af3d3f18b More descriptive error message when querying the database without hit. 2014-06-03 09:50:09 +02:00
Klaas Freitag f54248c0a7 Minor cleanups and changes 2014-06-03 09:50:09 +02:00
Klaas Freitag 2911c0e1c4 Add a recursiveFolderStatus method 2014-06-03 09:50:09 +02:00
Klaas Freitag 16d35c1489 Avoid crash on csync_ctx is NULL. 2014-06-03 09:50:09 +02:00
124 arquivos alterados com 2360 adições e 4005 exclusões
+4 -1
Ver Arquivo
@@ -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()
+2 -2
Ver Arquivo
@@ -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 )
+9 -9
Ver Arquivo
@@ -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:"
+1 -1
Ver Arquivo
@@ -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}基本组件。"
+6
Ver Arquivo
@@ -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
+7 -7
Ver Arquivo
@@ -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)
+28 -159
Ver Arquivo
@@ -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);
}
+3 -97
Ver Arquivo
@@ -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);
+7 -1
Ver Arquivo
@@ -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;
}
-46
Ver Arquivo
@@ -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>
-2
Ver Arquivo
@@ -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);
/**
+167 -363
Ver Arquivo
@@ -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: */
+9 -150
Ver Arquivo
@@ -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 */
+197
Ver Arquivo
@@ -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
+47 -71
Ver Arquivo
@@ -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);
}
}
+118 -24
Ver Arquivo
@@ -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
}
+7 -14
Ver Arquivo
@@ -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 */
+6 -2
Ver Arquivo
@@ -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;
+3 -25
Ver Arquivo
@@ -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);
+21 -6
Ver Arquivo
@@ -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)) {
-53
Ver Arquivo
@@ -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*)) {
-3
Ver Arquivo
@@ -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 */
-2
Ver Arquivo
@@ -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
-189
Ver Arquivo
@@ -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;
}
-86
Ver Arquivo
@@ -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 */
-346
Ver Arquivo
@@ -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;
}
-102
Ver Arquivo
@@ -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 */
-36
Ver Arquivo
@@ -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
-156
Ver Arquivo
@@ -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;
}
-22
Ver Arquivo
@@ -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);
/**
* }@
-63
Ver Arquivo
@@ -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)
{
-31
Ver Arquivo
@@ -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.
*
+7 -17
Ver Arquivo
@@ -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);
}
-3
Ver Arquivo
@@ -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 */
+4 -14
Ver Arquivo
@@ -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);
}
+12 -23
Ver Arquivo
@@ -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);
-11
Ver Arquivo
@@ -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;
-2
Ver Arquivo
@@ -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);
-6
Ver Arquivo
@@ -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;
}
-3
Ver Arquivo
@@ -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);
-15
Ver Arquivo
@@ -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);
+11
Ver Arquivo
@@ -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." );
+10
Ver Arquivo
@@ -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' );
-176
Ver Arquivo
@@ -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);
}
-180
Ver Arquivo
@@ -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);
}
-27
Ver Arquivo
@@ -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);
-86
Ver Arquivo
@@ -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);
+1 -1
Ver Arquivo
@@ -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")
Arquivo binário não exibido.
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 34 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 21 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 19 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 30 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 25 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 33 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 28 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 30 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 33 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 1.1 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 7.0 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 34 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 33 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 24 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 1.6 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 32 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 40 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 36 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 32 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 71 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 46 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 12 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 13 KiB

Arquivo binário não exibido.
+83
Ver Arquivo
@@ -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)
+7 -2
Ver Arquivo
@@ -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
+80 -24
Ver Arquivo
@@ -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;
}
+12 -1
Ver Arquivo
@@ -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();
+29 -6
Ver Arquivo
@@ -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)) {
+6
Ver Arquivo
@@ -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);
+4
Ver Arquivo
@@ -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;
+70 -22
Ver Arquivo
@@ -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();
}
}
+9 -4
Ver Arquivo
@@ -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();
+1 -10
Ver Arquivo
@@ -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")) ) {
+123 -75
Ver Arquivo
@@ -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
+7 -3
Ver Arquivo
@@ -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;
+6 -2
Ver Arquivo
@@ -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
+2
Ver Arquivo
@@ -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
+23 -1
Ver Arquivo
@@ -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)
{
+6
Ver Arquivo
@@ -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
+1 -1
Ver Arquivo
@@ -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);
}
+37 -37
Ver Arquivo
@@ -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&apos;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&apos;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&apos;ha esborrat &apos;%1&apos;</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&apos;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&apos;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&apos;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&apos;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 &quot;Keep files&quot;. If you want your data to be removed, choose &quot;Remove all files&quot;.</source>
<translation>Aquesta sincronització eliminarà tots els fitxers a la carpeta local de sincronització &apos;%1&apos;.
Si vós o l&apos;administrador heu reinicialitzat el compte en el servidor, escolliu &quot;Mantenir fitxers&quot;. Si voleueliminar les dades, escolliu &quot;Esborra tots els fitxers&quot;.</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&apos;ha de canviar el nom d&apos;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&apos;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&apos;element no s&apos;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&apos;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&apos;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>
+44 -44
Ver Arquivo
@@ -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 &quot;Keep files&quot;. If you want your data to be removed, choose &quot;Remove all files&quot;.</source>
<translation>Tato synchronizace by smazala všechny soubory v místní složce &apos;%1&apos;
Pokud jste vy nebo váš správce zresetovali účet na serveru, zvolte &quot;Ponechat soubory&quot;. Pokud chcete místní data odstranit, zvolte &quot;Odstranit všechny soubory&quot;.</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 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 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>
+37 -37
Ver Arquivo
@@ -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 &quot;Keep files&quot;. If you want your data to be removed, choose &quot;Remove all files&quot;.</source>
<translation>Dieser Synchronisationsvorgang würde alle Dateien in dem lokalen Ordner &apos;%1&apos; entfernen.
Wenn Sie oder Ihr Administrator Ihr Konto auf dem Server zurückgesetzt haben, wählen Sie &quot;Dateien behalten&quot;. Wenn Sie ihre Daten löschen wollen, wählen Sie &quot;Alle Dateien entfernen&quot;.</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>
+40 -40
Ver Arquivo
@@ -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 &quot;Keep files&quot;. If you want your data to be removed, choose &quot;Remove all files&quot;.</source>
<translation>Αυτός ο συγχρονισμός θα αφαιρέσει όλα τα αρχεία στον τοπικό φάκελο συγχρονισμού &apos;%1&apos;.
Εάν εσείς ή ο διαχειριστής σας επαναφέρατε τον λογαριασμό σας στο διακομιστή, επιλέξτε &quot;Διατήρηση αρχείων&quot;. Εάν θέλετε να αφαιρεθούν τα δεδομένα σας, επιλέξτε &quot;Αφαίρεση όλων των αρχείων&quot;.</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"/>
+37 -37
Ver Arquivo
@@ -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 &apos;%1&apos;.
If you or your administrator have reset your account on the server, choose &quot;Keep files&quot;. If you want your data to be removed, choose &quot;Remove all files&quot;.</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 &apos;%1&apos;.
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>

Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais