Comparar commits
482 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| c45bf61b02 | |||
| e833d01288 | |||
| 3047682223 | |||
| c91dd94728 | |||
| 52f9f44b51 | |||
| 49748191a9 | |||
| e6b937f508 | |||
| 31c13f74fb | |||
| be466b47b7 | |||
| 11b144957b | |||
| 817e97c148 | |||
| 29932004ae | |||
| 6d83e841a9 | |||
| b43a9421d2 | |||
| e70b78d14b | |||
| 6814342d1f | |||
| 68126dcff6 | |||
| e7f00339e6 | |||
| a36b4ec863 | |||
| 074f8eadb1 | |||
| 6a51ae5b1b | |||
| af5f2d3860 | |||
| 38bad564a0 | |||
| c2fa3fb4c8 | |||
| f7082ee3df | |||
| f7c6efb391 | |||
| 051a348afd | |||
| d0af3ede05 | |||
| 0da2adcbe0 | |||
| 07bdd519e9 | |||
| 0829a94c92 | |||
| faf2514be2 | |||
| 4ea2edcf4a | |||
| cd29875b76 | |||
| 85bc3b276f | |||
| ce5ca8a42e | |||
| ce6a365328 | |||
| 09eea7f5f2 | |||
| 043350f49d | |||
| f657bd0cd9 | |||
| b4cf17d99d | |||
| 12bf6e39b7 | |||
| 4e7c09de83 | |||
| 31f2c3e76a | |||
| 64b6486327 | |||
| 335e333e28 | |||
| 41eb5f0a3f | |||
| 030184fad9 | |||
| 7d285d0225 | |||
| d3a93322d2 | |||
| 8694db1c49 | |||
| 19eca84d4f | |||
| 665c3f40e1 | |||
| f8f394eb0a | |||
| 0711abbf56 | |||
| 84ac2e64e0 | |||
| 57f0603e0e | |||
| b61ae351dd | |||
| 277a1cfb5a | |||
| 6ba7c6e2d3 | |||
| 055c2ef73f | |||
| e5a5b95b9a | |||
| 7acdf50a2c | |||
| 361ebf5464 | |||
| 7a82fac0d5 | |||
| 8b39c6e6ce | |||
| e29d7e0128 | |||
| dbcb94e7d4 | |||
| 522f7afa9e | |||
| fa69d089cf | |||
| 1935c78f17 | |||
| b56919d0c4 | |||
| f72c7f43bf | |||
| add29befee | |||
| f9fb7a59dd | |||
| 1a51b6718a | |||
| a3a9417630 | |||
| 53a72148d3 | |||
| c379593c0f | |||
| bd37eab3ad | |||
| edb942ba61 | |||
| a17f37d8ae | |||
| 33459b48c8 | |||
| 598941948c | |||
| 038b7db606 | |||
| 9f30e83413 | |||
| 2ab4caf007 | |||
| 11d3aa3c4f | |||
| 93ad61aeef | |||
| 6a36d1b4fb | |||
| c0ec481436 | |||
| df0833d7f9 | |||
| 6a9655aab6 | |||
| 0f3d6d4160 | |||
| c4577cb2a1 | |||
| fafca26144 | |||
| 06c19b0b6f | |||
| d1649ce4df | |||
| ea40e314d4 | |||
| e2622310df | |||
| 4ad8e04bc3 | |||
| 74301e4373 | |||
| 053dcbf1f5 | |||
| 700c7bcbc6 | |||
| bc6c57aa0b | |||
| a0521caf52 | |||
| 8007331462 | |||
| 12330b38e9 | |||
| 8eb53fa9ae | |||
| dfd7d4d2f9 | |||
| 484a2c800d | |||
| 8d300b049f | |||
| 48e594ebbf | |||
| 910c61b492 | |||
| 8155c1c426 | |||
| 97a6d3df82 | |||
| f7aafb081f | |||
| 9cc981c8c7 | |||
| ed3203d25d | |||
| a4f606ceab | |||
| 15988c6fda | |||
| f443377978 | |||
| fdcdddca16 | |||
| bf99306a53 | |||
| 844777d43f | |||
| 4f79f1b5e8 | |||
| 6f454feb39 | |||
| 68b7437afb | |||
| 41b950b7e6 | |||
| 2d08754f91 | |||
| 868edb1f0d | |||
| aaf43bd0d3 | |||
| d5f1d1c6b2 | |||
| 6cb94e8849 | |||
| d433c24186 | |||
| c48b5c4f61 | |||
| 976f4dfabe | |||
| f8dc263338 | |||
| e896d16f32 | |||
| 2ec642aadb | |||
| bd3a079a7b | |||
| 6ee7e82913 | |||
| 648328fbe2 | |||
| ee58cc3b66 | |||
| 74a75f6399 | |||
| a0baca25ff | |||
| 4b5c9c5ee5 | |||
| 4ce97633cd | |||
| f1732d66d6 | |||
| 329f512a40 | |||
| c64720eac5 | |||
| 8f7b833c12 | |||
| 48bfcde97d | |||
| 42439490cc | |||
| 4dd8d61e4e | |||
| 271bea39ff | |||
| a0827c5ef2 | |||
| 058cd33324 | |||
| e4604b406f | |||
| 7b1f02fcda | |||
| 52a5234122 | |||
| 4e17dabcb6 | |||
| 15bdb7be64 | |||
| 9bdc84c6f4 | |||
| 252aea25da | |||
| efb0faa14e | |||
| 5b40921587 | |||
| 7994b3d91a | |||
| 65e740301a | |||
| f495daf1cf | |||
| 3334067d9f | |||
| 73e2a503d7 | |||
| bc6eebddf4 | |||
| 434d16941b | |||
| 6b0d535120 | |||
| 8b3ea7aa97 | |||
| 84ad0d234e | |||
| 87e4370bf4 | |||
| fa1bb309ca | |||
| e05819370b | |||
| d65808b1e1 | |||
| a115f4b9d0 | |||
| 9ea191f63d | |||
| 17c645ce43 | |||
| f427955512 | |||
| dd8b0c3e4a | |||
| 6c283c7a48 | |||
| c150350096 | |||
| c35e74d264 | |||
| cdbc25ede8 | |||
| a0260c29c0 | |||
| 2c0caf8b75 | |||
| 56064c9366 | |||
| 98995f45e6 | |||
| 5636dc1386 | |||
| 127291e35d | |||
| 885f8b382f | |||
| 8166c52f4a | |||
| ef57d4ae11 | |||
| fbf23b6abb | |||
| 47a552f8c2 | |||
| cd3f612857 | |||
| 2e30a0e5bc | |||
| 9f438cb768 | |||
| cacb751ab8 | |||
| 4d59f5ec66 | |||
| 69e8e15884 | |||
| 1730569f77 | |||
| 98091aeab7 | |||
| c5fbde412c | |||
| 10a7128d1a | |||
| 41f43feecf | |||
| 4915bbf8f3 | |||
| ffbd5df25f | |||
| 82190eaa81 | |||
| 69aa39f1f6 | |||
| ea5e6d367b | |||
| da7b9916e5 | |||
| dac4bd8370 | |||
| 6e16e34799 | |||
| 6d3fe9d865 | |||
| c090a511fd | |||
| a4e0899af4 | |||
| 2d2c7bc9b8 | |||
| df386b64ba | |||
| 80bd86a305 | |||
| d55c31d93b | |||
| 68cbaf1bd6 | |||
| 6867c2ffb3 | |||
| ecb34f60f2 | |||
| 5989a07339 | |||
| 7730e826b0 | |||
| 2d24585a8f | |||
| 84a6d1e920 | |||
| 05fae8ee7f | |||
| 1fe5d6bb0c | |||
| 0c944a06f9 | |||
| 1bb3a4a45d | |||
| 161d21904a | |||
| ea2f19b78a | |||
| f70c6282ca | |||
| ad60e8ac89 | |||
| d03fcc95e4 | |||
| 588646f7a2 | |||
| fb75adcd57 | |||
| d407aacc4a | |||
| 02a69d5487 | |||
| 57acde758b | |||
| f587f35ef0 | |||
| 8c00d5e1ee | |||
| f02148e8ca | |||
| 476d628c01 | |||
| c55ac504a3 | |||
| 6735126c09 | |||
| b9663456d8 | |||
| cabeeba7c5 | |||
| 6c517638d0 | |||
| 0e1b9a346d | |||
| 03db1894d8 | |||
| ff4cdc3161 | |||
| 0febe9b0df | |||
| ceb4a23dab | |||
| 7f22a07312 | |||
| 328d254f7f | |||
| 15f6e133a5 | |||
| 0a590b7cbe | |||
| f04895a407 | |||
| 41b43bf961 | |||
| 05de710b67 | |||
| f71fdab997 | |||
| 6d8e570420 | |||
| d7bd1300a8 | |||
| 2bba68e059 | |||
| 4b19cdeca0 | |||
| 3d157cbb02 | |||
| 80b5f3f43d | |||
| 254361cb87 | |||
| f7f412007e | |||
| 45c32ec0b1 | |||
| 97e323ac3a | |||
| 04faee4a0f | |||
| 4900703970 | |||
| 7bd4f95b8c | |||
| ecd44f70de | |||
| 9d5307d04c | |||
| 6e697bae97 | |||
| 366abb5350 | |||
| 9460aa7f21 | |||
| a4dcc2784a | |||
| 9a2f1456c5 | |||
| 9d219a18f3 | |||
| 97f1694f7e | |||
| 73cd5a9c27 | |||
| 25baa995ec | |||
| 39a95d3bd5 | |||
| 22acc004cc | |||
| 6c07f08175 | |||
| 62d4ed8087 | |||
| adf9570a92 | |||
| 2c2a18af43 | |||
| 2d1ab27cb5 | |||
| 903e79a7c4 | |||
| 6b8636f79b | |||
| 8a0ce463da | |||
| 7d13a1d8e1 | |||
| b97c832306 | |||
| 4a4dac22e2 | |||
| 32e16b323c | |||
| 688c5502a8 | |||
| eb00b34191 | |||
| a831b7417f | |||
| 0eb1041290 | |||
| c0623295e0 | |||
| e82a13803d | |||
| 5cb45bf738 | |||
| a14b495864 | |||
| ad1c343cd7 | |||
| 17003cec19 | |||
| 2843214d09 | |||
| b456ded5e7 | |||
| d4848880e1 | |||
| e41bb8af6d | |||
| 3a608dda8f | |||
| 41d38b37cf | |||
| 54612455e6 | |||
| 9c5b9f932b | |||
| debaff6f7a | |||
| 25ce5f1c22 | |||
| a441e4e30d | |||
| 50c32f45ac | |||
| 5f24575ed9 | |||
| e91a5c85ff | |||
| 7561f5c717 | |||
| c554f5383c | |||
| 4f48c888ef | |||
| 4ff6dc2992 | |||
| 266508b691 | |||
| d78c3679e7 | |||
| d6d3502960 | |||
| 7ed7512f27 | |||
| ffa78b99d9 | |||
| f66c28900a | |||
| 40c109597e | |||
| 6e9019120f | |||
| 17f40f7efd | |||
| b0db709960 | |||
| 216956da4a | |||
| e4ec09dd87 | |||
| ba42d40df9 | |||
| d521232587 | |||
| 10e8f03ea4 | |||
| 8877f04835 | |||
| f24fa46789 | |||
| a9b00a7489 | |||
| 3f462403a9 | |||
| 6aa418f7c4 | |||
| 6493421109 | |||
| 49f00499f7 | |||
| 0052386b41 | |||
| e1909c3bd1 | |||
| 8ce9388d29 | |||
| b8227afcaa | |||
| b8dee63d7a | |||
| 75c99bf2b1 | |||
| e6f81d3965 | |||
| 1fafb1325b | |||
| 8222295ab1 | |||
| 744464aca6 | |||
| c13637b105 | |||
| 60c101d90b | |||
| b685f6b6b6 | |||
| 424bf6f06a | |||
| 46c3c9e0fc | |||
| 85f6c5fda8 | |||
| 7e5d89293d | |||
| fe7630954e | |||
| 47ce4bd9e5 | |||
| 8fe4f1f0d7 | |||
| b3d57f3c7c | |||
| a76ba06817 | |||
| 86fb83261a | |||
| cf0762a067 | |||
| 99b3b752e3 | |||
| 5d7aa792e7 | |||
| 28b694b170 | |||
| 74f74e0363 | |||
| 64ca8a668a | |||
| bd72408e7a | |||
| a32381a2a4 | |||
| 841973d399 | |||
| cf47523b2c | |||
| 2918e45343 | |||
| e3b56fb559 | |||
| 667f2a7c4c | |||
| e846b36bf6 | |||
| 7f18d087e6 | |||
| 3cc9019b37 | |||
| 37924b9c7f | |||
| a6c2ccc6cc | |||
| c84051c737 | |||
| fe24ba55c4 | |||
| ed06fc51a0 | |||
| 14de3b460b | |||
| dd89ab59e4 | |||
| cd83772112 | |||
| 83adb7b55b | |||
| 49ba58e991 | |||
| 7db3bc91b5 | |||
| c93ecfbfb5 | |||
| 893e22691d | |||
| 41d8d77535 | |||
| e9307bb797 | |||
| c98bf174ed | |||
| ae3b9f112c | |||
| 7fd9e751e0 | |||
| 96f50d0c47 | |||
| 95a58e74ca | |||
| b70a95ba30 | |||
| 72e14643f7 | |||
| 93308faeb9 | |||
| f140d3447c | |||
| 16ab3ca6a6 | |||
| 6b643c7501 | |||
| 24920a4ad1 | |||
| 65655584e9 | |||
| e397056d2e | |||
| f442195b8a | |||
| 54a278edb9 | |||
| b0acc475b0 | |||
| aa8b772bff | |||
| 834a971e2a | |||
| 6701927840 | |||
| e4ae279f7b | |||
| 25e0d1eac3 | |||
| d42faa80a6 | |||
| a92c756fa9 | |||
| 4cf94ed62a | |||
| 57c7727479 | |||
| 8480fc7ae5 | |||
| 5ae81aa96c | |||
| 28907ec0c3 | |||
| 7ddfa79950 | |||
| dd76d72d61 | |||
| ba87178dee | |||
| d8af949a6a | |||
| 74a8c4aae8 | |||
| 8de21cc37f | |||
| 063444801a | |||
| 46e384a2f2 | |||
| 5092243080 | |||
| 110f3710be | |||
| 6096a836a4 | |||
| c3724068e5 | |||
| 7eba784b0c | |||
| 8486a2fd2b | |||
| f15f4aa886 | |||
| 3b60f6e238 | |||
| c23ae5aa14 | |||
| 93986e0234 | |||
| 47710d167a | |||
| 62ded39416 | |||
| 1534dad5b2 | |||
| f705c56cb3 | |||
| 4d52838e2b | |||
| 7f44e83cc7 | |||
| 2c6546f46f | |||
| 76bf93e3de | |||
| 7a676a748a | |||
| 17895f3a30 | |||
| 1bb76f5343 | |||
| 639301e9e9 | |||
| 8f26bb698d | |||
| ae806e8214 | |||
| e67bb1c5ce | |||
| f2c9a49c50 | |||
| 903dd8acef | |||
| e27374324d | |||
| 895f0b29aa | |||
| f54f48615d | |||
| 06bb97e6d9 | |||
| 0763f65329 | |||
| 40395bdc0e |
@@ -7,7 +7,6 @@ CMakeLists.txt.user*
|
||||
doc/_build/*
|
||||
*.kate-swp
|
||||
*.kdev4
|
||||
win/
|
||||
admin/win/nsi/l10n/pofiles/*.po
|
||||
*.swp
|
||||
*~$
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
url = https://github.com/owncloud/documentation
|
||||
[submodule "src/3rdparty/qtmacgoodies"]
|
||||
path = src/3rdparty/qtmacgoodies
|
||||
url = git://github.com/guruz/qtmacgoodies.git
|
||||
url = https://github.com/guruz/qtmacgoodies.git
|
||||
[submodule "binary"]
|
||||
path = binary
|
||||
url = git://github.com/owncloud/owncloud-client-binary.git
|
||||
|
||||
@@ -20,6 +20,11 @@ if (NOT DEFINED APPLICATION_SHORTNAME)
|
||||
set ( APPLICATION_SHORTNAME ${APPLICATION_NAME} )
|
||||
endif()
|
||||
|
||||
# For usage in XML files we preprocess
|
||||
string(REPLACE "&" "&" APPLICATION_NAME_XML_ESCAPED "${APPLICATION_NAME}")
|
||||
string(REPLACE "<" "<" APPLICATION_NAME_XML_ESCAPED "${APPLICATION_NAME_XML_ESCAPED}")
|
||||
string(REPLACE ">" ">" APPLICATION_NAME_XML_ESCAPED "${APPLICATION_NAME_XML_ESCAPED}")
|
||||
|
||||
set(PACKAGE "${APPLICATION_SHORTNAME}-client")
|
||||
set( CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules )
|
||||
|
||||
@@ -30,7 +35,7 @@ endif()
|
||||
include(Warnings)
|
||||
|
||||
include(${CMAKE_SOURCE_DIR}/VERSION.cmake)
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/src/mirall/")
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
# disable the crashreporter if libcrashreporter-qt is not available or we're building for ARM
|
||||
if( CMAKE_SYSTEM_PROCESSOR MATCHES "arm" OR NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/3rdparty/libcrashreporter-qt/CMakeLists.txt")
|
||||
@@ -51,9 +56,7 @@ endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(DefineInstallationPaths)
|
||||
include(QtVersionAbstraction)
|
||||
|
||||
setup_qt()
|
||||
|
||||
include(GetGitRevisionDescription)
|
||||
|
||||
@@ -126,34 +129,8 @@ if(APPLE)
|
||||
set( SOCKETAPI_TEAM_IDENTIFIER_PREFIX "" CACHE STRING "SocketApi prefix (including a following dot) that must match the codesign key's TeamIdentifier/Organizational Unit" )
|
||||
endif()
|
||||
|
||||
#### find libs
|
||||
#find_package(Qt4 4.7.0 COMPONENTS QtCore QtGui QtXml QtNetwork QtTest QtWebkit REQUIRED )
|
||||
#if( UNIX AND NOT APPLE ) # Fdo notifications
|
||||
# find_package(Qt4 4.7.0 COMPONENTS QtDBus REQUIRED )
|
||||
#endif()
|
||||
|
||||
|
||||
if(HAVE_QT5)
|
||||
if (${Qt5Core_VERSION_MAJOR} EQUAL "5")
|
||||
if (${Qt5Core_VERSION_MINOR} EQUAL "4" OR ${Qt5Core_VERSION_MINOR} GREATER 4)
|
||||
else()
|
||||
message(STATUS "If possible compile me with Qt 5.4 or higher.")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "If possible compile me with Qt 5.4 or higher.")
|
||||
endif()
|
||||
|
||||
find_package(OpenSSL 1.0.0 REQUIRED)
|
||||
|
||||
if(NOT TOKEN_AUTH_ONLY)
|
||||
if (Qt5Core_DIR)
|
||||
find_package(Qt5Keychain REQUIRED)
|
||||
else()
|
||||
find_package(QtKeychain REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
find_package(Sparkle)
|
||||
endif(APPLE)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
ChangeLog
|
||||
=========
|
||||
version 2.1.1 (release 2016-01-2x)
|
||||
version 2.1.1 (release 2016-02-10)
|
||||
* UI improvements for HiDPI screens, error messages, RTL languages
|
||||
* Fix occurences of "Connection Closed" when a new unauthenticated TCP socket is used
|
||||
* Fix undeliberate WiFi scanning done by Qt Network classes
|
||||
@@ -14,9 +14,11 @@ version 2.1.1 (release 2016-01-2x)
|
||||
* Allow changeable upload chunk size in owncloud.cfg
|
||||
* Crash fixes on account deletion
|
||||
* Forget password on explicit sign-out
|
||||
* OS X: Fix the file system watcher ignoring unicode paths (#4424)
|
||||
* Windows Installer: Update to NSIS 2.50, fixes possible DLL injection
|
||||
* Sync Engine: .lnk files
|
||||
* Sync Engine: symlinked syn directories
|
||||
* Sync Engine: Windows: Fix deleting and replacing of read-only files (#4308 #4277)
|
||||
* Sync Engine: Windows: Fix deleting and replacing of read-only files (#4308, #4277)
|
||||
* Sync Engine: Fixes for files becoming directories and vice versa (#4302)
|
||||
* Misc other fixes/improvements
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
set( MIRALL_VERSION_MAJOR 2 )
|
||||
set( MIRALL_VERSION_MINOR 1 )
|
||||
set( MIRALL_VERSION_PATCH 1 )
|
||||
set( MIRALL_VERSION_MINOR 2 )
|
||||
set( MIRALL_VERSION_PATCH 0 )
|
||||
set( MIRALL_VERSION_YEAR 2016 )
|
||||
set( MIRALL_SOVERSION 0 )
|
||||
|
||||
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||
set( MIRALL_VERSION_SUFFIX "git") #e.g. beta1, beta2, rc1
|
||||
set( MIRALL_VERSION_SUFFIX "beta2") #e.g. beta1, beta2, rc1
|
||||
endif( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||
|
||||
if( NOT DEFINED MIRALL_VERSION_BUILD )
|
||||
|
||||
@@ -25,6 +25,8 @@ def extractDeps(macho):
|
||||
deps = [macho]
|
||||
otool = subprocess.Popen(['otool', '-L', macho], stdout=subprocess.PIPE)
|
||||
for l in otool.communicate()[0].splitlines():
|
||||
if 'is not an object file' in l:
|
||||
return []
|
||||
m = re.search(r'@[^\s]+', l)
|
||||
if m:
|
||||
path = resolvePath(m.group(0))
|
||||
|
||||
@@ -249,35 +249,38 @@ def CopyPlugin(path, subdir):
|
||||
commands.append(args)
|
||||
return new_path
|
||||
|
||||
def CopyFramework(path):
|
||||
parts = path.split(os.sep)
|
||||
print "CopyFramework:", path
|
||||
def CopyFramework(source_dylib):
|
||||
parts = source_dylib.split(os.sep)
|
||||
print "CopyFramework:", source_dylib
|
||||
for i, part in enumerate(parts):
|
||||
matchObj = re.match(r'(\w+\.framework)', part)
|
||||
if matchObj:
|
||||
full_path = os.path.join(frameworks_dir, *parts[i:-1])
|
||||
framework = matchObj.group(1)
|
||||
dylib_name = parts[-1]
|
||||
source_path = os.path.join('/', *parts[:i+1])
|
||||
dest_path = os.path.join(frameworks_dir, framework)
|
||||
dest_dylib_path = os.path.join(frameworks_dir, *parts[i:-1])
|
||||
break
|
||||
args = ['mkdir', '-p', full_path]
|
||||
commands.append(args)
|
||||
args = ['ditto', '--arch=x86_64', path, full_path]
|
||||
commands.append(args)
|
||||
args = ['chmod', 'u+w', os.path.join(full_path, parts[-1])]
|
||||
commands.append(args)
|
||||
resources_dir = os.path.join(frameworks_dir, framework, "Resources")
|
||||
if os.path.exists(dest_path):
|
||||
print dest_path, "already exists, skipping copy..."
|
||||
return os.path.join(dest_dylib_path, dylib_name)
|
||||
|
||||
args = ['mkdir', resources_dir]
|
||||
args = ['mkdir', '-p', dest_dylib_path]
|
||||
commands.append(args)
|
||||
args = ['chmod', 'u+w', resources_dir]
|
||||
args = ['ditto', '--arch=x86_64', source_dylib, dest_dylib_path]
|
||||
commands.append(args)
|
||||
args = ['chmod', 'u+w', os.path.join(dest_dylib_path, parts[-1])]
|
||||
commands.append(args)
|
||||
args = ['ln', '-s', '5', os.path.join(dest_path, 'Versions', 'Current')]
|
||||
commands.append(args)
|
||||
args = ['ln', '-s', os.path.join('Versions', 'Current', dylib_name), os.path.join(dest_path, dylib_name)]
|
||||
commands.append(args)
|
||||
args = ['ln', '-s', os.path.join('Versions', 'Current', 'Resources'), os.path.join(dest_path, 'Resources')]
|
||||
commands.append(args)
|
||||
args = ['cp', '-r', os.path.join(source_path, 'Versions', '5', 'Resources'), os.path.join(dest_path, 'Versions', '5')]
|
||||
commands.append(args)
|
||||
|
||||
info_plist = os.path.join(os.path.split(path)[0], '..', '..', 'Contents', 'Info.plist')
|
||||
if not os.path.exists(info_plist):
|
||||
info_plist = os.path.join(os.path.split(path)[0], 'Resources', 'Info.plist')
|
||||
if os.path.exists(info_plist):
|
||||
args = ['cp', '-r', info_plist, resources_dir]
|
||||
commands.append(args)
|
||||
return os.path.join(full_path, parts[-1])
|
||||
return os.path.join(dest_dylib_path, dylib_name)
|
||||
|
||||
def FixId(path, library_name):
|
||||
id = '@executable_path/../Frameworks/%s' % library_name
|
||||
|
||||
@@ -497,7 +497,7 @@
|
||||
<key>IDENTIFIER</key>
|
||||
<string>@APPLICATION_REV_DOMAIN_INSTALLER@</string>
|
||||
<key>NAME</key>
|
||||
<string>@APPLICATION_NAME@</string>
|
||||
<string>@APPLICATION_NAME_XML_ESCAPED@</string>
|
||||
<key>OVERWRITE_PERMISSIONS</key>
|
||||
<false/>
|
||||
<key>VERSION</key>
|
||||
@@ -1245,7 +1245,7 @@
|
||||
<key>LANGUAGE</key>
|
||||
<string>English</string>
|
||||
<key>VALUE</key>
|
||||
<string>@APPLICATION_NAME@ Client</string>
|
||||
<string>@APPLICATION_NAME_XML_ESCAPED@ Client</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
@@ -1445,7 +1445,7 @@
|
||||
</dict>
|
||||
</array>
|
||||
<key>NAME</key>
|
||||
<string>@APPLICATION_NAME@ Installer</string>
|
||||
<string>@APPLICATION_NAME_XML_ESCAPED@ Installer</string>
|
||||
<key>REFERENCE_FOLDER_PATH</key>
|
||||
<string>@CMAKE_INSTALL_DIR@</string>
|
||||
</dict>
|
||||
|
||||
@@ -12,8 +12,10 @@ EOF
|
||||
if [ -x "$(command -v pluginkit)" ]; then
|
||||
# add it to DB. This happens automatically too but we try to push it a bit harder for issue #3463
|
||||
pluginkit -a "/Applications/@APPLICATION_EXECUTABLE@.app/Contents/PlugIns/FinderSyncExt.appex/"
|
||||
# Since El Capitan we need to sleep #4650
|
||||
sleep 10s
|
||||
# enable it
|
||||
pluginkit -e use -i @APPLICATION_REV_DOMAIN@.FinderSyncExt
|
||||
fi
|
||||
|
||||
exit 0
|
||||
exit 0
|
||||
|
||||
@@ -9,8 +9,9 @@ team_identifier="$3"
|
||||
codesign -s "$identity" --force --preserve-metadata=entitlements --verbose=4 --deep "$src_app"
|
||||
|
||||
# Verify the signature
|
||||
spctl -a -t exec -vv $src_app
|
||||
codesign -dv $src_app
|
||||
codesign --verify -v $src_app
|
||||
spctl -a -t exec -vv $src_app
|
||||
|
||||
# Validate that the key used for signing the binary matches the expected TeamIdentifier
|
||||
# needed to pass the SocketApi through the sandbox
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# This script creates a new windows toolchain repository in OBS.
|
||||
# It only works for versions that do not yet exist.
|
||||
#
|
||||
# Make sure to adopt the variable stableversion.
|
||||
|
||||
# Set the new stable version accordingly:
|
||||
stableversion=2.1
|
||||
targetproject="isv:ownCloud:toolchains:mingw:win32:${stableversion}"
|
||||
|
||||
# Create the new repo
|
||||
|
||||
# get the xml build description of the stable repo
|
||||
xml=`osc meta prj isv:ownCloud:toolchains:mingw:win32:stable`
|
||||
stable_xml="${xml/stable/$stableversion}"
|
||||
|
||||
echo $stable_xml
|
||||
|
||||
echo $stable_xml | osc meta prj -F - ${targetproject}
|
||||
|
||||
|
||||
# now copy all packages
|
||||
packs=`osc ls isv:ownCloud:toolchains:mingw:win32:stable`
|
||||
|
||||
for pack in $packs
|
||||
do
|
||||
osc copypac isv:ownCloud:toolchains:mingw:win32:stable $pack $targetproject
|
||||
done
|
||||
@@ -0,0 +1,37 @@
|
||||
FROM opensuse:42.1
|
||||
|
||||
MAINTAINER Daniel Molkentin <danimo@owncloud.com>
|
||||
|
||||
ENV TERM ansi
|
||||
ENV HOME /root
|
||||
|
||||
ENV REFRESHED_AT 20160421
|
||||
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys refresh
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys ar http://download.opensuse.org/repositories/windows:/mingw/openSUSE_42.1/windows:mingw.repo
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys ar http://download.opensuse.org/repositories/isv:ownCloud:toolchains:mingw:win32:2.2/openSUSE_Leap_42.1/isv:ownCloud:toolchains:mingw:win32:2.2.repo
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys install cmake make mingw32-cross-binutils mingw32-cross-cpp mingw32-cross-gcc \
|
||||
mingw32-cross-gcc-c++ mingw32-cross-pkg-config mingw32-filesystem \
|
||||
mingw32-headers mingw32-runtime site-config mingw32-libwebp \
|
||||
mingw32-cross-libqt5-qmake mingw32-cross-libqt5-qttools mingw32-libqt5* \
|
||||
mingw32-qt5keychain* mingw32-angleproject* \
|
||||
mingw32-cross-nsis mingw32-libopenssl* \
|
||||
mingw32-sqlite* kdewin-png2ico \
|
||||
osslsigncode wget
|
||||
|
||||
# RPM depends on curl for installs from HTTP
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys install curl
|
||||
|
||||
# sudo needed for building as user
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys install sudo
|
||||
|
||||
# Use packaged UAC dependencies
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys install mingw32-cross-nsis-plugin-uac mingw32-cross-nsis-plugin-nsprocess
|
||||
|
||||
# Required for checksumming
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys install mingw32-zlib-devel
|
||||
|
||||
# Required for windres not to crash
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys install glibc-locale
|
||||
|
||||
CMD /bin/bash
|
||||
@@ -7,13 +7,13 @@ fi
|
||||
|
||||
useradd user -u ${2:-1000}
|
||||
su - user << EOF
|
||||
cd /home/user/$1
|
||||
rm -rf build-win32
|
||||
mkdir build-win32
|
||||
cd build-win32
|
||||
../admin/win/download_runtimes.sh
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=../admin/win/Toolchain-mingw32-openSUSE.cmake -DWITH_CRASHREPORTER=ON
|
||||
make -j4
|
||||
make package
|
||||
ctest .
|
||||
cd /home/user/$1
|
||||
rm -rf build-win32
|
||||
mkdir build-win32
|
||||
cd build-win32
|
||||
../admin/win/download_runtimes.sh
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=../admin/win/Toolchain-mingw32-openSUSE.cmake -DWITH_CRASHREPORTER=ON
|
||||
make -j4
|
||||
make package
|
||||
ctest .
|
||||
EOF
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Auto-generated - do not modify
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Toon releaseopmerkingen"
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Toon opmerkingen bij deze uitgave"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Gevonden ${APPLICATION_EXECUTABLE} proces(sen) moet worden gestopt.$\nWilt u dat het installatieprogramma dat voor u doet?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Stoppen ${APPLICATION_EXECUTABLE} processen."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Het te stoppen proces is niet gevonden!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Er is een oudere versie van ${APPLICATION_NAME} geïnstalleerd op uw systeem. geadviseerd wordt om de huidige versie te de-installeren voordat de nieuwe versie wordt geïnstalleerd. Selecteer de uit te voeren actie en klik op Verder om door te gaan."
|
||||
StrCpy $PageReinstall_NEW_Field_2 "De-installeren voor installeren"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "Niet de-installeren"
|
||||
StrCpy $PageReinstall_NEW_Field_2 "Verwijder oude versie"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "Behoud oude versie"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Al geïnstalleerd"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Kies hoe u ${APPLICATION_NAME} wilt installeren."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Er is al een recentere versie van ${APPLICATION_NAME} geïnstalleerd! Installeren van een oudere versie wordt niet aangeraden. Als u echt de oudere versie wilt installeren, adviseren we de huidige versie eerst te verwijderen. Kies de actie die u wilt uitvoeren en druk op Verder om door te gaan."
|
||||
|
||||
@@ -38,6 +38,6 @@ StrCpy $UAC_ERROR_ELEVATE "Rechte k
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Dieses Installationsprogramm erfordert Administrator-Rechte, bitte erneut versuchen"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "Das Installationsprogramm wird bereits ausgeführt."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Das Deinstallationsprogramm erfordert Administrator-Rechte. Bitte erneut versuchen."
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Anmeldedienst läuft nicht, abbruch!"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Das Deinstallationsprogramm wird bereits ausgeführt."
|
||||
StrCpy $SectionGroup_Shortcuts "Verknüpfungen"
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Logon service is not running, aborting!"
|
||||
|
||||
@@ -7,7 +7,7 @@ StrCpy $PageReinstall_NEW_Field_1 "Az ${APPLICATION_NAME} alkalmazás egy régeb
|
||||
StrCpy $PageReinstall_NEW_Field_2 "Eltávolítás telepítés előtt"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "Ne távolítsa el"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Már telepítve"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Válaszd ki, hogy szeretnéd telepíteni a következő alkalmazást ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Válassza ki, hogy szeretné telepíteni a következő alkalmazást: ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Az ${APPLICATION_NAME} alkalmazás egy újabb verziója már megtalálható a rendszeren. Nem ajánlott egy régebbi verzió telepítése. Ha valóban szeretné a régebbi verziót telepíteni, akkor ajánlott a jelenleg telepített verzió eltávolítása. Válassza ki milyen műveletet szeretne végrehajtani, és nyomja meg a $\"Következő$\" gombot a folytatáshoz."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "Az ${APPLICATION_NAME} alkalmazás ${VERSION} verziója már telepítve van.$↩$\nKérjük válaszd ki milyen műveletet szeretnél végrehajtani, és nyomd meg a „Következő” gombot."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Komponens hozzáadása/újratelepítése"
|
||||
@@ -31,13 +31,13 @@ StrCpy $UNINSTALLER_FILE_Detail "Elltávolító írása"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Telepítési registry kulcsok írása"
|
||||
StrCpy $UNINSTALLER_FINISHED_Detail "Befejezve!"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Nem sikerült az ${APPLICATION_NAME} alkalmazás telepítése a '$INSTDIR' könyvtárba.$\n$\nSzeretné mindenképpen folytatni (nem ajánlott)?"
|
||||
StrCpy $UNINSTALL_ABORT "Az eltávolítást egy felhasználó megszakította"
|
||||
StrCpy $UNINSTALL_ABORT "Az eltávolítást a felhasználó megszakította"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Gyorsindító hivatkozás (N/A)"
|
||||
StrCpy $INIT_NO_DESKTOP "Asztali hivatkozás (felülírja a meglévőt)"
|
||||
StrCpy $UAC_ERROR_ELEVATE "Nem sikerült felemelni, hiba:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "A telepítő futtatásához adminisztrátori hozzáférés szükséges, próbáld újra."
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "A telepítő futtatásához adminisztrátori hozzáférés szükséges, próbálja újra."
|
||||
StrCpy $INIT_INSTALLER_RUNNING "A telepítő már fut."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Az eltávolító futtatásához adminisztrátori hozzáférés szükséges, próbáld újra."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Az eltávolító futtatásához adminisztrátori hozzáférés szükséges, próbálja újra."
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "A bejelentkező szolgáltatás nem fut, megszakítás!"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Az eltávolító már fut."
|
||||
StrCpy $SectionGroup_Shortcuts "Parancsikonok"
|
||||
|
||||
@@ -9,6 +9,7 @@ StrCpy $PageReinstall_NEW_Field_3 "Nie usuwaj "
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Ju¿ zainstalowane"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Wybierz jak chcesz zainstalowaæ ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Zainstalowana jest nowsza wersja ${APPLICATION_NAME}! Niezalecane jest instalowanie starszej wersji. Jeœli naprawdê chcesz zainstalowaæ starsz¹ wersjê lepiej najpierw odinstalowaæ obecn¹ aplikacjê. Wybierz operacjê któr¹ chcesz wykonaæ i naciœnij przycisk Dalej."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} jest ju¿ zainstalowany.$\nWybierz operacjê któr¹ chcesz wykonaæ i naciœnij przycisk Dalej."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Doda/Przeinstaluj komponenty"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Odinstaluj ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Odinstaluj ${APPLICATION_NAME}"
|
||||
@@ -37,7 +38,6 @@ StrCpy $UAC_ERROR_ELEVATE "Niemo
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Ten instalator potrzebuje uprawnieñ administratora, spróbuj ponownie"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "Instalator ju¿ jest uruchomiony."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Ten dezinstalator potrzebuje uprawnieñ administratora, spróbuj ponownie"
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Proces logowania nie jest uruchomiony, przerywam !"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Dezinstalator ju¿ jest uruchomiony."
|
||||
StrCpy $SectionGroup_Shortcuts "Skróty"
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.$\r$\nSelect the operation you want to perform and click Next to continue."
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Logon service is not running, aborting!"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Auto-generated - do not modify
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Mostrar notas de lançamento"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Processos(s) ${APPLICATION_EXECUTABLE} em execução. Estes processos precisam de ser interrompidos.$\\nDeseja que o instalador os termine automaticamente?"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Existem ${APPLICATION_EXECUTABLE} processo(s) em execução que precisa(m) de ser interrompido(s).$\nDeseja que o instalador o(s) termine automaticamente?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "A terminar os processos ${APPLICATION_EXECUTABLE}."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Não foi encontrado o processo a terminar!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Uma versão antiga de ${APPLICATION_NAME} está instalada no sistema. É recomendado que você desinstale a versão atual antes de instalar a mais recente. Selecione a operação que deseja executar e clique em $\"Avançar$\" para continuar."
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Auto-generated - do not modify
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "查看版本日志"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "有 ${APPLICATION_EXECUTABLE} 项进程需要关闭。$\n您想让安装程序关闭这些进程吗?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "杀死${APPLICATION_EXECUTABLE}进程。"
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "未找到要杀死的进程!"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "停止${APPLICATION_EXECUTABLE}进程。"
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "未找到要停止的进程!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "您的系统已经安装${APPLICATION_NAME}较老版本。建议安装前卸载当前版本。选择将要执行的操作,点击下一步继续。"
|
||||
StrCpy $PageReinstall_NEW_Field_2 "在安装前先卸载"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "不要卸载"
|
||||
@@ -38,6 +38,6 @@ StrCpy $UAC_ERROR_ELEVATE "无法获得权限,错误:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "安装程序需要管理员权限,请重试"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "安装程序已经运行。"
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "卸载程序需要管理员权限,请重试"
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "登录服务器未运行!"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "卸载程序已经运行。"
|
||||
StrCpy $SectionGroup_Shortcuts "快捷方式"
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Logon service is not running, aborting!"
|
||||
|
||||
@@ -9,6 +9,7 @@ StrCpy $PageReinstall_NEW_Field_3 "Ne odstrani namestitve"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Program je že nameščen"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Izberite način namestitve programa ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Novejša različica programa ${APPLICATION_NAME} je že nameščena! Ni priporočljivo namestiti starejše. V kolikor želite vseeno nadaljevati z namestitvijo, prej odstranite obstoječo različico. Izberite opravilo in pritisnite gumb za nadaljevanje."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "Program ${APPLICATION_NAME} ${VERSION} je že nameščen.$\n$\nIzberite opravilo, ki ga želite izvesti in kliknite za nadaljevanje."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Dodaj/Ponovno namesti programe"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Odstrani ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Odstrani ${APPLICATION_NAME}"
|
||||
@@ -37,7 +38,6 @@ StrCpy $UAC_ERROR_ELEVATE "Ni mogo
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Namestilnik zahteva skrbniška dovoljenja."
|
||||
StrCpy $INIT_INSTALLER_RUNNING "Namestilnik je že zagnan."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Program za odstranjevanje namestitve zahteva skrbniška dovoljenja."
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Storitev za prijavo ni zagnana. Opravilo je ustavljeno!"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Program za odstranjevanje namestitve je že zagnan."
|
||||
StrCpy $SectionGroup_Shortcuts "Bližnjice"
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.$\r$\nSelect the operation you want to perform and click Next to continue."
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Logon service is not running, aborting!"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Auto-generated - do not modify
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Mostrar notas de la versión"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Se encontrarion ${APPLICATION_EXECUTABLE} proceso(s) que debe/n ser detenidos.$\"$\\n$\"¿Quiere que el instalador lo haga por usted?"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Se encontrarion ${APPLICATION_EXECUTABLE} proceso(s) que debe/n ser detenidos.$\"$\n$\"¿Quiere que el instalador lo haga por usted?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Parando el proceso ${APPLICATION_EXECUTABLE}."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Proceso a detener no encontrado!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Una versión anterior de ${APPLICATION_NAME} esta instalada en el sistema. Es recomendado que quite esta versión antes de instalar. Elija la operación a realizar y seleccione Siguiente para continuar."
|
||||
|
||||
@@ -14,6 +14,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Avinstallera ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Avinstallera ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Välj underhålls alternativ att utföra."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Installerar ${APPLICATION_NAME} väsentligheter."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integration för Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installerar integration för Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Start-meny program genväg"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Lägger till genväg för ${APPLICATION_NAME} till Start-menyn."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Skrivbordsgenväg"
|
||||
@@ -35,9 +37,7 @@ StrCpy $UAC_ERROR_ELEVATE "Kunde inte få förhöjda rättigheter, fel:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Detta installationsprogram kräver adminstratörs rättigheter, försök igen"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "Installationsprogrammet körs redan."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Detta avinstallationsprogram kräver administratörsrättigheter, försök igen"
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Login-service körs inte, avbryter!"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Avinstallationsprogrammet körs redan."
|
||||
StrCpy $SectionGroup_Shortcuts "Genvägar"
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.$\r$\nSelect the operation you want to perform and click Next to continue."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integration for Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing Integration for Windows Explorer"
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Logon service is not running, aborting!"
|
||||
|
||||
@@ -3,13 +3,13 @@ StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "แสดงบันทึกป
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "พบว่ากระบวนการ ${APPLICATION_EXECUTABLE} จะต้องหยุดทำงาน$\nคุณต้องการติดตั้งเพื่อหยุดการทำงานเหล่านี้ของคุณ?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "ฆ่ากระบวนการทำงาน ${APPLICATION_EXECUTABLE}"
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "ไม่พบการฆ่ากระบวนการ!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "รุ่นเก่าของ ${APPLICATION_NAME} มีการติดตั้งในระบบของคุณ ขอแนะนำให้คุณถอนการติดตั้งรุ่นปัจจุบันออกก่อน เลือกการดำเนินการที่คุณต้องการที่จะดำเนินการและคลิกถัดไปเพื่อดำเนินการต่อ"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "รุ่นเก่าของ ${APPLICATION_NAME} ได้ถูกติดตั้งในระบบของคุณ ขอแนะนำให้คุณถอนการติดตั้งรุ่นปัจจุบันออกก่อน แล้วเลือกการดำเนินการที่คุณต้องการหลังจากนั้นคลิกถัดไปเพื่อดำเนินการต่อ"
|
||||
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_OLD_Field_1 "รุ่นใหม่ของ ${APPLICATION_NAME} ถูกติดตั้งแล้ว! เราไม่แนะนำให้คุณติดตั้งรุ่นเก่า ถ้าคุณอยากจะติดตั้งรุ่นเก่าก็สามารถสอนการติดตั้งได้"
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} ถูกติดตั้งไปแล้ว$ $\nเลือกดำเนินงานที่คุณต้องการและคลิกถัดไปเพื่อดำเนินการต่อ"
|
||||
StrCpy $PageReinstall_OLD_Field_1 "รุ่นใหม่ของ ${APPLICATION_NAME} ถูกติดตั้งแล้ว! เราไม่แนะนำให้คุณติดตั้งรุ่นที่เก่ากว่า ถ้าคุณอยากจะติดตั้งรุ่นเก่าก็สามารถถอนการติดตั้งได้"
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} รุ่น ${VERSION} ถูกติดตั้งไปแล้ว$ $\nเลือกดำเนินงานที่คุณต้องการและคลิกถัดไปเพื่อดำเนินการต่อ"
|
||||
StrCpy $PageReinstall_SAME_Field_2 "ส่วนประกอบ เพิ่ม/ติดตั้งใหม่ "
|
||||
StrCpy $PageReinstall_SAME_Field_3 "ถอนการติดตั้ง ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "ถอนการติดตั้ง ${APPLICATION_NAME}"
|
||||
|
||||
@@ -9,6 +9,7 @@ StrCpy $PageReinstall_NEW_Field_3 "Не видаляти"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Установлено"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Оберіть, як ви хочете установити ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Знайдено новішу версію ${APPLICATION_NAME}! Ми не рекомендуємо встановлювати стару версію. Якщо ви все ж бажаєте встановити цю версію, спочатку видаліть поточну версію. Оберіть подальшу дію та натисніть $\"Далі$\"."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} вже встановлено.$\n$\nОберіть подальшу дію та натисніть $\"Далі$\" для продовження."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Додати/Перевстановити компоненти"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Видалити ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Видалити ${APPLICATION_NAME}"
|
||||
@@ -37,7 +38,6 @@ StrCpy $UAC_ERROR_ELEVATE "Неможливо підняти, помилка:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Для установки потрібні права адміністратора, спробуйте ще раз"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "Установка вже запущена."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Для видалення потрібні права адміністратора, спробуйте ще раз"
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Сервіс авторизації не запущений, припиняю!"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Програма видалення вже запущено."
|
||||
StrCpy $SectionGroup_Shortcuts "Ярлики"
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.$\r$\nSelect the operation you want to perform and click Next to continue."
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Logon service is not running, aborting!"
|
||||
|
||||
@@ -108,7 +108,8 @@ def escapeNSIS(st):
|
||||
.replace('\n', r'$\n')\
|
||||
.replace('\"', r'$\"')\
|
||||
.replace('$$\\', '$\\')\
|
||||
.replace('$\\n', r'$\n')
|
||||
.replace('$\\n', r'$\n')\
|
||||
.replace('$\\\\n', r'$\n')
|
||||
|
||||
|
||||
translationCache = {}
|
||||
|
||||
@@ -22,5 +22,6 @@
|
||||
<file>resources/account.png</file>
|
||||
<file>resources/more.png</file>
|
||||
<file>resources/delete.png</file>
|
||||
<file>resources/bell.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -20,15 +20,4 @@ function (ADD_CMOCKA_TEST _testName _testSource)
|
||||
add_executable(${_testName} ${_testSource})
|
||||
target_link_libraries(${_testName} ${ARGN})
|
||||
add_test(${_testName} ${CMAKE_CURRENT_BINARY_DIR}/${_testName})
|
||||
|
||||
if(UNIT_TESTING)
|
||||
INSTALL(
|
||||
TARGETS
|
||||
${_testName}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
endif(UNIT_TESTING)
|
||||
|
||||
endfunction (ADD_CMOCKA_TEST)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleLongVersionString</key>
|
||||
<string>@APPLICATION_NAME@ @MIRALL_VERSION_STRING@</string>
|
||||
<string>@APPLICATION_NAME_XML_ESCAPED@ @MIRALL_VERSION_STRING@</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleSignature</key>
|
||||
@@ -27,7 +27,7 @@
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>@MIRALL_VERSION_STRING@</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>(C) 2014-2015 @APPLICATION_VENDOR@</string>
|
||||
<string>(C) 2014-2016 @APPLICATION_VENDOR@</string>
|
||||
<key>SUShowReleaseNotes</key>
|
||||
<false/>
|
||||
<key>LSMinimumBundleVersion</key>
|
||||
|
||||
@@ -757,6 +757,12 @@ Function .onInit
|
||||
|
||||
;Shutdown ${APPLICATION_NAME} in case Add/Remove re-installer option used.
|
||||
Call EnsureOwncloudShutdown
|
||||
|
||||
ReadRegStr $R0 ${MEMENTO_REGISTRY_ROOT} "${MEMENTO_REGISTRY_KEY}" "InstallLocation"
|
||||
${If} ${Silent}
|
||||
${AndIf} $R0 != ""
|
||||
ExecWait '"$R0\Uninstall.exe" /S _?=$R0'
|
||||
${EndIf}
|
||||
FunctionEnd
|
||||
|
||||
Function .onInstSuccess
|
||||
@@ -766,6 +772,11 @@ Function .onInstSuccess
|
||||
WriteRegDWORD HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "skipUpdateCheck" "1"
|
||||
${EndIf}
|
||||
|
||||
; TODO: Only needed to when updating from 2.1.{0,1}. Remove in due time.
|
||||
Delete /REBOOTOK $INSTDIR\bearer\qgenericbearer.dll
|
||||
Delete /REBOOTOK $INSTDIR\bearer\qnativewifibearer.dll
|
||||
RMDir /REBOOTOK $INSTDIR\bearer
|
||||
|
||||
${If} ${Silent}
|
||||
${AndIf} $InstallRunIfSilent == "yes"
|
||||
Call LaunchApplication
|
||||
|
||||
@@ -18,6 +18,9 @@ if( Qt5Core_FOUND )
|
||||
find_package(Qt5Network REQUIRED)
|
||||
find_package(Qt5Xml REQUIRED)
|
||||
find_package(Qt5Concurrent REQUIRED)
|
||||
if(UNIT_TESTING)
|
||||
find_package(Qt5Test REQUIRED)
|
||||
endif()
|
||||
if(NOT TOKEN_AUTH_ONLY)
|
||||
find_package(Qt5WebKitWidgets REQUIRED)
|
||||
find_package(Qt5WebKit REQUIRED)
|
||||
|
||||
@@ -128,10 +128,4 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
# INSTALL(
|
||||
# FILES
|
||||
# ${csync_HDRS}
|
||||
# DESTINATION
|
||||
# ${INCLUDE_INSTALL_DIR}/${APPLICATION_NAME}
|
||||
# )
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -89,14 +90,11 @@ static int _data_cmp(const void *key, const void *data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int csync_create(CSYNC **csync, const char *local, const char *remote) {
|
||||
void csync_create(CSYNC **csync, const char *local, const char *remote) {
|
||||
CSYNC *ctx;
|
||||
size_t len = 0;
|
||||
|
||||
ctx = c_malloc(sizeof(CSYNC));
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
@@ -121,46 +119,21 @@ int csync_create(CSYNC **csync, const char *local, const char *remote) {
|
||||
ctx->ignore_hidden_files = true;
|
||||
|
||||
*csync = ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int csync_init(CSYNC *ctx) {
|
||||
int rc;
|
||||
|
||||
if (ctx == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
void csync_init(CSYNC *ctx) {
|
||||
assert(ctx);
|
||||
/* Do not initialize twice */
|
||||
if (ctx->status & CSYNC_STATUS_INIT) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* check for uri */
|
||||
if (csync_fnmatch("owncloud://*", ctx->remote.uri, 0) == 0 && csync_fnmatch("ownclouds://*", ctx->remote.uri, 0) == 0) {
|
||||
ctx->status_code = CSYNC_STATUS_NO_MODULE;
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
assert(!(ctx->status & CSYNC_STATUS_INIT));
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
ctx->local.type = LOCAL_REPLICA;
|
||||
|
||||
ctx->remote.type = REMOTE_REPLICA;
|
||||
|
||||
if (c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp) < 0) {
|
||||
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c_rbtree_create(&ctx->remote.tree, _key_cmp, _data_cmp) < 0) {
|
||||
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp);
|
||||
c_rbtree_create(&ctx->remote.tree, _key_cmp, _data_cmp);
|
||||
|
||||
ctx->remote.root_perms = 0;
|
||||
|
||||
@@ -168,11 +141,6 @@ int csync_init(CSYNC *ctx) {
|
||||
|
||||
/* initialize random generator */
|
||||
srand(time(NULL));
|
||||
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int csync_update(CSYNC *ctx) {
|
||||
@@ -580,29 +548,17 @@ int csync_commit(CSYNC *ctx) {
|
||||
ctx->remote.read_from_db = 0;
|
||||
ctx->read_remote_from_db = true;
|
||||
ctx->db_is_empty = false;
|
||||
ctx->ignore_hidden_files = true; // do NOT sync hidden files by default.
|
||||
|
||||
|
||||
/* Create new trees */
|
||||
rc = c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp);
|
||||
if (rc < 0) {
|
||||
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = c_rbtree_create(&ctx->remote.tree, _key_cmp, _data_cmp);
|
||||
if (rc < 0) {
|
||||
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
|
||||
goto out;
|
||||
}
|
||||
c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp);
|
||||
c_rbtree_create(&ctx->remote.tree, _key_cmp, _data_cmp);
|
||||
|
||||
|
||||
ctx->status = CSYNC_STATUS_INIT;
|
||||
SAFE_FREE(ctx->error_string);
|
||||
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -622,9 +578,6 @@ int csync_destroy(CSYNC *ctx) {
|
||||
}
|
||||
ctx->statedb.db = NULL;
|
||||
|
||||
/* destroy exclude list */
|
||||
csync_exclude_destroy(ctx);
|
||||
|
||||
_csync_clean_ctx(ctx);
|
||||
|
||||
SAFE_FREE(ctx->local.uri);
|
||||
@@ -640,19 +593,6 @@ int csync_destroy(CSYNC *ctx) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
int csync_add_exclude_list(CSYNC *ctx, const char *path) {
|
||||
if (ctx == NULL || path == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return csync_exclude_load(path, &ctx->excludes);
|
||||
}
|
||||
|
||||
void csync_clear_exclude_list(CSYNC *ctx)
|
||||
{
|
||||
csync_exclude_clear(ctx);
|
||||
}
|
||||
|
||||
void *csync_get_userdata(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return NULL;
|
||||
|
||||
@@ -316,10 +316,8 @@ typedef const char* (*csync_checksum_hook) (
|
||||
* @brief Allocate a csync context.
|
||||
*
|
||||
* @param csync The context variable to allocate.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
*/
|
||||
int csync_create(CSYNC **csync, const char *local, const char *remote);
|
||||
void csync_create(CSYNC **csync, const char *local, const char *remote);
|
||||
|
||||
/**
|
||||
* @brief Initialize the file synchronizer.
|
||||
@@ -327,17 +325,15 @@ int csync_create(CSYNC **csync, const char *local, const char *remote);
|
||||
* This function loads the configuration
|
||||
*
|
||||
* @param ctx The context to initialize.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
*/
|
||||
int csync_init(CSYNC *ctx);
|
||||
void csync_init(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Update detection
|
||||
*
|
||||
* @param ctx The context to run the update detection on.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_update(CSYNC *ctx);
|
||||
|
||||
@@ -346,7 +342,7 @@ int csync_update(CSYNC *ctx);
|
||||
*
|
||||
* @param ctx The context to run the reconciliation on.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_reconcile(CSYNC *ctx);
|
||||
|
||||
@@ -355,7 +351,7 @@ int csync_reconcile(CSYNC *ctx);
|
||||
*
|
||||
* @param ctx The context to commit.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_commit(CSYNC *ctx);
|
||||
|
||||
@@ -366,35 +362,17 @@ int csync_commit(CSYNC *ctx);
|
||||
*
|
||||
* @param ctx The context to destroy.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_destroy(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Add an additional exclude list.
|
||||
*
|
||||
* @param ctx The context to add the exclude list.
|
||||
*
|
||||
* @param path The path pointing to the file.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
*/
|
||||
int csync_add_exclude_list(CSYNC *ctx, const char *path);
|
||||
|
||||
/**
|
||||
* @brief Removes all items imported from exclude lists.
|
||||
*
|
||||
* @param ctx The context to add the exclude list.
|
||||
*/
|
||||
void csync_clear_exclude_list(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Get the userdata saved in the context.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*
|
||||
* @return The userdata saved in the context, NULL if an error
|
||||
* occured.
|
||||
* occurred.
|
||||
*/
|
||||
void *csync_get_userdata(CSYNC *ctx);
|
||||
|
||||
@@ -406,7 +384,7 @@ void *csync_get_userdata(CSYNC *ctx);
|
||||
*
|
||||
* @param userdata The userdata to be stored in the context.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_set_userdata(CSYNC *ctx, void *userdata);
|
||||
|
||||
@@ -416,7 +394,7 @@ int csync_set_userdata(CSYNC *ctx, void *userdata);
|
||||
* @param ctx The csync context.
|
||||
*
|
||||
* @return The authentication callback set or NULL if an error
|
||||
* occured.
|
||||
* occurred.
|
||||
*/
|
||||
csync_auth_callback csync_get_auth_callback(CSYNC *ctx);
|
||||
|
||||
@@ -427,7 +405,7 @@ csync_auth_callback csync_get_auth_callback(CSYNC *ctx);
|
||||
*
|
||||
* @param cb The authentication callback.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_set_auth_callback(CSYNC *ctx, csync_auth_callback cb);
|
||||
|
||||
@@ -436,7 +414,7 @@ int csync_set_auth_callback(CSYNC *ctx, csync_auth_callback cb);
|
||||
*
|
||||
* @param[in] level The log verbosity.
|
||||
*
|
||||
* @return 0 on success, < 0 if an error occured.
|
||||
* @return 0 on success, < 0 if an error occurred.
|
||||
*/
|
||||
int csync_set_log_level(int level);
|
||||
|
||||
@@ -451,7 +429,7 @@ int csync_get_log_level(void);
|
||||
* @brief Get the logging callback set.
|
||||
*
|
||||
* @return The logging callback set or NULL if an error
|
||||
* occured.
|
||||
* occurred.
|
||||
*/
|
||||
csync_log_callback csync_get_log_callback(void);
|
||||
|
||||
@@ -460,7 +438,7 @@ csync_log_callback csync_get_log_callback(void);
|
||||
*
|
||||
* @param cb The logging callback.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_set_log_callback(csync_log_callback cb);
|
||||
|
||||
@@ -476,7 +454,7 @@ void *csync_get_log_userdata(void);
|
||||
*
|
||||
* @param[in] data The userdata to set.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_set_log_userdata(void *data);
|
||||
|
||||
@@ -495,7 +473,7 @@ typedef int csync_treewalk_visit_func(TREE_WALK_FILE* ,void*);
|
||||
* @param visitor A callback function to handle the file info.
|
||||
* @param filter A filter, built from or'ed csync_instructions_e
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter);
|
||||
|
||||
@@ -506,7 +484,7 @@ int csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int fi
|
||||
* @param visitor A callback function to handle the file info.
|
||||
* @param filter A filter, built from and'ed csync_instructions_e
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter);
|
||||
|
||||
|
||||
@@ -47,6 +47,45 @@ int _csync_exclude_add(c_strlist_t **inList, const char *string) {
|
||||
return c_strlist_add_grow(inList, string);
|
||||
}
|
||||
|
||||
/** Expands C-like escape sequences.
|
||||
*
|
||||
* The returned string is heap-allocated and owned by the caller.
|
||||
*/
|
||||
static const char *csync_exclude_expand_escapes(const char * input)
|
||||
{
|
||||
size_t i_len = strlen(input) + 1;
|
||||
char *out = c_malloc(i_len); // out can only be shorter
|
||||
|
||||
size_t i = 0;
|
||||
size_t o = 0;
|
||||
for (; i < i_len; ++i) {
|
||||
if (input[i] == '\\') {
|
||||
// at worst input[i+1] is \0
|
||||
switch (input[i+1]) {
|
||||
case '\'': out[o++] = '\''; break;
|
||||
case '"': out[o++] = '"'; break;
|
||||
case '?': out[o++] = '?'; break;
|
||||
case '\\': out[o++] = '\\'; break;
|
||||
case 'a': out[o++] = '\a'; break;
|
||||
case 'b': out[o++] = '\b'; break;
|
||||
case 'f': out[o++] = '\f'; break;
|
||||
case 'n': out[o++] = '\n'; break;
|
||||
case 'r': out[o++] = '\r'; break;
|
||||
case 't': out[o++] = '\t'; break;
|
||||
case 'v': out[o++] = '\v'; break;
|
||||
default:
|
||||
out[o++] = input[i];
|
||||
out[o++] = input[i+1];
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
} else {
|
||||
out[o++] = input[i];
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int csync_exclude_load(const char *fname, c_strlist_t **list) {
|
||||
int fd = -1;
|
||||
int i = 0;
|
||||
@@ -99,8 +138,10 @@ int csync_exclude_load(const char *fname, c_strlist_t **list) {
|
||||
if (entry != buf + i) {
|
||||
buf[i] = '\0';
|
||||
if (*entry != '#') {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Adding entry: %s", entry);
|
||||
rc = _csync_exclude_add(list, entry);
|
||||
const char *unescaped = csync_exclude_expand_escapes(entry);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Adding entry: %s", unescaped);
|
||||
rc = _csync_exclude_add(list, unescaped);
|
||||
SAFE_FREE(unescaped);
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
@@ -117,23 +158,6 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
void csync_exclude_clear(CSYNC *ctx) {
|
||||
c_strlist_clear(ctx->excludes);
|
||||
}
|
||||
|
||||
void csync_exclude_destroy(CSYNC *ctx) {
|
||||
c_strlist_destroy(ctx->excludes);
|
||||
}
|
||||
|
||||
CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype) {
|
||||
|
||||
CSYNC_EXCLUDE_TYPE match = CSYNC_NOT_EXCLUDED;
|
||||
|
||||
match = csync_excluded_no_ctx( ctx->excludes, path, filetype );
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
// See http://support.microsoft.com/kb/74496 and
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
|
||||
// Additionally, we ignore '$Recycle.Bin', see https://github.com/owncloud/client/issues/2955
|
||||
|
||||
@@ -43,41 +43,10 @@ int _csync_exclude_add(c_strlist_t **inList, const char *string);
|
||||
* @param ctx The context of the synchronizer.
|
||||
* @param fname The filename to load.
|
||||
*
|
||||
* @return 0 on success, -1 if an error occured with errno set.
|
||||
* @return 0 on success, -1 if an error occurred with errno set.
|
||||
*/
|
||||
int csync_exclude_load(const char *fname, c_strlist_t **list);
|
||||
|
||||
/**
|
||||
* @brief Clear the exclude list in memory.
|
||||
*
|
||||
* @param ctx The synchronizer context.
|
||||
*/
|
||||
void csync_exclude_clear(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Destroy the exclude list in memory.
|
||||
*
|
||||
* @param ctx The synchronizer context.
|
||||
*/
|
||||
void csync_exclude_destroy(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Check if the given path should be excluded.
|
||||
*
|
||||
* This excludes also paths which can't be used without unix extensions.
|
||||
*
|
||||
* The exclude list is checked against the full path, each component of
|
||||
* the path and all leading directory strings, e.g.
|
||||
* '/foo/bar/file' checks ('/foo/bar/file', 'foo', 'bar', 'file',
|
||||
* '/foo/bar', '/foo').
|
||||
*
|
||||
* @param ctx The synchronizer context.
|
||||
* @param path The patch to check.
|
||||
*
|
||||
* @return 2 if excluded and needs cleanup, 1 if excluded, 0 if not.
|
||||
*/
|
||||
CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype);
|
||||
|
||||
/**
|
||||
* @brief Check if the given path should be excluded in a traversal situation.
|
||||
*
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
* than fmmatch anyway, which does not care for flags.
|
||||
**/
|
||||
#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
|
||||
#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
|
||||
#endif
|
||||
|
||||
int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags);
|
||||
|
||||
@@ -54,7 +54,7 @@ int csync_get_statedb_exists(CSYNC *ctx);
|
||||
* @param ctx The csync context.
|
||||
* @param statedb Path to the statedb file (sqlite3 db).
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured with errno set.
|
||||
* @return 0 on success, less than 0 if an error occurred with errno set.
|
||||
*/
|
||||
int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb);
|
||||
|
||||
|
||||
@@ -106,6 +106,42 @@ static bool _last_db_return_error(CSYNC* ctx) {
|
||||
return ctx->statedb.lastReturnValue != SQLITE_OK && ctx->statedb.lastReturnValue != SQLITE_DONE && ctx->statedb.lastReturnValue != SQLITE_ROW;
|
||||
}
|
||||
|
||||
/*
|
||||
* This static method is needed because the type members of the two structs use
|
||||
* different enum values. A direct comparion is not neccessarily correct.
|
||||
*
|
||||
* tmp is csync_file_stat_t
|
||||
* fs is csync_vio_file_stat_t with this vio type:
|
||||
* enum csync_vio_file_type_e {
|
||||
* CSYNC_VIO_FILE_TYPE_UNKNOWN,
|
||||
* CSYNC_VIO_FILE_TYPE_REGULAR,
|
||||
* CSYNC_VIO_FILE_TYPE_DIRECTORY,
|
||||
* CSYNC_VIO_FILE_TYPE_FIFO,
|
||||
* CSYNC_VIO_FILE_TYPE_SOCKET,
|
||||
* CSYNC_VIO_FILE_TYPE_CHARACTER_DEVICE,
|
||||
* CSYNC_VIO_FILE_TYPE_BLOCK_DEVICE,
|
||||
* CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK
|
||||
* };
|
||||
*
|
||||
* csync_file_stat_t can be:
|
||||
* CSYNC_FTW_TYPE_SKIP, CSYNC_FTW_TYPE_FILE
|
||||
* CSYNC_FTW_TYPE_DIR, CSYNC_FTW_TYPE_SLINK
|
||||
*/
|
||||
static bool _csync_filetype_different( const csync_file_stat_t *tmp, const csync_vio_file_stat_t *fs)
|
||||
{
|
||||
if( !(tmp && fs)) return false;
|
||||
|
||||
if( tmp->type == CSYNC_FTW_TYPE_SKIP ) return true;
|
||||
|
||||
if( tmp->type == CSYNC_FTW_TYPE_DIR && fs->type != CSYNC_VIO_FILE_TYPE_DIRECTORY )
|
||||
return true;
|
||||
if( tmp->type == CSYNC_FTW_TYPE_FILE && fs->type != CSYNC_VIO_FILE_TYPE_REGULAR )
|
||||
return true;
|
||||
if( tmp->type == CSYNC_FTW_TYPE_SLINK && fs->type != CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK )
|
||||
return true;
|
||||
|
||||
return false; // both are NOT different.
|
||||
}
|
||||
|
||||
/* Return true if two mtime are considered equal
|
||||
* We consider mtime that are one hour difference to be equal if they are one hour appart
|
||||
@@ -209,33 +245,9 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
st->etag = NULL;
|
||||
st->child_modified = 0;
|
||||
st->has_ignored_files = 0;
|
||||
|
||||
/* FIXME: Under which conditions are the following two ifs true and the code
|
||||
* is executed? */
|
||||
if (type == CSYNC_FTW_TYPE_FILE ) {
|
||||
if (fs->mtime == 0) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s - mtime is zero!", path);
|
||||
|
||||
tmp = csync_statedb_get_stat_by_hash(ctx, h);
|
||||
if(_last_db_return_error(ctx)) {
|
||||
SAFE_FREE(st);
|
||||
SAFE_FREE(tmp);
|
||||
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tmp == NULL) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s - not found in db, IGNORE!", path);
|
||||
st->instruction = CSYNC_INSTRUCTION_IGNORE;
|
||||
} else {
|
||||
SAFE_FREE(st);
|
||||
st = tmp;
|
||||
st->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s - tmp non zero, mtime %lu", path, st->modtime );
|
||||
tmp = NULL;
|
||||
}
|
||||
goto fastout; /* Skip copying of the etag. That's an important difference to upstream
|
||||
* without etags. */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,8 +286,9 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
st->instruction = CSYNC_INSTRUCTION_EVAL;
|
||||
|
||||
// Preserve the EVAL flag later on if the type has changed.
|
||||
if (tmp->type != fs->type)
|
||||
if (_csync_filetype_different(tmp, fs)) {
|
||||
st->child_modified = 1;
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
@@ -284,7 +297,10 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
// zero size in statedb can happen during migration
|
||||
|| (tmp->size != 0 && fs->size != tmp->size))) {
|
||||
|
||||
if (fs->size == tmp->size && tmp->checksumTypeId) {
|
||||
// Checksum comparison at this stage is only enabled for .eml files,
|
||||
// check #4754 #4755
|
||||
bool isEmlFile = csync_fnmatch("*.eml", file, FNM_CASEFOLD) == 0;
|
||||
if (isEmlFile && fs->size == tmp->size && tmp->checksumTypeId) {
|
||||
if (ctx->callbacks.checksum_hook) {
|
||||
st->checksum = ctx->callbacks.checksum_hook(
|
||||
file, tmp->checksumTypeId,
|
||||
@@ -296,6 +312,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
checksumIdentical = strncmp(st->checksum, tmp->checksum, 1000) == 0;
|
||||
}
|
||||
if (checksumIdentical) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "NOTE: Checksums are identical, file did not actually change: %s", path);
|
||||
st->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
st->should_update_metadata = true;
|
||||
goto out;
|
||||
@@ -303,8 +320,9 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
}
|
||||
|
||||
// Preserve the EVAL flag later on if the type has changed.
|
||||
if (tmp->type != fs->type)
|
||||
if (_csync_filetype_different(tmp, fs)) {
|
||||
st->child_modified = 1;
|
||||
}
|
||||
|
||||
st->instruction = CSYNC_INSTRUCTION_EVAL;
|
||||
goto out;
|
||||
@@ -353,32 +371,51 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
}
|
||||
|
||||
/* translate the file type between the two stat types csync has. */
|
||||
if( tmp && tmp->type == 0 ) {
|
||||
if( tmp && tmp->type == CSYNC_FTW_TYPE_FILE ) {
|
||||
tmp_vio_type = CSYNC_VIO_FILE_TYPE_REGULAR;
|
||||
} else if( tmp && tmp->type == 2 ) {
|
||||
} else if( tmp && tmp->type == CSYNC_FTW_TYPE_DIR) {
|
||||
tmp_vio_type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
|
||||
} else if( tmp && tmp->type == CSYNC_FTW_TYPE_SLINK ) {
|
||||
tmp_vio_type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK;
|
||||
} else {
|
||||
tmp_vio_type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
if (tmp && tmp->inode == fs->inode && tmp_vio_type == fs->type
|
||||
// Default to NEW unless we're sure it's a rename.
|
||||
st->instruction = CSYNC_INSTRUCTION_NEW;
|
||||
|
||||
bool isRename =
|
||||
tmp && tmp->inode == fs->inode && tmp_vio_type == fs->type
|
||||
&& (tmp->modtime == fs->mtime || fs->type == CSYNC_VIO_FILE_TYPE_DIRECTORY)
|
||||
#ifdef NO_RENAME_EXTENSION
|
||||
&& _csync_sameextension(tmp->path, path)
|
||||
#endif
|
||||
) {
|
||||
;
|
||||
|
||||
|
||||
// Verify the checksum where possible
|
||||
if (isRename && tmp->checksumTypeId && ctx->callbacks.checksum_hook
|
||||
&& fs->type == CSYNC_VIO_FILE_TYPE_REGULAR) {
|
||||
st->checksum = ctx->callbacks.checksum_hook(
|
||||
file, tmp->checksumTypeId,
|
||||
ctx->callbacks.checksum_userdata);
|
||||
if (st->checksum) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "checking checksum of potential rename %s %s <-> %s", path, st->checksum, tmp->checksum);
|
||||
st->checksumTypeId = tmp->checksumTypeId;
|
||||
isRename = strncmp(st->checksum, tmp->checksum, 1000) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (isRename) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "pot rename detected based on inode # %" PRId64 "", (uint64_t) fs->inode);
|
||||
/* inode found so the file has been renamed */
|
||||
st->instruction = CSYNC_INSTRUCTION_EVAL_RENAME;
|
||||
if (fs->type == CSYNC_VIO_FILE_TYPE_DIRECTORY) {
|
||||
csync_rename_record(ctx, tmp->path, path);
|
||||
}
|
||||
goto out;
|
||||
} else {
|
||||
/* file not found in statedb */
|
||||
st->instruction = CSYNC_INSTRUCTION_NEW;
|
||||
goto out;
|
||||
}
|
||||
goto out;
|
||||
|
||||
} else {
|
||||
/* Remote Replica Rename check */
|
||||
tmp = csync_statedb_get_stat_by_file_id(ctx, fs->file_id);
|
||||
@@ -389,8 +426,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
return -1;
|
||||
}
|
||||
if(tmp ) { /* tmp existing at all */
|
||||
if ((tmp->type == CSYNC_FTW_TYPE_DIR && fs->type != CSYNC_VIO_FILE_TYPE_DIRECTORY) ||
|
||||
(tmp->type == CSYNC_FTW_TYPE_FILE && fs->type != CSYNC_VIO_FILE_TYPE_REGULAR)) {
|
||||
if ( _csync_filetype_different(tmp, fs)) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "WARN: file types different is not!");
|
||||
st->instruction = CSYNC_INSTRUCTION_NEW;
|
||||
goto out;
|
||||
@@ -479,7 +515,6 @@ out:
|
||||
strncpy(st->remotePerm, fs->remotePerm, REMOTE_PERM_BUF_SIZE);
|
||||
}
|
||||
|
||||
fastout: /* target if the file information is read from database into st */
|
||||
st->phash = h;
|
||||
st->pathlen = len;
|
||||
memcpy(st->path, (len ? path : ""), len + 1);
|
||||
@@ -524,7 +559,11 @@ int csync_walker(CSYNC *ctx, const char *file, const csync_vio_file_stat_t *fs,
|
||||
switch (flag) {
|
||||
case CSYNC_FTW_FLAG_FILE:
|
||||
if (ctx->current == REMOTE_REPLICA) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [file_id=%s size=%" PRIu64 "]", file, fs->file_id, fs->size);
|
||||
if (fs->fields & CSYNC_VIO_FILE_STAT_FIELDS_SIZE) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [file_id=%s size=%" PRIu64 "]", file, fs->file_id, fs->size);
|
||||
} else {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [file_id=%s size=UNKNOWN]", file, fs->file_id);
|
||||
}
|
||||
} else {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [inode=%" PRIu64 " size=%" PRIu64 "]", file, fs->inode, fs->size);
|
||||
}
|
||||
@@ -781,7 +820,9 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
* local stat function.
|
||||
*/
|
||||
if( d_name[0] == '.' ) {
|
||||
dirent->flags |= CSYNC_VIO_FILE_FLAGS_HIDDEN;
|
||||
if (strcmp(".sys.admin#recall#", d_name) != 0) { /* recall file shall not be ignored (#4420) */
|
||||
dirent->flags |= CSYNC_VIO_FILE_FLAGS_HIDDEN;
|
||||
}
|
||||
}
|
||||
|
||||
if( res == 0) {
|
||||
|
||||
@@ -38,13 +38,12 @@
|
||||
#define NIL &_sentinel /* all leafs are sentinels */
|
||||
static c_rbnode_t _sentinel = {NULL, NIL, NIL, NULL, NULL, BLACK};
|
||||
|
||||
int c_rbtree_create(c_rbtree_t **rbtree, c_rbtree_compare_func *key_compare, c_rbtree_compare_func *data_compare) {
|
||||
c_rbtree_t *tree = NULL;
|
||||
void c_rbtree_create(c_rbtree_t **rbtree, c_rbtree_compare_func *key_compare, c_rbtree_compare_func *data_compare) {
|
||||
assert(rbtree);
|
||||
assert(key_compare);
|
||||
assert(data_compare);
|
||||
|
||||
if (rbtree == NULL || key_compare == NULL || data_compare == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
c_rbtree_t *tree = NULL;
|
||||
|
||||
tree = c_malloc(sizeof(*tree));
|
||||
tree->root = NIL;
|
||||
@@ -53,8 +52,6 @@ int c_rbtree_create(c_rbtree_t **rbtree, c_rbtree_compare_func *key_compare, c_r
|
||||
tree->size = 0;
|
||||
|
||||
*rbtree = tree;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static c_rbnode_t *_rbtree_subtree_dup(const c_rbnode_t *node, c_rbtree_t *new_tree, c_rbnode_t *new_parent) {
|
||||
|
||||
@@ -135,10 +135,8 @@ struct c_rbnode_s {
|
||||
*
|
||||
* @param data_compare Callback function to compare a key as data with thee
|
||||
* data inside a red-black tree node.
|
||||
*
|
||||
* @return 0 on success, -1 if an error occured with errno set.
|
||||
*/
|
||||
int c_rbtree_create(c_rbtree_t **rbtree, c_rbtree_compare_func *key_compare, c_rbtree_compare_func *data_compare);
|
||||
void c_rbtree_create(c_rbtree_t **rbtree, c_rbtree_compare_func *key_compare, c_rbtree_compare_func *data_compare);
|
||||
|
||||
/**
|
||||
* @brief Duplicate a red-black tree.
|
||||
@@ -146,7 +144,7 @@ int c_rbtree_create(c_rbtree_t **rbtree, c_rbtree_compare_func *key_compare, c_r
|
||||
* @param tree Tree to duplicate.
|
||||
*
|
||||
* @return Pointer to a new allocated duplicated rbtree. NULL if an error
|
||||
* occured.
|
||||
* occurred.
|
||||
*/
|
||||
c_rbtree_t *c_rbtree_dup(const c_rbtree_t *tree);
|
||||
|
||||
@@ -157,7 +155,7 @@ c_rbtree_t *c_rbtree_dup(const c_rbtree_t *tree);
|
||||
*
|
||||
* @param tree The tree to free.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int c_rbtree_free(c_rbtree_t *tree);
|
||||
|
||||
@@ -198,7 +196,7 @@ int c_rbtree_free(c_rbtree_t *tree);
|
||||
* @param data The data to insert into the tree.
|
||||
*
|
||||
* @return 0 on success, 1 if a duplicate has been found and < 0 if an error
|
||||
* occured with errno set.
|
||||
* occurred with errno set.
|
||||
* EINVAL if a null pointer has been passed as the tree.
|
||||
* ENOMEM if there is no memory left.
|
||||
*/
|
||||
@@ -223,7 +221,7 @@ c_rbnode_t *c_rbtree_find(c_rbtree_t *tree, const void *key);
|
||||
*
|
||||
* @param tree The tree to get the head for.
|
||||
*
|
||||
* @return The head node. NULL if an error occured.
|
||||
* @return The head node. NULL if an error occurred.
|
||||
*/
|
||||
c_rbnode_t *c_rbtree_head(c_rbtree_t *tree);
|
||||
|
||||
@@ -232,7 +230,7 @@ c_rbnode_t *c_rbtree_head(c_rbtree_t *tree);
|
||||
*
|
||||
* @param tree The tree to get the tail for.
|
||||
*
|
||||
* @return The tail node. NULL if an error occured.
|
||||
* @return The tail node. NULL if an error occurred.
|
||||
*/
|
||||
c_rbnode_t *c_rbtree_tail(c_rbtree_t *tree);
|
||||
|
||||
@@ -254,7 +252,7 @@ c_rbnode_t *c_rbtree_tail(c_rbtree_t *tree);
|
||||
* @param data Data which should be passed to the visitor function.
|
||||
* @param visitor Visitor function. This will be called for each node passed.
|
||||
*
|
||||
* @return 0 on sucess, less than 0 if an error occured.
|
||||
* @return 0 on sucess, less than 0 if an error occurred.
|
||||
*/
|
||||
int c_rbtree_walk(c_rbtree_t *tree, void *data, c_rbtree_visit_func *visitor);
|
||||
|
||||
@@ -263,7 +261,7 @@ int c_rbtree_walk(c_rbtree_t *tree, void *data, c_rbtree_visit_func *visitor);
|
||||
*
|
||||
* @param node Node which should be deleted.
|
||||
*
|
||||
* @return 0 on success, -1 if an error occured.
|
||||
* @return 0 on success, -1 if an error occurred.
|
||||
*/
|
||||
int c_rbtree_node_delete(c_rbnode_t *node);
|
||||
|
||||
@@ -272,7 +270,7 @@ int c_rbtree_node_delete(c_rbnode_t *node);
|
||||
*
|
||||
* @param node The node of which you want the next node.
|
||||
*
|
||||
* @return The next node, NULL if an error occured.
|
||||
* @return The next node, NULL if an error occurred.
|
||||
*/
|
||||
c_rbnode_t *c_rbtree_node_next(c_rbnode_t *node);
|
||||
|
||||
@@ -281,7 +279,7 @@ c_rbnode_t *c_rbtree_node_next(c_rbnode_t *node);
|
||||
*
|
||||
* @param node The node of which you want the previous node.
|
||||
*
|
||||
* @return The previous node, NULL if an error occured.
|
||||
* @return The previous node, NULL if an error occurred.
|
||||
*/
|
||||
c_rbnode_t *c_rbtree_node_prev(c_rbnode_t *node);
|
||||
|
||||
@@ -290,7 +288,7 @@ c_rbnode_t *c_rbtree_node_prev(c_rbnode_t *node);
|
||||
*
|
||||
* @param N The node to get the data from.
|
||||
*
|
||||
* @return The data, NULL if an error occured.
|
||||
* @return The data, NULL if an error occurred.
|
||||
*/
|
||||
#define c_rbtree_node_data(N) ((N) ? ((N)->data) : NULL)
|
||||
|
||||
@@ -301,7 +299,7 @@ c_rbnode_t *c_rbtree_node_prev(c_rbnode_t *node);
|
||||
*
|
||||
* @param tree The tree to check.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int c_rbtree_check_sanity(c_rbtree_t *tree);
|
||||
|
||||
|
||||
@@ -139,7 +139,6 @@ csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_handle_t *dhandle) {
|
||||
|
||||
dhandle_t *handle = NULL;
|
||||
csync_vio_file_stat_t *file_stat = NULL;
|
||||
ULARGE_INTEGER FileIndex;
|
||||
DWORD rem;
|
||||
|
||||
handle = (dhandle_t *) dhandle;
|
||||
@@ -168,9 +167,14 @@ csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_handle_t *dhandle) {
|
||||
}
|
||||
file_stat->name = c_utf8_from_locale(handle->ffd.cFileName);
|
||||
|
||||
file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
|
||||
if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT
|
||||
&& handle->ffd.dwReserved0 & IO_REPARSE_TAG_SYMLINK) {
|
||||
file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
|
||||
if ( (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
|
||||
&& (handle->ffd.dwReserved0 & IO_REPARSE_TAG_SYMLINK)
|
||||
// The SIS or DEDUP flag points to a MS deduplication feature of
|
||||
// certain file storage products. It is not a normal symlink
|
||||
// that should be ignored.
|
||||
&& (! (handle->ffd.dwReserved0 & IO_REPARSE_TAG_SIS))
|
||||
&& (! (handle->ffd.dwReserved0 & IO_REPARSE_TAG_DEDUP)) ) {
|
||||
file_stat->flags = CSYNC_VIO_FILE_FLAGS_SYMLINK;
|
||||
file_stat->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK;
|
||||
} else if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE
|
||||
@@ -226,8 +230,10 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
ULARGE_INTEGER FileIndex;
|
||||
mbchar_t *wuri = c_utf8_path_to_locale( uri );
|
||||
|
||||
h = CreateFileW( wuri, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL+FILE_FLAG_BACKUP_SEMANTICS+FILE_FLAG_OPEN_REPARSE_POINT, NULL );
|
||||
h = CreateFileW( wuri, 0, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
|
||||
NULL );
|
||||
if( h == INVALID_HANDLE_VALUE ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_CRIT, "CreateFileW failed on %s", uri );
|
||||
errno = GetLastError();
|
||||
|
||||
@@ -53,7 +53,3 @@ add_cmocka_test(check_csync_update csync_tests/check_csync_update.c ${TEST_TARGE
|
||||
# encoding
|
||||
add_cmocka_test(check_encoding_functions encoding_tests/check_encoding.c ${TEST_TARGET_LIBRARIES})
|
||||
|
||||
if(UNIT_TESTING)
|
||||
INSTALL( FILES "${CMOCKA_LIBRARIES}" DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif(UNIT_TESTING)
|
||||
|
||||
|
||||
@@ -33,8 +33,7 @@ static void setup(void **state) {
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
|
||||
*state = csync;
|
||||
}
|
||||
@@ -49,10 +48,9 @@ static void setup_module(void **state) {
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "dummy://foo/bar");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/check_csync1", "dummy://foo/bar");
|
||||
|
||||
rc = csync_init(csync);
|
||||
csync_init(csync);
|
||||
*state = csync;
|
||||
}
|
||||
|
||||
@@ -74,16 +72,6 @@ static void teardown(void **state) {
|
||||
*state = NULL;
|
||||
}
|
||||
|
||||
static void check_csync_commit_null(void **state)
|
||||
{
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = csync_commit(NULL);
|
||||
assert_int_equal(rc, -1);
|
||||
}
|
||||
|
||||
static void check_csync_commit(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
@@ -110,7 +98,6 @@ static void check_csync_commit_dummy(void **state)
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
unit_test_setup_teardown(check_csync_commit_null, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_commit, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_commit_dummy, setup_module, teardown),
|
||||
};
|
||||
|
||||
@@ -42,8 +42,7 @@ static void check_csync_create(void **state)
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = csync_create(&csync, "/tmp/csync1", "/tmp/csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/csync1", "/tmp/csync2");
|
||||
|
||||
rc = csync_destroy(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
@@ -32,8 +32,7 @@ static void setup(void **state) {
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
|
||||
*state = csync;
|
||||
}
|
||||
@@ -42,8 +41,7 @@ static void setup_init(void **state) {
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
|
||||
rc = csync_exclude_load(EXCLUDE_LIST_FILE, &(csync->excludes));
|
||||
assert_int_equal(rc, 0);
|
||||
@@ -102,84 +100,84 @@ static void check_csync_excluded(void **state)
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
|
||||
rc = csync_excluded(csync, "", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
rc = csync_excluded(csync, "/", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "/", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
|
||||
rc = csync_excluded(csync, "krawel_krawel", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "krawel_krawel", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
rc = csync_excluded(csync, ".kde/share/config/kwin.eventsrc", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, ".kde/share/config/kwin.eventsrc", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
rc = csync_excluded(csync, ".htaccess/cache-maximegalon/cache1.txt", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, ".htaccess/cache-maximegalon/cache1.txt", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
rc = csync_excluded(csync, "mozilla/.htaccess", CSYNC_FTW_TYPE_DIR);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "mozilla/.htaccess", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
/*
|
||||
* Test for patterns in subdirs. '.beagle' is defined as a pattern and has
|
||||
* to be found in top dir as well as in directories underneath.
|
||||
*/
|
||||
rc = csync_excluded(csync, ".apdisk", CSYNC_FTW_TYPE_DIR);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, ".apdisk", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
rc = csync_excluded(csync, "foo/.apdisk", CSYNC_FTW_TYPE_DIR);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "foo/.apdisk", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
rc = csync_excluded(csync, "foo/bar/.apdisk", CSYNC_FTW_TYPE_DIR);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "foo/bar/.apdisk", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded(csync, ".java", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, ".java", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
|
||||
/* Files in the ignored dir .java will also be ignored. */
|
||||
rc = csync_excluded(csync, ".apdisk/totally_amazing.jar", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, ".apdisk/totally_amazing.jar", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
/* and also in subdirs */
|
||||
rc = csync_excluded(csync, "projects/.apdisk/totally_amazing.jar", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "projects/.apdisk/totally_amazing.jar", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
/* csync-journal is ignored in general silently. */
|
||||
rc = csync_excluded(csync, ".csync_journal.db", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, ".csync_journal.db", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
|
||||
rc = csync_excluded(csync, ".csync_journal.db.ctmp", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, ".csync_journal.db.ctmp", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
|
||||
rc = csync_excluded(csync, "subdir/.csync_journal.db", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "subdir/.csync_journal.db", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
|
||||
|
||||
/* pattern ]*.directory - ignore and remove */
|
||||
rc = csync_excluded(csync, "my.~directory", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "my.~directory", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_AND_REMOVE);
|
||||
|
||||
rc = csync_excluded(csync, "/a_folder/my.~directory", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "/a_folder/my.~directory", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_AND_REMOVE);
|
||||
|
||||
/* Not excluded because the pattern .netscape/cache requires directory. */
|
||||
rc = csync_excluded(csync, ".netscape/cache", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, ".netscape/cache", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
|
||||
/* Not excluded */
|
||||
rc = csync_excluded(csync, "unicode/中文.hé", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "unicode/中文.hé", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
/* excluded */
|
||||
rc = csync_excluded(csync, "unicode/пятницы.txt", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "unicode/пятницы.txt", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
rc = csync_excluded(csync, "unicode/中文.💩", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "unicode/中文.💩", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
/* path wildcards */
|
||||
rc = csync_excluded(csync, "foobar/my_manuscript.out", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "foobar/my_manuscript.out", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded(csync, "latex_tmp/my_manuscript.run.xml", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "latex_tmp/my_manuscript.run.xml", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded(csync, "word_tmp/my_manuscript.run.xml", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "word_tmp/my_manuscript.run.xml", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
|
||||
rc = csync_excluded(csync, "latex/my_manuscript.tex.tmp", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "latex/my_manuscript.tex.tmp", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
|
||||
rc = csync_excluded(csync, "latex/songbook/my_manuscript.tex.tmp", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "latex/songbook/my_manuscript.tex.tmp", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
}
|
||||
|
||||
@@ -241,45 +239,45 @@ static void check_csync_pathes(void **state)
|
||||
_csync_exclude_add( &(csync->excludes), "/exclude" );
|
||||
|
||||
/* Check toplevel dir, the pattern only works for toplevel dir. */
|
||||
rc = csync_excluded(csync, "/exclude", CSYNC_FTW_TYPE_DIR);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "/exclude", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded(csync, "/foo/exclude", CSYNC_FTW_TYPE_DIR);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "/foo/exclude", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
|
||||
/* check for a file called exclude. Must still work */
|
||||
rc = csync_excluded(csync, "/exclude", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "/exclude", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded(csync, "/foo/exclude", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "/foo/exclude", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
|
||||
/* Add an exclude for directories only: excl/ */
|
||||
_csync_exclude_add( &(csync->excludes), "excl/" );
|
||||
rc = csync_excluded(csync, "/excl", CSYNC_FTW_TYPE_DIR);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "/excl", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded(csync, "meep/excl", CSYNC_FTW_TYPE_DIR);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "meep/excl", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded(csync, "meep/excl/file", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "meep/excl/file", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded(csync, "/excl", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "/excl", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
|
||||
_csync_exclude_add(&csync->excludes, "/excludepath/withsubdir");
|
||||
|
||||
rc = csync_excluded(csync, "/excludepath/withsubdir", CSYNC_FTW_TYPE_DIR);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "/excludepath/withsubdir", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded(csync, "/excludepath/withsubdir", CSYNC_FTW_TYPE_FILE);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "/excludepath/withsubdir", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded(csync, "/excludepath/withsubdir2", CSYNC_FTW_TYPE_DIR);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "/excludepath/withsubdir2", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
|
||||
rc = csync_excluded(csync, "/excludepath/withsubdir/foo", CSYNC_FTW_TYPE_DIR);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "/excludepath/withsubdir/foo", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
}
|
||||
|
||||
@@ -314,8 +312,8 @@ static void check_csync_excluded_performance(void **state)
|
||||
gettimeofday(&before, 0);
|
||||
|
||||
for (int i = 0; i < N; ++i) {
|
||||
totalRc += csync_excluded(csync, "/this/is/quite/a/long/path/with/many/components", CSYNC_FTW_TYPE_DIR);
|
||||
totalRc += csync_excluded(csync, "/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/29", CSYNC_FTW_TYPE_FILE);
|
||||
totalRc += csync_excluded_no_ctx(csync->excludes, "/this/is/quite/a/long/path/with/many/components", CSYNC_FTW_TYPE_DIR);
|
||||
totalRc += csync_excluded_no_ctx(csync->excludes, "/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/29", CSYNC_FTW_TYPE_FILE);
|
||||
}
|
||||
assert_int_equal(totalRc, CSYNC_NOT_EXCLUDED); // mainly to avoid optimization
|
||||
|
||||
@@ -346,6 +344,25 @@ static void check_csync_excluded_performance(void **state)
|
||||
}
|
||||
}
|
||||
|
||||
static void check_csync_exclude_expand_escapes(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
const char *str = csync_exclude_expand_escapes(
|
||||
"keep \\' \\\" \\? \\\\ \\a \\b \\f \\n \\r \\t \\v \\z");
|
||||
assert_true(0 == strcmp(
|
||||
str, "keep ' \" ? \\ \a \b \f \n \r \t \v \\z"));
|
||||
SAFE_FREE(str);
|
||||
|
||||
str = csync_exclude_expand_escapes("");
|
||||
assert_true(0 == strcmp(str, ""));
|
||||
SAFE_FREE(str);
|
||||
|
||||
str = csync_exclude_expand_escapes("\\");
|
||||
assert_true(0 == strcmp(str, "\\"));
|
||||
SAFE_FREE(str);
|
||||
}
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
@@ -356,6 +373,7 @@ int torture_run_tests(void)
|
||||
unit_test_setup_teardown(check_csync_pathes, setup_init, teardown),
|
||||
unit_test_setup_teardown(check_csync_is_windows_reserved_word, setup_init, teardown),
|
||||
unit_test_setup_teardown(check_csync_excluded_performance, setup_init, teardown),
|
||||
unit_test(check_csync_exclude_expand_escapes),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
|
||||
@@ -33,8 +33,7 @@ static void setup(void **state) {
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
|
||||
*state = csync;
|
||||
}
|
||||
@@ -49,8 +48,7 @@ static void setup_module(void **state) {
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "dummy://foo/bar");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/check_csync1", "dummy://foo/bar");
|
||||
|
||||
*state = csync;
|
||||
}
|
||||
@@ -73,34 +71,19 @@ static void teardown(void **state) {
|
||||
*state = NULL;
|
||||
}
|
||||
|
||||
static void check_csync_init_null(void **state)
|
||||
{
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = csync_init(NULL);
|
||||
assert_int_equal(rc, -1);
|
||||
}
|
||||
|
||||
static void check_csync_init(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
|
||||
rc = csync_init(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
csync_init(csync);
|
||||
|
||||
assert_int_equal(csync->status & CSYNC_STATUS_INIT, 1);
|
||||
|
||||
rc = csync_init(csync);
|
||||
assert_int_equal(rc, 1);
|
||||
}
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
unit_test_setup_teardown(check_csync_init_null, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_init, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_init, setup_module, teardown),
|
||||
};
|
||||
|
||||
@@ -37,8 +37,7 @@ static void setup(void **state) {
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
|
||||
*state = csync;
|
||||
}
|
||||
|
||||
@@ -37,8 +37,7 @@ static void setup(void **state) {
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
|
||||
csync->statedb.file = c_strdup( TESTDB );
|
||||
*state = csync;
|
||||
|
||||
@@ -42,10 +42,8 @@ static void setup(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = csync_init(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_init(csync);
|
||||
|
||||
sqlite3 *db = NULL;
|
||||
rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
|
||||
|
||||
@@ -93,10 +93,8 @@ static void setup(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = csync_init(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_init(csync);
|
||||
|
||||
/* Create a new db with metadata */
|
||||
sqlite3 *db;
|
||||
@@ -126,10 +124,8 @@ static void setup_ftw(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = csync_create(&csync, "/tmp", "/tmp");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = csync_init(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp", "/tmp");
|
||||
csync_init(csync);
|
||||
|
||||
sqlite3 *db = NULL;
|
||||
rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
|
||||
|
||||
@@ -85,6 +85,16 @@ sub fromFileName($)
|
||||
}
|
||||
}
|
||||
|
||||
sub setCredentials
|
||||
{
|
||||
my ($dav, $user, $passwd) = @_;
|
||||
|
||||
$dav->credentials(-url=> $owncloud, -realm=>"sabre/dav",
|
||||
-user=> $user, -pass=> $passwd);
|
||||
$dav->credentials(-url=> $owncloud, -realm=>"ownCloud",
|
||||
-user=> $user, -pass=> $passwd);
|
||||
}
|
||||
|
||||
|
||||
sub initTesting(;$)
|
||||
{
|
||||
@@ -127,9 +137,7 @@ sub initTesting(;$)
|
||||
my $ua = HTTP::DAV::UserAgent->new(keep_alive => 1 );
|
||||
$d = HTTP::DAV->new(-useragent => $ua);
|
||||
|
||||
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
|
||||
-user=> $user,
|
||||
-pass=> $passwd );
|
||||
setCredentials($d, $user, $passwd);
|
||||
# $d->DebugLevel(3);
|
||||
$prefix = "t1" unless( defined $prefix );
|
||||
|
||||
@@ -193,9 +201,7 @@ sub removeRemoteDir($;$)
|
||||
|
||||
my $url = testDirUrl() . $dir;
|
||||
if( $optionsRef && $optionsRef->{user} && $optionsRef->{passwd} ) {
|
||||
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
|
||||
-user=> $optionsRef->{user},
|
||||
-pass=> $optionsRef->{passwd} );
|
||||
setCredentials($d, $optionsRef->{user}, $optionsRef->{passwd});
|
||||
if( $optionsRef->{url} ) {
|
||||
$url = $optionsRef->{url} . $dir;
|
||||
}
|
||||
@@ -219,9 +225,7 @@ sub createRemoteDir(;$$)
|
||||
my $url = testDirUrl() . $dir;
|
||||
|
||||
if( $optionsRef && $optionsRef->{user} && $optionsRef->{passwd} ) {
|
||||
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
|
||||
-user=> $optionsRef->{user},
|
||||
-pass=> $optionsRef->{passwd} );
|
||||
setCredentials($d, $optionsRef->{user}, $optionsRef->{passwd});
|
||||
if( $optionsRef->{url} ) {
|
||||
$url = $optionsRef->{url} . $dir;
|
||||
}
|
||||
@@ -396,9 +400,7 @@ sub traverse( $$;$ )
|
||||
my %seen;
|
||||
|
||||
|
||||
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
|
||||
-user=> $user,
|
||||
-pass=> $passwd );
|
||||
setCredentials($d, $user, $passwd);
|
||||
$d->open( $owncloud );
|
||||
|
||||
if( my $r = $d->propfind( -url => $url, -depth => 1 ) ) {
|
||||
@@ -513,9 +515,7 @@ sub put_to_dir( $$;$ )
|
||||
my $targetUrl = testDirUrl();
|
||||
|
||||
if( $optionsRef && $optionsRef->{user} && $optionsRef->{passwd} ) {
|
||||
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
|
||||
-user=> $optionsRef->{user},
|
||||
-pass=> $optionsRef->{passwd} );
|
||||
setCredentials($d, $optionsRef->{user}, $optionsRef->{passwd});
|
||||
if( $optionsRef->{url} ) {
|
||||
$targetUrl = $optionsRef->{url};
|
||||
}
|
||||
@@ -649,9 +649,7 @@ sub moveRemoteFile($$;$)
|
||||
{
|
||||
my ($from, $to, $no_testdir) = @_;
|
||||
|
||||
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
|
||||
-user=> $user,
|
||||
-pass=> $passwd );
|
||||
setCredentials($d, $user, $passwd);
|
||||
|
||||
my $fromUrl = testDirUrl(). $from;
|
||||
my $toUrl = testDirUrl() . $to;
|
||||
@@ -725,9 +723,7 @@ sub createShare($$)
|
||||
|
||||
my $dd = HTTP::DAV->new();
|
||||
|
||||
$dd->credentials( -url=> $owncloud, -realm=>"ownCloud",
|
||||
-user=> $share_user,
|
||||
-pass=> $share_passwd );
|
||||
setCredentials($dd, $share_user, $share_passwd);
|
||||
$dd->open( $owncloud);
|
||||
|
||||
# create a remote dir
|
||||
@@ -769,9 +765,7 @@ sub removeShare($$)
|
||||
|
||||
my $dd = HTTP::DAV->new();
|
||||
|
||||
$dd->credentials( -url => $owncloud, -realm=>"ownCloud",
|
||||
-user => $share_user,
|
||||
-pass => $share_passwd );
|
||||
setCredentials($dd, $share_user, $share_passwd);
|
||||
$dd->open( $owncloud);
|
||||
|
||||
my $ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 0 });
|
||||
|
||||
@@ -146,9 +146,9 @@ assertLocalAndRemoteDir( '', 0);
|
||||
|
||||
# create a true conflict.
|
||||
printInfo( "Create a conflict." );
|
||||
system( "echo \"This is more stuff\" >> /tmp/kernelcrash.txt" );
|
||||
system( "echo \"This is more server stuff\" >> /tmp/kernelcrash.txt" );
|
||||
put_to_dir( '/tmp/kernelcrash.txt', 'remoteToLocal1' );
|
||||
system( "sleep 2 && touch " . localDir() . "remoteToLocal1/kernelcrash.txt" );
|
||||
system( "sleep 2 && echo \"This is more client stuff\" >> " . localDir() . "remoteToLocal1/kernelcrash.txt" );
|
||||
csync();
|
||||
assertLocalAndRemoteDir( '', 1);
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ assert($emlpropafter->get_property( "getlastmodified" ) eq
|
||||
$emlpropbefore->get_property( "getlastmodified" ));
|
||||
|
||||
printInfo( "Change content of eml file (but not size)");
|
||||
system( "sed -i -e 's/in/IN/' $locDir/test.eml" );
|
||||
system( "sleep 1 && sed -i -e 's/in/IN/' $locDir/test.eml" );
|
||||
|
||||
csync( );
|
||||
|
||||
|
||||
@@ -84,10 +84,8 @@ static void destructor(void *data) {
|
||||
|
||||
static void setup(void **state) {
|
||||
c_rbtree_t *tree = NULL;
|
||||
int rc;
|
||||
|
||||
rc = c_rbtree_create(&tree, key_cmp, data_cmp);
|
||||
assert_int_equal(rc, 0);
|
||||
c_rbtree_create(&tree, key_cmp, data_cmp);
|
||||
|
||||
*state = tree;
|
||||
}
|
||||
@@ -97,8 +95,7 @@ static void setup_complete_tree(void **state) {
|
||||
int i = 0;
|
||||
int rc;
|
||||
|
||||
rc = c_rbtree_create(&tree, key_cmp, data_cmp);
|
||||
assert_int_equal(rc, 0);
|
||||
c_rbtree_create(&tree, key_cmp, data_cmp);
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
test_t *testdata = NULL;
|
||||
@@ -131,31 +128,13 @@ static void check_c_rbtree_create_free(void **state)
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = c_rbtree_create(&tree, key_cmp, data_cmp);
|
||||
assert_int_equal(rc, 0);
|
||||
c_rbtree_create(&tree, key_cmp, data_cmp);
|
||||
assert_int_equal(tree->size, 0);
|
||||
|
||||
rc = c_rbtree_free(tree);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void check_c_rbtree_create_null(void **state)
|
||||
{
|
||||
c_rbtree_t *tree = NULL;
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = c_rbtree_create(NULL, key_cmp, data_cmp);
|
||||
assert_int_equal(rc, -1);
|
||||
|
||||
rc = c_rbtree_create(&tree, NULL, data_cmp);
|
||||
assert_int_equal(rc, -1);
|
||||
|
||||
rc = c_rbtree_create(&tree, key_cmp, NULL);
|
||||
assert_int_equal(rc, -1);
|
||||
}
|
||||
|
||||
static void check_c_rbtree_free_null(void **state)
|
||||
{
|
||||
int rc;
|
||||
@@ -175,8 +154,7 @@ static void check_c_rbtree_insert_delete(void **state)
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = c_rbtree_create(&tree, key_cmp, data_cmp);
|
||||
assert_int_equal(rc, 0);
|
||||
c_rbtree_create(&tree, key_cmp, data_cmp);
|
||||
|
||||
testdata = malloc(sizeof(test_t));
|
||||
testdata->key = 42;
|
||||
@@ -369,7 +347,6 @@ int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
unit_test(check_c_rbtree_create_free),
|
||||
unit_test(check_c_rbtree_create_null),
|
||||
unit_test(check_c_rbtree_free_null),
|
||||
unit_test(check_c_rbtree_insert_delete),
|
||||
unit_test_setup_teardown(check_c_rbtree_insert_random, setup, teardown),
|
||||
|
||||
@@ -49,8 +49,7 @@ static void setup(void **state)
|
||||
rc = system("rm -rf /tmp/csync_test");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = csync_create(&csync, "/tmp/csync1", "/tmp/csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/csync1", "/tmp/csync2");
|
||||
|
||||
csync->replica = LOCAL_REPLICA;
|
||||
|
||||
|
||||
@@ -97,8 +97,7 @@ static void setup_testenv(void **state) {
|
||||
statevar *mystate = malloc( sizeof(statevar) );
|
||||
mystate->result = NULL;
|
||||
|
||||
rc = csync_create(&(mystate->csync), "/tmp/csync1", "/tmp/csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&(mystate->csync), "/tmp/csync1", "/tmp/csync2");
|
||||
|
||||
mystate->csync->replica = LOCAL_REPLICA;
|
||||
|
||||
|
||||
@@ -18,3 +18,8 @@ ownCloud Command Line Client
|
||||
----------------------------
|
||||
.. index:: owncloudcmd
|
||||
.. include:: owncloudcmd.rst
|
||||
|
||||
Low Disk Space
|
||||
--------------
|
||||
.. index:: disk space
|
||||
.. include:: lowdiskspace.rst
|
||||
|
||||
@@ -87,7 +87,7 @@ To manually override this key, use the same value in ``HKEY_CURRENT_USER``.
|
||||
|
||||
To prevent automatic updates and disallow manual overrides:
|
||||
|
||||
.. note::This is the preferred method of controlling the updater behavior using
|
||||
.. note:: This is the preferred method of controlling the updater behavior using
|
||||
Group Policies.
|
||||
|
||||
1. Edit this Registry key:
|
||||
@@ -98,6 +98,14 @@ To prevent automatic updates and disallow manual overrides:
|
||||
|
||||
3. Specify a value of ``1`` to the machine.
|
||||
|
||||
.. note:: Enterprise branded clients
|
||||
(see `Building Branded ownCloud Clients
|
||||
<https://doc.owncloud.org/branded_clients/>`_) have different key names,
|
||||
which are set in ownBrander using the Application Vendor and Application
|
||||
Name fields. Your key names look like this::
|
||||
|
||||
``HKEY_LOCAL_MACHINE\Software\Policies\myCompanyName\myAppName``
|
||||
|
||||
|
||||
Preventing Automatic Updates in Mac OS X Environments
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -11,25 +11,44 @@ desktop client.
|
||||
.. note:: Build instructions are subject to change as development proceeds.
|
||||
Please check the version for which you want to build.
|
||||
|
||||
The instructions contained in this topic were updated to work with version 1.7 of the ownCloud Client.
|
||||
These instructions are updated to work with version 2.2 of the ownCloud Client.
|
||||
|
||||
Getting Source Code
|
||||
-------------------
|
||||
|
||||
The :ref:`generic-build-instructions` pull the latest code directly from
|
||||
GitHub, and work on Linux, Mac OS X, and Windows.
|
||||
|
||||
See the next section for instructions on getting source code from Linux
|
||||
packages.
|
||||
|
||||
Linux
|
||||
-----
|
||||
|
||||
1. Add the `ownCloud repository from OBS`_.
|
||||
2. Install the dependencies (as root, or using ``sudo``) using the following
|
||||
commands for your specific Linux distribution:
|
||||
You may wish to use source packages for your Linux distribution, as these give
|
||||
you the exact sources from which the binary packages are built. These are
|
||||
hosted on the `ownCloud repository from OBS`_. Go to the `Index of
|
||||
repositories`_ to see all the Linux client repos.
|
||||
|
||||
1. At the `bottom of the page for each distribution
|
||||
<https://software.opensuse.org/download/package?project=isv:ownCloud:desktop&
|
||||
package=owncloud-client>`_ is a "Grab binary packages directly" section.
|
||||
These contain source RPMs for CentOS, RHEL, Fedora, SLES, and openSUSE.
|
||||
|
||||
To get the .deb source packages add the source
|
||||
repo for your Debian or Ubuntu version, like this example for Debian 8
|
||||
(run as root)::
|
||||
|
||||
echo 'deb-src
|
||||
http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/Debian_8.0/ /' >> /etc/apt/sources.list.d/owncloud-client.list
|
||||
|
||||
2. Install the dependencies using the following commands for your specific Linux distribution:
|
||||
|
||||
* Debian/Ubuntu: ``apt-get update; apt-get build-dep owncloud-client``
|
||||
* openSUSE: ``zypper ref; zypper si -d owncloud-client``
|
||||
* Fedora/CentOS: ``yum install yum-utils; yum-builddep owncloud-client``
|
||||
* openSUSE/SLES: ``zypper ref; zypper si -d owncloud-client``
|
||||
* Fedora/CentOS/RHEL: ``yum install yum-utils; yum-builddep owncloud-client``
|
||||
|
||||
3. Follow the :ref:`generic-build-instructions`.
|
||||
|
||||
4. (Optional) Call ``make install`` to install the client to the ``/usr/local/bin`` directory.
|
||||
|
||||
.. note:: This step requires the ``mingw32-cross-nsis`` packages be installed on
|
||||
Windows.
|
||||
3. Follow the :ref:`generic-build-instructions`, starting with step 2.
|
||||
|
||||
Mac OS X
|
||||
--------
|
||||
@@ -63,15 +82,17 @@ To set up your build environment for development using HomeBrew_:
|
||||
|
||||
5. For compilation of the client, follow the :ref:`generic-build-instructions`.
|
||||
|
||||
6. In the build directory, run ``admin/osx/create_mac.sh <build_dir>
|
||||
6. Install the Packages_ package creation tool.
|
||||
|
||||
7. In the build directory, run ``admin/osx/create_mac.sh <build_dir>
|
||||
<install_dir>``. If you have a developer signing certificate, you can specify
|
||||
its Common Name as a third parameter (use quotes) to have the package
|
||||
signed automatically.
|
||||
|
||||
.. note:: Contrary to earlier versions, ownCloud 1.7 and later are packaged
|
||||
as a ``pkg`` installer. Do not call "make package" at any time when
|
||||
compiling for OS X, as this will build a disk image, and will not
|
||||
work correctly.
|
||||
.. note:: Contrary to earlier versions, ownCloud 1.7 and later are packaged
|
||||
as a ``pkg`` installer. Do not call "make package" at any time when
|
||||
compiling for OS X, as this will build a disk image, and will not
|
||||
work correctly.
|
||||
|
||||
Windows Development Build
|
||||
-----------------------
|
||||
@@ -111,64 +132,62 @@ follow `Windows Installer Build (Cross-Compile)`_ instead.
|
||||
|
||||
6. Create the build directory::
|
||||
|
||||
mkdir client-build
|
||||
cd client-build
|
||||
mkdir client-build
|
||||
cd client-build
|
||||
|
||||
7. Build the client::
|
||||
|
||||
cmake -G "MinGW Makefiles" ../client
|
||||
mingw32-make
|
||||
cmake -G "MinGW Makefiles" ../client
|
||||
mingw32-make
|
||||
|
||||
.. note:: You can try using ninja to build in parallel using
|
||||
``cmake -G Ninja ../client`` and ``ninja`` instead.
|
||||
.. note:: Refer to the :ref:`generic-build-instructions` section for additional options.
|
||||
.. note:: You can try using ninja to build in parallel using
|
||||
``cmake -G Ninja ../client`` and ``ninja`` instead.
|
||||
.. note:: Refer to the :ref:`generic-build-instructions` section for additional options.
|
||||
|
||||
The ownCloud binary will appear in the ``bin`` directory.
|
||||
The ownCloud binary will appear in the ``bin`` directory.
|
||||
|
||||
Windows Installer Build (Cross-Compile)
|
||||
---------------------------------------
|
||||
|
||||
Due to the large number of dependencies, building the client installer for Windows
|
||||
is **currently only officially supported on openSUSE**, by using the MinGW cross compiler.
|
||||
You can set up openSUSE 13.1, 13.2 or openSUSE Factory in a virtual machine if you do not
|
||||
You can set up any currently supported version of openSUSE in a virtual machine if you do not
|
||||
have it installed already.
|
||||
|
||||
To cross-compile:
|
||||
In order to make setup simple, you can use the provided Dockerfile to build your own image.
|
||||
|
||||
1. Add the following repository using YaST or ``zypper ar`` (adjust when using another openSUSE version)::
|
||||
1. Assuming you are in the root of the ownCloud Client's source tree, you can
|
||||
build an image from this Dockerfile like this::
|
||||
|
||||
zypper ar https://build.opensuse.org/project/show/isv:ownCloud:toolchains:mingw:win32:stable
|
||||
cd admin/win32/docker
|
||||
docker build . -t ownCloud-client-win32:<version>
|
||||
|
||||
2. Install the cross-compiler packages and the cross-compiled dependencies::
|
||||
Replace ``<version>`` by the version of the client you are building, e.g.
|
||||
|version| for the release of the client that this document describes.
|
||||
If you do not wish to use docker, you can run the commands in ``RUN`` manually
|
||||
in a shell, e.g. to create your own build environment in a virtual machine.
|
||||
|
||||
zypper install cmake make mingw32-cross-binutils mingw32-cross-cpp mingw32-cross-gcc \
|
||||
mingw32-cross-gcc-c++ mingw32-cross-pkg-config mingw32-filesystem \
|
||||
mingw32-headers mingw32-runtime site-config mingw32-libwebp \
|
||||
mingw32-cross-libqt5-qmake mingw32-cross-libqt5-qttools mingw32-libqt5*
|
||||
.. note:: Docker images are specific to releases. This one refers to |version|.
|
||||
Newer releases may have different dependencies, and thus require a later
|
||||
version of the docker image! Always pick the docker image fitting your release
|
||||
of ownCloud client!
|
||||
|
||||
3. For the installer, install the NSIS installer package::
|
||||
2. From within the source tree Run the docker instance::
|
||||
|
||||
zypper install mingw32-cross-nsis mingw32-cross-nsis-plugin-uac mingw32-cross-nsis-plugin-nsprocess
|
||||
docker run ownCloud-client-win32:<version> -v "$PWD:/home/jenkins/client" \
|
||||
admin/win32/docker/build.sh $(id -u)
|
||||
|
||||
4. Follow the :ref:`generic-build-instructions`
|
||||
It will run the build, create an NSIS based installer, as well as run tests.
|
||||
You will find the resulting binary in an newly created ``build-win32`` subfolder.
|
||||
|
||||
.. note:: When building for Windows platforms, you must specify a special
|
||||
toolchain file that enables cmake to locate the platform-specific tools. To add
|
||||
this parameter to the call to cmake, enter
|
||||
``-DCMAKE_TOOLCHAIN_FILE=../client/admin/win/Toolchain-mingw32-openSUSE.cmake``.
|
||||
If you do not wish to use docker, and ran the ``RUN`` commands above in a virtual machine,
|
||||
you can run the indented commands in the lower section of ``build.sh`` manually in your
|
||||
source tree.
|
||||
|
||||
5. Build by running ``make``.
|
||||
4. Finally, you should sign the installer to avoid warnings upon installation.
|
||||
This requires a `Microsoft Authenticode`_ Certificate ``osslsigncode`` to sign the installer::
|
||||
|
||||
.. note:: Using ``make package`` produces an NSIS-based installer, provided
|
||||
the NSIS mingw32 packages are installed.
|
||||
|
||||
6. If you want to sign the installer, acquire a `Microsoft Authenticode`_ Certificate and install ``osslsigncode`` to sign the installer::
|
||||
|
||||
zypper install osslsigncode
|
||||
|
||||
7. Sign the package::
|
||||
|
||||
osslsigncode -pkcs12 $HOME/.codesign/packages.pfx -h sha1 \
|
||||
osslsigncode -pkcs12 $HOME/.codesign/packages.pfx -h sha256 \
|
||||
-pass yourpass \
|
||||
-n "ACME Client" \
|
||||
-i "http://acme.com" \
|
||||
@@ -179,6 +198,7 @@ To cross-compile:
|
||||
for ``-in``, use the URL to the time stamping server provided by your CA along with the Authenticode certificate. Alternatively,
|
||||
you may use the official Microsoft ``signtool`` utility on Microsoft Windows.
|
||||
|
||||
If you're familiar with docker, you can use the version of ``osslsigncode`` that is part of the docker image.
|
||||
|
||||
.. _generic-build-instructions:
|
||||
|
||||
@@ -189,35 +209,37 @@ Compared to previous versions, building the desktop sync client has become easie
|
||||
earlier versions, CSync, which is the sync engine library of the client, is now
|
||||
part of the client source repository and not a separate module.
|
||||
|
||||
You can download the desktop sync client from the ownCloud `Client Download Page`_.
|
||||
To build the most up-to-date version of the client:
|
||||
|
||||
To build the most up to date version of the client:
|
||||
1. Clone the latest versions of the client from Git_ as follows::
|
||||
|
||||
1. Clone the latest versions of the client from Git_ as follows:
|
||||
git clone git://github.com/owncloud/client.git
|
||||
cd client
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
``git clone git://github.com/owncloud/client.git``
|
||||
``git submodule init``
|
||||
``git submodule update``
|
||||
2. Create the build directory::
|
||||
|
||||
2. Create the build directory:
|
||||
mkdir client-build
|
||||
cd client-build
|
||||
|
||||
``mkdir client-build``
|
||||
``cd client-build``
|
||||
3. Configure the client build::
|
||||
|
||||
3. Configure the client build:
|
||||
cmake -DCMAKE_BUILD_TYPE="Debug" ..
|
||||
|
||||
``cmake -DCMAKE_BUILD_TYPE="Debug" ../client``
|
||||
.. note:: You must use absolute paths for the ``include`` and ``library``
|
||||
directories.
|
||||
|
||||
..note:: You must use absolute paths for the ``include`` and ``library``
|
||||
directories.
|
||||
|
||||
..note:: On Mac OS X, you need to specify ``-DCMAKE_INSTALL_PREFIX=target``,
|
||||
where ``target`` is a private location, i.e. in parallel to your build
|
||||
dir by specifying ``../install``.
|
||||
.. note:: On Mac OS X, you need to specify ``-DCMAKE_INSTALL_PREFIX=target``,
|
||||
where ``target`` is a private location, i.e. in parallel to your build
|
||||
dir by specifying ``../install``.
|
||||
|
||||
4. Call ``make``.
|
||||
|
||||
The owncloud binary will appear in the ``bin`` directory.
|
||||
The owncloud binary will appear in the ``bin`` directory.
|
||||
|
||||
5. (Optional) Call ``make install`` to install the client to the
|
||||
``/usr/local/bin`` directory.
|
||||
|
||||
The following are known cmake parameters:
|
||||
|
||||
@@ -230,14 +252,17 @@ The following are known cmake parameters:
|
||||
* ``BUILD_WITH_QT4=ON``: Builds using Qt4 (even if Qt5 is found).
|
||||
* ``CMAKE_INSTALL_PREFIX=path``: Set an install prefix. This is mandatory on Mac OS
|
||||
|
||||
.. _`ownCloud repository from OBS`: http://software.opensuse.org/download/package?project=isv:ownCloud:desktop&package=owncloud-client
|
||||
.. _ownCloud repository from OBS: http://software.opensuse.org/download/package?
|
||||
project=isv:ownCloud:desktop&package=owncloud-client
|
||||
.. _CMake: http://www.cmake.org/download
|
||||
.. _CSync: http://www.csync.org
|
||||
.. _`Client Download Page`: http://owncloud.org/sync-clients/
|
||||
.. _Client Download Page: https://owncloud.org/install/#desktop
|
||||
.. _Git: http://git-scm.com
|
||||
.. _MacPorts: http://www.macports.org
|
||||
.. _Homebrew: http://mxcl.github.com/homebrew/
|
||||
.. _`OpenSSL Windows Build`: http://slproweb.com/products/Win32OpenSSL.html
|
||||
.. _OpenSSL Windows Build: http://slproweb.com/products/Win32OpenSSL.html
|
||||
.. _Qt: http://www.qt.io/download
|
||||
.. _`Microsoft Authenticode`: https://msdn.microsoft.com/en-us/library/ie/ms537361%28v=vs.85%29.aspx
|
||||
.. _Microsoft Authenticode: https://msdn.microsoft.com/en-us/library/ie/ms537361%28v=vs.85%29.aspx
|
||||
.. _QtKeychain: https://github.com/frankosterfeld/qtkeychain
|
||||
.. _Packages: http://s.sudre.free.fr/Software/Packages/about.html
|
||||
.. _Index of repositories: http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/
|
||||
|
||||
@@ -288,3 +288,5 @@ epub_copyright = u'2013, The ownCloud developers'
|
||||
|
||||
# Include todos?
|
||||
todo_include_todos = True
|
||||
|
||||
rst_epilog = '.. |version| replace:: %s' % version
|
||||
|
||||
@@ -22,3 +22,9 @@ You can change the following configuration settings (must be under the ``[ownClo
|
||||
|
||||
- ``maxLogLines`` (default: ``20000``) -- Specifies the maximum number of log lines displayed in the log window.
|
||||
|
||||
- ``chunkSize`` (default: ``5242880``) -- Specifies the chunk size of uploaded files in bytes.
|
||||
|
||||
- ``promptDeleteAllFiles`` (default: ``true``) -- If a UI prompt should ask for confirmation if it was detected that all files and folders were deleted.
|
||||
|
||||
- ``notificationRefreshInterval`` (default``300,000``) -- Specifies the default interval of checking for new server notifications in milliseconds.
|
||||
|
||||
|
||||
|
Antes Largura: | Altura: | Tamanho: 82 KiB Depois Largura: | Altura: | Tamanho: 72 KiB |
|
Antes Largura: | Altura: | Tamanho: 52 KiB Depois Largura: | Altura: | Tamanho: 86 KiB |
|
Antes Largura: | Altura: | Tamanho: 99 KiB Depois Largura: | Altura: | Tamanho: 23 KiB |
@@ -22,8 +22,16 @@ Improvements and New Features
|
||||
The 2.1 release of the ownCloud desktop sync client has many new features and
|
||||
improvements. (See the `complete changelog
|
||||
<https://owncloud.org/changelog/desktop/>`_.)
|
||||
|
||||
|
||||
* Improved appearance on HiDPI screens
|
||||
* Improved error messages
|
||||
* Several fixes/improvements to the sharing dialog
|
||||
* Several fixes/improvements to the server activity tab
|
||||
* Allow changeable upload chunk size in owncloud.cfg
|
||||
* Forget password on explicit sign-out
|
||||
* Windows: Fix deleting and replacing of read-only files
|
||||
* Share with internal ownCloud users from your desktop
|
||||
* Separate views for server activity, sync activity, and errors
|
||||
* Don't re-upload *eml-files if size and checksum are unchanged
|
||||
* Improved upload/download progress indicator
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
When disk space is low the ownCloud Client will be unable to synchronize all files. This section describes its behavior in a low disk space situation as well as the options that influence it.
|
||||
|
||||
1. Synchronization of a folder aborts entirely if the remaining disk space falls below 50 MB. This threshold can be adjusted with the ``OWNCLOUD_CRITICAL_FREE_SPACE_BYTES`` environment variable.
|
||||
|
||||
2. Downloads that would reduce the free disk space below 250 MB will be skipped or aborted. The download will be retried regularly and other synchronization is unaffected. This threshold can be adjusted with the ``OWNCLOUD_FREE_SPACE_BYTES`` environment variable.
|
||||
@@ -11,7 +11,7 @@ in the system tray (Windows, KDE), status bar (Mac OS X), or notification area
|
||||
.. figure:: images/icon.png
|
||||
:alt: Status icon, little cloud with green circle and white checkmark
|
||||
|
||||
The status indicator uses overlay icons to indicate the current status of your
|
||||
The status indicator uses icons to indicate the current status of your
|
||||
synchronization. The green circle with the white checkmark tells you that your
|
||||
synchronization is current and you are connected to your ownCloud server.
|
||||
|
||||
@@ -24,7 +24,7 @@ The blue icon with the white semi-circles means synchronization is in progress.
|
||||
:alt: Status icon, little cloud with yellow circle and vertical parallel
|
||||
lines
|
||||
|
||||
The yellow overlay icon with the parallel lines tells you your synchronization
|
||||
The yellow icon with the parallel lines tells you your synchronization
|
||||
has been paused. (Most likely by you.)
|
||||
|
||||
.. figure:: images/icon-offline.png
|
||||
@@ -58,11 +58,12 @@ operations.
|
||||
This menu provides the following options:
|
||||
|
||||
* Quick access to your accounts
|
||||
* Sync status
|
||||
* Recent Changes, showing latest activities
|
||||
* Status of your client version (whether it is up to date)
|
||||
* Settings
|
||||
* Help menu
|
||||
* An option to log in or log out of all of your accounts at once
|
||||
* Quit ownCloud
|
||||
* Quit ownCloud, logging out and closing the client
|
||||
|
||||
A left-click on your systray icon opens the desktop client to the account
|
||||
settings window.
|
||||
@@ -82,7 +83,7 @@ have the following features:
|
||||
* Connection status, showing which ownCloud server you are connected to, and
|
||||
your ownCloud username.
|
||||
* An **Account** button, which contains a dropdown menu with **Add New**,
|
||||
**Sign In/Sign Out**, and **Remove**.
|
||||
**Log In/Log Out**, and **Remove**.
|
||||
* Used and available space on the server.
|
||||
* Current synchronization status.
|
||||
* **Add Folder Sync Connection** button, which is active only when you have
|
||||
@@ -124,12 +125,47 @@ button, and re-select the folder tree that you want to sync.
|
||||
Adding New Accounts
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
You may configure multiple ownCloud accounts in your desktop sync client. Simply
|
||||
You may configure multiple ownCloud accounts in your desktop sync client.
|
||||
Simply
|
||||
click the **Account** > **Add New** button on any account tab to add a new
|
||||
account, and then follow the account creation wizard. The new account will
|
||||
appear as a new tab in the settings dialog, where you can adjust its settings at
|
||||
appear as a new tab in the settings dialog, where you can adjust its settings
|
||||
at
|
||||
any time. Use **Account** > **Remove** to delete accounts.
|
||||
|
||||
File Manager Overlay Icons
|
||||
--------------------------
|
||||
|
||||
The ownCloud sync client provides overlay icons, in addition to the normal file
|
||||
type icons, for your system file manager (Explorer on Windows, Finder on Mac and
|
||||
Nautilus on Linux) to indicate the sync status of your ownCloud files.
|
||||
|
||||
The overlay icons are similar to the systray icons introduced above. They
|
||||
behave differently on files and directories according to sync status
|
||||
and errors.
|
||||
|
||||
The overlay icon of an individual file indicates its current sync state. If the
|
||||
file is in sync with the server version, it displays a green checkmark.
|
||||
|
||||
If the file is ignored from syncing, for example because it is on your
|
||||
exclude list, or because it is a symbolic link, it displays a warning icon.
|
||||
|
||||
If there is a sync error, or the file is blacklisted, it displays an
|
||||
eye-catching red X.
|
||||
|
||||
If the file is waiting to be synced, or is currently syncing, the overlay
|
||||
icon displays a blue cycling icon.
|
||||
|
||||
When the client is offline, no icons are shown to reflect that the
|
||||
folder is currently out of sync and no changes are synced to the server.
|
||||
|
||||
The overlay icon of a synced directory indicates the status of the files in the
|
||||
directory. If there are any sync errors, the directory is marked with a warning
|
||||
icon.
|
||||
|
||||
If a directory includes ignored files that are marked with warning icons
|
||||
that does not change the status of the parent directories.
|
||||
|
||||
Sharing From Your Desktop
|
||||
-------------------------
|
||||
|
||||
@@ -206,10 +242,12 @@ can use the *Ignored Files Editor* (General tab.)
|
||||
|
||||
.. figure:: images/ignored_files_editor.png
|
||||
|
||||
For your convenience, the editor is pre-populated with a default list of typical
|
||||
For your convenience, the editor is pre-populated with a default list of
|
||||
typical
|
||||
ignore patterns. These patterns are contained in a system file (typically
|
||||
``sync-exclude.lst``) located in the ownCloud Client application directory. You
|
||||
cannot modify these pre-populated patterns directly from the editor. However, if
|
||||
cannot modify these pre-populated patterns directly from the editor. However,
|
||||
if
|
||||
necessary, you can hover over any pattern in the list to show the path and
|
||||
filename associated with that pattern, locate the file, and edit the
|
||||
``sync-exclude.lst`` file.
|
||||
|
||||
@@ -49,7 +49,7 @@ Other command line switches supported by ``owncloudcmd`` include the following:
|
||||
Exclude list file
|
||||
|
||||
``--unsyncedfolders [file]``
|
||||
File containing the list of unsynced folders (selective sync)
|
||||
File containing the list of unsynced remote folders (selective sync)
|
||||
|
||||
``--max-sync-retries [n]``
|
||||
Retries maximum n times (defaults to 3)
|
||||
|
||||
@@ -78,7 +78,7 @@ Other issues can affect synchronization of your ownCloud files:
|
||||
- If you are operating your own server, and use the local storage backend (the
|
||||
default), make sure that ownCloud has exclusive access to the directory.
|
||||
|
||||
.. note:: The data directory on the server is exclusive to ownCloud and must not be modified manually.
|
||||
.. warning:: The data directory on the server is exclusive to ownCloud and must not be modified manually.
|
||||
|
||||
- If you are using a different file backend on the server, you can try to exclude a bug in the
|
||||
backend by reverting to the built-in backend.
|
||||
|
||||
@@ -8,3 +8,14 @@ GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
|
||||
|
||||
# Translations
|
||||
Comment[sq]=Klient njëkohësimesh @APPLICATION_NAME@ për desktop
|
||||
GenericName[sq]=Njëkohësim Dosjesh
|
||||
Name[sq]=Klient njëkohësimesh @APPLICATION_NAME@ për desktop
|
||||
Icon[sq]=@APPLICATION_EXECUTABLE@
|
||||
Comment[nl]=@APPLICATION_NAME@ desktop synchronisatie client
|
||||
GenericName[nl]=Mappen sync
|
||||
Name[nl]=@APPLICATION_NAME@ desktop sync client
|
||||
Icon[nl]=@APPLICATION_EXECUTABLE@
|
||||
|
||||
|
Depois Largura: | Altura: | Tamanho: 900 B |
@@ -7,6 +7,9 @@ add_custom_target( legacy_mac_overlayplugin ALL
|
||||
OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}
|
||||
COMMENT building Legacy Mac Overlay icons)
|
||||
|
||||
# Contrary to popular belief, this is called like this no matter what theme/OEM.
|
||||
set(OC_OEM_SHARE_ICNS "${CMAKE_BINARY_DIR}/src/gui/ownCloud.icns")
|
||||
|
||||
# The bundle identifier and application group need to have compatible values with the client
|
||||
# to be able to open a Mach port across the extension's sandbox boundary.
|
||||
# Pass the info through the xcodebuild command line and make sure that the project uses
|
||||
@@ -14,15 +17,21 @@ add_custom_target( legacy_mac_overlayplugin ALL
|
||||
add_custom_target( mac_overlayplugin ALL
|
||||
xcodebuild -project ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj
|
||||
-target FinderSyncExt -configuration Release SYMROOT=${CMAKE_CURRENT_BINARY_DIR}
|
||||
OC_APPLICATION_NAME=${APPLICATION_NAME}
|
||||
OC_OEM_SHARE_ICNS=${OC_OEM_SHARE_ICNS}
|
||||
OC_APPLICATION_NAME="${APPLICATION_NAME}"
|
||||
OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}
|
||||
OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}
|
||||
COMMENT building Mac Overlay icons)
|
||||
add_dependencies(mac_overlayplugin ${APPLICATION_EXECUTABLE}) # for the ownCloud.icns to be generated
|
||||
|
||||
|
||||
# legacy
|
||||
INSTALL( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/SyncStateFinder.osax/Contents
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/Library/ScriptingAdditions/SyncStateFinder.osax/ )
|
||||
|
||||
# >= 10.10.x
|
||||
INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/FinderSyncExt.appex
|
||||
DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/Plugins
|
||||
DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns
|
||||
USE_SOURCE_PERMISSIONS)
|
||||
endif(APPLE)
|
||||
|
||||
|
||||
@@ -103,7 +103,8 @@
|
||||
|
||||
if (_shareMenuTitle && !onlyRootsSelected) {
|
||||
NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
|
||||
[menu addItemWithTitle:_shareMenuTitle action:@selector(shareMenuAction:) keyEquivalent:@"title"];
|
||||
NSMenuItem *item = [menu addItemWithTitle:_shareMenuTitle action:@selector(shareMenuAction:) keyEquivalent:@"title"];
|
||||
item.image = [[NSBundle mainBundle] imageForResource:@"app.icns"];
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
@@ -178,6 +178,7 @@
|
||||
C2B573D31B1CD9CE00303B36 /* Sources */,
|
||||
C2B573D41B1CD9CE00303B36 /* Frameworks */,
|
||||
C2B573D51B1CD9CE00303B36 /* Resources */,
|
||||
5B3335471CA058E200E11A45 /* ShellScript */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -253,6 +254,23 @@
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
5B3335471CA058E200E11A45 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "if [[ ${OC_OEM_SHARE_ICNS} ]]; then\n cp ${OC_OEM_SHARE_ICNS} ${BUILT_PRODUCTS_DIR}/FinderSyncExt.appex/Contents/Resources/app.icns\nfi";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
C2B573AD1B1CD91E00303B36 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
@@ -429,6 +447,7 @@
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
OC_APPLICATION_NAME = ownCloud;
|
||||
OC_APPLICATION_REV_DOMAIN = com.owncloud.desktopclient;
|
||||
OC_OEM_SHARE_ICNS = "";
|
||||
OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX = "";
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -476,6 +495,7 @@
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
OC_APPLICATION_NAME = ownCloud;
|
||||
OC_APPLICATION_REV_DOMAIN = com.owncloud.desktopclient;
|
||||
OC_OEM_SHARE_ICNS = "";
|
||||
OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE = "";
|
||||
|
||||
@@ -28,19 +28,26 @@ include(GenerateExportHeader)
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS)
|
||||
|
||||
if (NOT DEFINED APPLICATION_EXECUTABLE )
|
||||
set ( APPLICATION_EXECUTABLE "owncloud" )
|
||||
endif()
|
||||
|
||||
#---HELPER---
|
||||
add_library(ownclouddolphinpluginhelper SHARED ownclouddolphinpluginhelper.cpp)
|
||||
target_link_libraries(ownclouddolphinpluginhelper Qt5::Network)
|
||||
generate_export_header(ownclouddolphinpluginhelper)
|
||||
install(TARGETS ownclouddolphinpluginhelper LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
set(OWNCLOUDDOLPHINHELPER ${APPLICATION_EXECUTABLE}dolphinpluginhelper)
|
||||
add_library(${OWNCLOUDDOLPHINHELPER} SHARED ownclouddolphinpluginhelper.cpp)
|
||||
target_link_libraries(${OWNCLOUDDOLPHINHELPER} Qt5::Network)
|
||||
generate_export_header(${OWNCLOUDDOLPHINHELPER})
|
||||
install(TARGETS ${OWNCLOUDDOLPHINHELPER} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
|
||||
#---OVERLAY PLUGIN---
|
||||
kcoreaddons_add_plugin(ownclouddolphinoverlayplugin INSTALL_NAMESPACE "kf5/overlayicon"
|
||||
set(OWNCLOUDDOLPHINOVERLAYPLUGIN ${APPLICATION_EXECUTABLE}dolphinoverlayplugin)
|
||||
kcoreaddons_add_plugin(${OWNCLOUDDOLPHINOVERLAYPLUGIN} INSTALL_NAMESPACE "kf5/overlayicon"
|
||||
JSON ownclouddolphinoverlayplugin.json SOURCES ownclouddolphinoverlayplugin.cpp)
|
||||
target_link_libraries(ownclouddolphinoverlayplugin KF5::CoreAddons KF5::KIOCore KF5::KIOWidgets ownclouddolphinpluginhelper)
|
||||
target_link_libraries(${OWNCLOUDDOLPHINOVERLAYPLUGIN} KF5::CoreAddons KF5::KIOCore KF5::KIOWidgets ${OWNCLOUDDOLPHINHELPER})
|
||||
|
||||
#---ACTION PLUGIN---
|
||||
add_library(ownclouddolphinactionplugin MODULE ownclouddolphinactionplugin.cpp)
|
||||
target_link_libraries(ownclouddolphinactionplugin KF5::CoreAddons KF5::KIOCore KF5::KIOWidgets ownclouddolphinpluginhelper)
|
||||
install(FILES ownclouddolphinactionplugin.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR})
|
||||
install(TARGETS ownclouddolphinactionplugin DESTINATION ${KDE_INSTALL_PLUGINDIR})
|
||||
set(OWNCLOUDDOLPHINACTIONPLUGIN ${APPLICATION_EXECUTABLE}dolphinactionplugin)
|
||||
add_library(${OWNCLOUDDOLPHINACTIONPLUGIN} MODULE ownclouddolphinactionplugin.cpp)
|
||||
target_link_libraries(${OWNCLOUDDOLPHINACTIONPLUGIN} KF5::CoreAddons KF5::KIOCore KF5::KIOWidgets ${OWNCLOUDDOLPHINHELPER})
|
||||
install(FILES ownclouddolphinactionplugin.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} RENAME ${OWNCLOUDDOLPHINACTIONPLUGIN}.desktop)
|
||||
install(TARGETS ${OWNCLOUDDOLPHINACTIONPLUGIN} DESTINATION ${KDE_INSTALL_PLUGINDIR})
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# this script creates a plugin for nemo, just be replacing
|
||||
# all occurences of Nautilus with Nemo.
|
||||
|
||||
sed -i.org -e 's/autilus/emo/g' syncstate_nemo.py
|
||||
@@ -3,4 +3,4 @@
|
||||
# this script replaces the line
|
||||
# appname = 'ownCloud'
|
||||
# with the correct branding name in the syncstate.py script
|
||||
/usr/bin/sed -i.org -e 's/appname\s*=\s*'"'"'ownCloud'"'/appname = '$1'/" syncstate.py
|
||||
sed -i.org -e 's/appname\s*=\s*'"'"'ownCloud'"'/appname = '$1'/" syncstate.py
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# Copyright (C) by Klaas Freitag <freitag@owncloud.com>
|
||||
#
|
||||
@@ -67,6 +66,7 @@ class SocketConnect(GObject.GObject):
|
||||
GObject.timeout_add(5000, self._connectToSocketServer)
|
||||
|
||||
def sendCommand(self, cmd):
|
||||
# print("Server command: " + cmd)
|
||||
if self.connected:
|
||||
try:
|
||||
self._sock.send(cmd)
|
||||
@@ -226,41 +226,43 @@ class SyncStateExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.Info
|
||||
for p in socketConnect.nautilusVFSFile_table:
|
||||
if p == path or p.startswith(path):
|
||||
item = socketConnect.nautilusVFSFile_table[p]['item']
|
||||
update_items.append(item)
|
||||
update_items.append(p)
|
||||
|
||||
for item in update_items:
|
||||
item.invalidate_extension_info()
|
||||
for path1 in update_items:
|
||||
socketConnect.nautilusVFSFile_table[path1]['item'].invalidate_extension_info()
|
||||
|
||||
# Handles a single line of server response and sets the emblem
|
||||
def handle_commands(self, action, args):
|
||||
Emblems = { 'OK' : appname +'_ok',
|
||||
'SYNC' : appname +'_sync',
|
||||
'NEW' : appname +'_sync',
|
||||
'IGNORE' : appname +'_warn',
|
||||
'ERROR' : appname +'_error',
|
||||
'OK+SWM' : appname +'_ok_shared',
|
||||
'SYNC+SWM' : appname +'_sync_shared',
|
||||
'NEW+SWM' : appname +'_sync_shared',
|
||||
'IGNORE+SWM': appname +'_warn_shared',
|
||||
'ERROR+SWM' : appname +'_error_shared',
|
||||
'NOP' : appname +'_error'
|
||||
}
|
||||
|
||||
# file = args[0] # For debug only
|
||||
# print("Action for " + file + ": " + args[0]) # For debug only
|
||||
if action == 'STATUS':
|
||||
newState = args[0]
|
||||
emblem = Emblems[newState]
|
||||
filename = ':'.join(args[1:])
|
||||
|
||||
if emblem:
|
||||
itemStore = self.find_item_for_file(filename)
|
||||
if itemStore:
|
||||
if( not itemStore['state'] or newState != itemStore['state'] ):
|
||||
item = itemStore['item']
|
||||
item.add_emblem(emblem)
|
||||
# print("Setting emblem on " + filename + "<>" + emblem + "<>") # For debug only
|
||||
socketConnect.nautilusVFSFile_table[filename] = {'item': item, 'state':newState}
|
||||
itemStore = self.find_item_for_file(filename)
|
||||
if itemStore:
|
||||
if( not itemStore['state'] or newState != itemStore['state'] ):
|
||||
item = itemStore['item']
|
||||
|
||||
# print("Setting emblem on " + filename + "<>" + emblem + "<>") # For debug only
|
||||
|
||||
# If an emblem is already set for this item, we need to
|
||||
# clear the existing extension info before setting a new one.
|
||||
#
|
||||
# That will also trigger a new call to
|
||||
# update_file_info for this item! That's why we set
|
||||
# skipNextUpdate to True: we don't want to pull the
|
||||
# current data from the client after getting a push
|
||||
# notification.
|
||||
invalidate = itemStore['state'] != None
|
||||
if invalidate:
|
||||
item.invalidate_extension_info()
|
||||
self.set_emblem(item, newState)
|
||||
|
||||
socketConnect.nautilusVFSFile_table[filename] = {
|
||||
'item': item,
|
||||
'state': newState,
|
||||
'skipNextUpdate': invalidate }
|
||||
|
||||
elif action == 'UPDATE_VIEW':
|
||||
# Search all items underneath this path and invalidate them
|
||||
@@ -272,6 +274,25 @@ class SyncStateExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.Info
|
||||
elif action == 'UNREGISTER_PATH':
|
||||
self.invalidate_items_underneath(args[0])
|
||||
|
||||
def set_emblem(self, item, state):
|
||||
Emblems = { 'OK' : appname +'_ok',
|
||||
'SYNC' : appname +'_sync',
|
||||
'NEW' : appname +'_sync',
|
||||
'IGNORE' : appname +'_warn',
|
||||
'ERROR' : appname +'_error',
|
||||
'OK+SWM' : appname +'_ok_shared',
|
||||
'SYNC+SWM' : appname +'_sync_shared',
|
||||
'NEW+SWM' : appname +'_sync_shared',
|
||||
'IGNORE+SWM': appname +'_warn_shared',
|
||||
'ERROR+SWM' : appname +'_error_shared',
|
||||
'NOP' : ''
|
||||
}
|
||||
|
||||
emblem = 'NOP' # Show nothing if no emblem is defined.
|
||||
if state in Emblems:
|
||||
emblem = Emblems[state]
|
||||
item.add_emblem(emblem)
|
||||
|
||||
def update_file_info(self, item):
|
||||
if item.get_uri_scheme() != 'file':
|
||||
return
|
||||
@@ -280,13 +301,28 @@ class SyncStateExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.Info
|
||||
if item.is_directory():
|
||||
filename += '/'
|
||||
|
||||
inScope = False
|
||||
for reg_path in socketConnect.registered_paths:
|
||||
if filename.startswith(reg_path):
|
||||
socketConnect.nautilusVFSFile_table[filename] = {'item': item, 'state':''}
|
||||
|
||||
# item.add_string_attribute('share_state', "share state") # ?
|
||||
self.askForOverlay(filename)
|
||||
inScope = True
|
||||
break
|
||||
else:
|
||||
# print("Not in scope:" + filename) # For debug only
|
||||
pass
|
||||
|
||||
if not inScope:
|
||||
return
|
||||
|
||||
# Ask for the current state from the client -- unless this update was
|
||||
# triggered by receiving a STATUS message from the client in the first
|
||||
# place.
|
||||
itemStore = self.find_item_for_file(filename)
|
||||
if itemStore and itemStore['skipNextUpdate'] and itemStore['state']:
|
||||
itemStore['skipNextUpdate'] = False
|
||||
itemStore['item'] = item
|
||||
self.set_emblem(item, itemStore['state'])
|
||||
else:
|
||||
socketConnect.nautilusVFSFile_table[filename] = {
|
||||
'item': item,
|
||||
'state': None,
|
||||
'skipNextUpdate': False }
|
||||
|
||||
# item.add_string_attribute('share_state', "share state") # ?
|
||||
self.askForOverlay(filename)
|
||||
|
||||
@@ -108,31 +108,6 @@ HRESULT RegisterCLSID(LPCOLESTR guidStr, PCWSTR overlayStr, PCWSTR szModule)
|
||||
return hResult;
|
||||
}
|
||||
|
||||
HRESULT _stdcall DllRegisterServer(void)
|
||||
{
|
||||
HRESULT hResult = S_OK;
|
||||
|
||||
wchar_t szModule[MAX_PATH];
|
||||
|
||||
if (GetModuleFileName(instanceHandle, szModule, ARRAYSIZE(szModule)) == 0) {
|
||||
hResult = HRESULT_FROM_WIN32(GetLastError());
|
||||
return hResult;
|
||||
}
|
||||
|
||||
hResult = RegisterCLSID(OVERLAY_GUID_ERROR, OVERLAY_NAME_ERROR, szModule);
|
||||
if (!SUCCEEDED(hResult)) { return hResult; }
|
||||
hResult = RegisterCLSID(OVERLAY_GUID_OK, OVERLAY_NAME_OK, szModule);
|
||||
if (!SUCCEEDED(hResult)) { return hResult; }
|
||||
hResult = RegisterCLSID(OVERLAY_GUID_OK_SHARED, OVERLAY_NAME_OK_SHARED, szModule);
|
||||
if (!SUCCEEDED(hResult)) { return hResult; }
|
||||
hResult = RegisterCLSID(OVERLAY_GUID_SYNC, OVERLAY_NAME_SYNC, szModule);
|
||||
if (!SUCCEEDED(hResult)) { return hResult; }
|
||||
hResult = RegisterCLSID(OVERLAY_GUID_WARNING, OVERLAY_NAME_WARNING, szModule);
|
||||
|
||||
return hResult;
|
||||
}
|
||||
|
||||
|
||||
HRESULT UnregisterCLSID(LPCOLESTR guidStr, PCWSTR overlayStr)
|
||||
{
|
||||
HRESULT hResult = S_OK;
|
||||
@@ -155,6 +130,37 @@ HRESULT UnregisterCLSID(LPCOLESTR guidStr, PCWSTR overlayStr)
|
||||
return hResult;
|
||||
}
|
||||
|
||||
HRESULT _stdcall DllRegisterServer(void)
|
||||
{
|
||||
HRESULT hResult = S_OK;
|
||||
|
||||
wchar_t szModule[MAX_PATH];
|
||||
|
||||
if (GetModuleFileName(instanceHandle, szModule, ARRAYSIZE(szModule)) == 0) {
|
||||
hResult = HRESULT_FROM_WIN32(GetLastError());
|
||||
return hResult;
|
||||
}
|
||||
|
||||
// Unregister any obsolete CLSID when we register here
|
||||
// Those CLSID were removed in 2.1, but we need to make sure to prevent any previous version
|
||||
// of the extension on the system from loading at the same time as a new version to avoid crashing explorer.
|
||||
UnregisterCLSID(OVERLAY_GUID_ERROR_SHARED, OVERLAY_NAME_ERROR_SHARED);
|
||||
UnregisterCLSID(OVERLAY_GUID_SYNC_SHARED, OVERLAY_NAME_SYNC_SHARED);
|
||||
UnregisterCLSID(OVERLAY_GUID_WARNING_SHARED, OVERLAY_NAME_WARNING_SHARED);
|
||||
|
||||
hResult = RegisterCLSID(OVERLAY_GUID_ERROR, OVERLAY_NAME_ERROR, szModule);
|
||||
if (!SUCCEEDED(hResult)) { return hResult; }
|
||||
hResult = RegisterCLSID(OVERLAY_GUID_OK, OVERLAY_NAME_OK, szModule);
|
||||
if (!SUCCEEDED(hResult)) { return hResult; }
|
||||
hResult = RegisterCLSID(OVERLAY_GUID_OK_SHARED, OVERLAY_NAME_OK_SHARED, szModule);
|
||||
if (!SUCCEEDED(hResult)) { return hResult; }
|
||||
hResult = RegisterCLSID(OVERLAY_GUID_SYNC, OVERLAY_NAME_SYNC, szModule);
|
||||
if (!SUCCEEDED(hResult)) { return hResult; }
|
||||
hResult = RegisterCLSID(OVERLAY_GUID_WARNING, OVERLAY_NAME_WARNING, szModule);
|
||||
|
||||
return hResult;
|
||||
}
|
||||
|
||||
STDAPI DllUnregisterServer(void)
|
||||
{
|
||||
HRESULT hResult = S_OK;
|
||||
|
||||
@@ -14,19 +14,25 @@
|
||||
|
||||
|
||||
#define OVERLAY_GUID_ERROR L"{0960F090-F328-48A3-B746-276B1E3C3722}"
|
||||
#define OVERLAY_GUID_ERROR_SHARED L"{0960F091-F328-48A3-B746-276B1E3C3722}"
|
||||
#define OVERLAY_GUID_OK L"{0960F092-F328-48A3-B746-276B1E3C3722}"
|
||||
#define OVERLAY_GUID_OK_SHARED L"{0960F093-F328-48A3-B746-276B1E3C3722}"
|
||||
#define OVERLAY_GUID_SYNC L"{0960F094-F328-48A3-B746-276B1E3C3722}"
|
||||
#define OVERLAY_GUID_SYNC_SHARED L"{0960F095-F328-48A3-B746-276B1E3C3722}"
|
||||
#define OVERLAY_GUID_WARNING L"{0960F096-F328-48A3-B746-276B1E3C3722}"
|
||||
#define OVERLAY_GUID_WARNING_SHARED L"{0960F097-F328-48A3-B746-276B1E3C3722}"
|
||||
|
||||
#define OVERLAY_GENERIC_NAME L"OC Overlay Handler"
|
||||
|
||||
// two spaces to put us ahead of the competition :/
|
||||
#define OVERLAY_NAME_ERROR L" OCError"
|
||||
#define OVERLAY_NAME_ERROR_SHARED L" OCErrorShared"
|
||||
#define OVERLAY_NAME_OK L" OCOK"
|
||||
#define OVERLAY_NAME_OK_SHARED L" OCOKShared"
|
||||
#define OVERLAY_NAME_SYNC L" OCSync"
|
||||
#define OVERLAY_NAME_SYNC_SHARED L" OCSyncShared"
|
||||
#define OVERLAY_NAME_WARNING L" OCWarning"
|
||||
#define OVERLAY_NAME_WARNING_SHARED L" OCWarningShared"
|
||||
|
||||
#define REGISTRY_OVERLAY_KEY L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers"
|
||||
#define REGISTRY_CLSID L"CLSID"
|
||||
|
||||
@@ -31,12 +31,24 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define BUFSIZE 512
|
||||
|
||||
std::wstring getUserName() {
|
||||
DWORD len = BUFSIZE;
|
||||
TCHAR buf[BUFSIZE];
|
||||
if (GetUserName(buf, &len)) {
|
||||
return std::wstring(&buf[0], len);
|
||||
} else {
|
||||
return std::wstring();
|
||||
}
|
||||
}
|
||||
|
||||
// This code is run in a thread
|
||||
void RemotePathChecker::workerThreadLoop()
|
||||
{
|
||||
auto pipename = std::wstring(L"\\\\.\\pipe\\");
|
||||
pipename += L"ownCloud";
|
||||
pipename += L"ownCloud\\";
|
||||
pipename += getUserName();
|
||||
|
||||
bool connected = false;
|
||||
CommunicationSocket socket;
|
||||
@@ -241,4 +253,4 @@ RemotePathChecker::FileState RemotePathChecker::_StrToFileState(const std::wstri
|
||||
}
|
||||
|
||||
return StateNone;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,353 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "fancylineedit.h"
|
||||
|
||||
#include <QEvent>
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QApplication>
|
||||
#include <QMenu>
|
||||
#include <QMouseEvent>
|
||||
#include <QLabel>
|
||||
#include <QAbstractButton>
|
||||
#include <QPainter>
|
||||
#include <QStyle>
|
||||
#include <QPaintEvent>
|
||||
#include <QDesktopWidget>
|
||||
|
||||
/*! Opens a menu at the specified widget position.
|
||||
* This functions computes the position where to show the menu, and opens it with
|
||||
* QMenu::exec().
|
||||
* \param menu The menu to open
|
||||
* \param widget The widget next to which to open the menu
|
||||
*/
|
||||
static void execMenuAtWidget(QMenu *menu, QWidget *widget)
|
||||
{
|
||||
QPoint p;
|
||||
QRect screen = qApp->desktop()->availableGeometry(widget);
|
||||
QSize sh = menu->sizeHint();
|
||||
QRect rect = widget->rect();
|
||||
if (widget->isRightToLeft()) {
|
||||
if (widget->mapToGlobal(QPoint(0, rect.bottom())).y() + sh.height() <= screen.height())
|
||||
p = widget->mapToGlobal(rect.bottomRight());
|
||||
else
|
||||
p = widget->mapToGlobal(rect.topRight() - QPoint(0, sh.height()));
|
||||
p.rx() -= sh.width();
|
||||
} else {
|
||||
if (widget->mapToGlobal(QPoint(0, rect.bottom())).y() + sh.height() <= screen.height())
|
||||
p = widget->mapToGlobal(rect.bottomLeft());
|
||||
else
|
||||
p = widget->mapToGlobal(rect.topLeft() - QPoint(0, sh.height()));
|
||||
}
|
||||
p.rx() = qMax(screen.left(), qMin(p.x(), screen.right() - sh.width()));
|
||||
p.ry() += 1;
|
||||
|
||||
menu->exec(p);
|
||||
}
|
||||
|
||||
/*!
|
||||
\class Utils::FancyLineEdit
|
||||
|
||||
\brief A line edit with an embedded pixmap on one side that is connected to
|
||||
a menu.
|
||||
|
||||
Additionally, it can display a grayed hintText (like "Type Here to")
|
||||
when not focused and empty. When connecting to the changed signals and
|
||||
querying text, one has to be aware that the text is set to that hint
|
||||
text if isShowingHintText() returns true (that is, does not contain
|
||||
valid user input).
|
||||
*/
|
||||
|
||||
enum { margin = 6 };
|
||||
|
||||
#define ICONBUTTON_HEIGHT 18
|
||||
#define FADE_TIME 160
|
||||
|
||||
namespace Utils {
|
||||
|
||||
// --------- FancyLineEditPrivate
|
||||
class FancyLineEditPrivate : public QObject
|
||||
{
|
||||
public:
|
||||
explicit FancyLineEditPrivate(FancyLineEdit *parent);
|
||||
|
||||
virtual bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE;
|
||||
|
||||
FancyLineEdit *m_lineEdit;
|
||||
QPixmap m_pixmap[2];
|
||||
QMenu *m_menu[2];
|
||||
bool m_menuTabFocusTrigger[2];
|
||||
IconButton *m_iconbutton[2];
|
||||
bool m_iconEnabled[2];
|
||||
};
|
||||
|
||||
|
||||
FancyLineEditPrivate::FancyLineEditPrivate(FancyLineEdit *parent) :
|
||||
QObject(parent), m_lineEdit(parent)
|
||||
{
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
m_menu[i] = 0;
|
||||
m_menuTabFocusTrigger[i] = false;
|
||||
m_iconbutton[i] = new IconButton(parent);
|
||||
m_iconbutton[i]->installEventFilter(this);
|
||||
m_iconbutton[i]->hide();
|
||||
m_iconbutton[i]->setAutoHide(false);
|
||||
m_iconEnabled[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool FancyLineEditPrivate::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
int buttonIndex = -1;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (obj == m_iconbutton[i]) {
|
||||
buttonIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (buttonIndex == -1)
|
||||
return QObject::eventFilter(obj, event);
|
||||
switch (event->type()) {
|
||||
case QEvent::FocusIn:
|
||||
if (m_menuTabFocusTrigger[buttonIndex] && m_menu[buttonIndex]) {
|
||||
m_lineEdit->setFocus();
|
||||
execMenuAtWidget(m_menu[buttonIndex], m_iconbutton[buttonIndex]);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
|
||||
// --------- FancyLineEdit
|
||||
FancyLineEdit::FancyLineEdit(QWidget *parent) :
|
||||
QLineEdit(parent),
|
||||
d(new FancyLineEditPrivate(this))
|
||||
{
|
||||
ensurePolished();
|
||||
updateMargins();
|
||||
|
||||
connect(this, SIGNAL(textChanged(QString)), this, SLOT(checkButtons(QString)));
|
||||
connect(d->m_iconbutton[Left], SIGNAL(clicked()), this, SLOT(iconClicked()));
|
||||
connect(d->m_iconbutton[Right], SIGNAL(clicked()), this, SLOT(iconClicked()));
|
||||
}
|
||||
|
||||
void FancyLineEdit::checkButtons(const QString &text)
|
||||
{
|
||||
if (m_oldText.isEmpty() || text.isEmpty()) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (d->m_iconbutton[i]->hasAutoHide())
|
||||
d->m_iconbutton[i]->animateShow(!text.isEmpty());
|
||||
}
|
||||
m_oldText = text;
|
||||
}
|
||||
}
|
||||
|
||||
FancyLineEdit::~FancyLineEdit()
|
||||
{
|
||||
}
|
||||
|
||||
void FancyLineEdit::setButtonVisible(Side side, bool visible)
|
||||
{
|
||||
d->m_iconbutton[side]->setVisible(visible);
|
||||
d->m_iconEnabled[side] = visible;
|
||||
updateMargins();
|
||||
}
|
||||
|
||||
bool FancyLineEdit::isButtonVisible(Side side) const
|
||||
{
|
||||
return d->m_iconEnabled[side];
|
||||
}
|
||||
|
||||
void FancyLineEdit::iconClicked()
|
||||
{
|
||||
IconButton *button = qobject_cast<IconButton *>(sender());
|
||||
int index = -1;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
if (d->m_iconbutton[i] == button)
|
||||
index = i;
|
||||
if (index == -1)
|
||||
return;
|
||||
if (d->m_menu[index]) {
|
||||
execMenuAtWidget(d->m_menu[index], button);
|
||||
} else {
|
||||
emit buttonClicked((Side)index);
|
||||
if (index == Left)
|
||||
emit leftButtonClicked();
|
||||
else if (index == Right)
|
||||
emit rightButtonClicked();
|
||||
}
|
||||
}
|
||||
|
||||
void FancyLineEdit::updateMargins()
|
||||
{
|
||||
bool leftToRight = (layoutDirection() == Qt::LeftToRight);
|
||||
Side realLeft = (leftToRight ? Left : Right);
|
||||
Side realRight = (leftToRight ? Right : Left);
|
||||
|
||||
int leftMargin = d->m_iconbutton[realLeft]->pixmap().width() + 8;
|
||||
int rightMargin = d->m_iconbutton[realRight]->pixmap().width() + 8;
|
||||
// Note KDE does not reserve space for the highlight color
|
||||
if (style()->inherits("OxygenStyle")) {
|
||||
leftMargin = qMax(24, leftMargin);
|
||||
rightMargin = qMax(24, rightMargin);
|
||||
}
|
||||
|
||||
QMargins margins((d->m_iconEnabled[realLeft] ? leftMargin : 0), 0,
|
||||
(d->m_iconEnabled[realRight] ? rightMargin : 0), 0);
|
||||
|
||||
setTextMargins(margins);
|
||||
}
|
||||
|
||||
void FancyLineEdit::updateButtonPositions()
|
||||
{
|
||||
QRect contentRect = rect();
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
Side iconpos = (Side)i;
|
||||
if (layoutDirection() == Qt::RightToLeft)
|
||||
iconpos = (iconpos == Left ? Right : Left);
|
||||
|
||||
if (iconpos == FancyLineEdit::Right) {
|
||||
const int iconoffset = textMargins().right() + 4;
|
||||
d->m_iconbutton[i]->setGeometry(contentRect.adjusted(width() - iconoffset, 0, 0, 0));
|
||||
} else {
|
||||
const int iconoffset = textMargins().left() + 4;
|
||||
d->m_iconbutton[i]->setGeometry(contentRect.adjusted(0, 0, -width() + iconoffset, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FancyLineEdit::resizeEvent(QResizeEvent *)
|
||||
{
|
||||
updateButtonPositions();
|
||||
}
|
||||
|
||||
void FancyLineEdit::setButtonPixmap(Side side, const QPixmap &buttonPixmap)
|
||||
{
|
||||
d->m_iconbutton[side]->setPixmap(buttonPixmap);
|
||||
updateMargins();
|
||||
updateButtonPositions();
|
||||
update();
|
||||
}
|
||||
|
||||
QPixmap FancyLineEdit::buttonPixmap(Side side) const
|
||||
{
|
||||
return d->m_pixmap[side];
|
||||
}
|
||||
|
||||
void FancyLineEdit::setButtonMenu(Side side, QMenu *buttonMenu)
|
||||
{
|
||||
d->m_menu[side] = buttonMenu;
|
||||
d->m_iconbutton[side]->setIconOpacity(1.0);
|
||||
}
|
||||
|
||||
QMenu *FancyLineEdit::buttonMenu(Side side) const
|
||||
{
|
||||
return d->m_menu[side];
|
||||
}
|
||||
|
||||
bool FancyLineEdit::hasMenuTabFocusTrigger(Side side) const
|
||||
{
|
||||
return d->m_menuTabFocusTrigger[side];
|
||||
}
|
||||
|
||||
void FancyLineEdit::setMenuTabFocusTrigger(Side side, bool v)
|
||||
{
|
||||
if (d->m_menuTabFocusTrigger[side] == v)
|
||||
return;
|
||||
|
||||
d->m_menuTabFocusTrigger[side] = v;
|
||||
d->m_iconbutton[side]->setFocusPolicy(v ? Qt::TabFocus : Qt::NoFocus);
|
||||
}
|
||||
|
||||
bool FancyLineEdit::hasAutoHideButton(Side side) const
|
||||
{
|
||||
return d->m_iconbutton[side]->hasAutoHide();
|
||||
}
|
||||
|
||||
void FancyLineEdit::setAutoHideButton(Side side, bool h)
|
||||
{
|
||||
d->m_iconbutton[side]->setAutoHide(h);
|
||||
if (h)
|
||||
d->m_iconbutton[side]->setIconOpacity(text().isEmpty() ? 0.0 : 1.0);
|
||||
else
|
||||
d->m_iconbutton[side]->setIconOpacity(1.0);
|
||||
}
|
||||
|
||||
void FancyLineEdit::setButtonToolTip(Side side, const QString &tip)
|
||||
{
|
||||
d->m_iconbutton[side]->setToolTip(tip);
|
||||
}
|
||||
|
||||
void FancyLineEdit::setButtonFocusPolicy(Side side, Qt::FocusPolicy policy)
|
||||
{
|
||||
d->m_iconbutton[side]->setFocusPolicy(policy);
|
||||
}
|
||||
|
||||
// IconButton - helper class to represent a clickable icon
|
||||
|
||||
IconButton::IconButton(QWidget *parent)
|
||||
: QAbstractButton(parent), m_iconOpacity(0), m_autoHide(false)
|
||||
{
|
||||
setCursor(Qt::ArrowCursor);
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
}
|
||||
|
||||
void IconButton::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter(this);
|
||||
QRect pixmapRect = QRect(0, 0, m_pixmap.width(), m_pixmap.height());
|
||||
pixmapRect.moveCenter(rect().center());
|
||||
|
||||
if (m_autoHide)
|
||||
painter.setOpacity(m_iconOpacity);
|
||||
|
||||
painter.drawPixmap(pixmapRect, m_pixmap);
|
||||
}
|
||||
|
||||
void IconButton::animateShow(bool visible)
|
||||
{
|
||||
if (visible) {
|
||||
QPropertyAnimation *animation = new QPropertyAnimation(this, "iconOpacity");
|
||||
animation->setDuration(FADE_TIME);
|
||||
animation->setEndValue(1.0);
|
||||
animation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
} else {
|
||||
QPropertyAnimation *animation = new QPropertyAnimation(this, "iconOpacity");
|
||||
animation->setDuration(FADE_TIME);
|
||||
animation->setEndValue(0.0);
|
||||
animation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Utils
|
||||
@@ -1,121 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef FANCYLINEEDIT_H
|
||||
#define FANCYLINEEDIT_H
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QAbstractButton>
|
||||
|
||||
namespace Utils {
|
||||
|
||||
class FancyLineEditPrivate;
|
||||
|
||||
class IconButton: public QAbstractButton
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(float iconOpacity READ iconOpacity WRITE setIconOpacity)
|
||||
Q_PROPERTY(bool autoHide READ hasAutoHide WRITE setAutoHide)
|
||||
Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap)
|
||||
public:
|
||||
explicit IconButton(QWidget *parent = 0);
|
||||
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
|
||||
void setPixmap(const QPixmap &pixmap) { m_pixmap = pixmap; update(); }
|
||||
QPixmap pixmap() const { return m_pixmap; }
|
||||
float iconOpacity() { return m_iconOpacity; }
|
||||
void setIconOpacity(float value) { m_iconOpacity = value; update(); }
|
||||
void animateShow(bool visible);
|
||||
|
||||
void setAutoHide(bool hide) { m_autoHide = hide; }
|
||||
bool hasAutoHide() const { return m_autoHide; }
|
||||
|
||||
private:
|
||||
float m_iconOpacity;
|
||||
bool m_autoHide;
|
||||
QPixmap m_pixmap;
|
||||
};
|
||||
|
||||
class FancyLineEdit : public QLineEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_ENUMS(Side)
|
||||
|
||||
public:
|
||||
enum Side {Left = 0, Right = 1};
|
||||
|
||||
explicit FancyLineEdit(QWidget *parent = 0);
|
||||
~FancyLineEdit();
|
||||
|
||||
QPixmap buttonPixmap(Side side) const;
|
||||
void setButtonPixmap(Side side, const QPixmap &pixmap);
|
||||
|
||||
QMenu *buttonMenu(Side side) const;
|
||||
void setButtonMenu(Side side, QMenu *menu);
|
||||
|
||||
void setButtonVisible(Side side, bool visible);
|
||||
bool isButtonVisible(Side side) const;
|
||||
|
||||
void setButtonToolTip(Side side, const QString &);
|
||||
void setButtonFocusPolicy(Side side, Qt::FocusPolicy policy);
|
||||
|
||||
// Set whether tabbing in will trigger the menu.
|
||||
void setMenuTabFocusTrigger(Side side, bool v);
|
||||
bool hasMenuTabFocusTrigger(Side side) const;
|
||||
|
||||
// Set if icon should be hidden when text is empty
|
||||
void setAutoHideButton(Side side, bool h);
|
||||
bool hasAutoHideButton(Side side) const;
|
||||
#if QT_VERSION <= 0x040700
|
||||
void setPlaceholderText( const QString& ) { }
|
||||
#endif
|
||||
|
||||
signals:
|
||||
void buttonClicked(Utils::FancyLineEdit::Side side);
|
||||
void leftButtonClicked();
|
||||
void rightButtonClicked();
|
||||
|
||||
private slots:
|
||||
void checkButtons(const QString &);
|
||||
void iconClicked();
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
void updateMargins();
|
||||
void updateButtonPositions();
|
||||
friend class Utils::FancyLineEditPrivate;
|
||||
|
||||
FancyLineEditPrivate *d;
|
||||
QString m_oldText;
|
||||
};
|
||||
|
||||
} // namespace Utils
|
||||
|
||||
#endif // FANCYLINEEDIT_H
|
||||
@@ -0,0 +1,264 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Daniel Molkentin <daniel@molkentin.de>
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef TOKENIZER_H
|
||||
#define TOKENIZER_H
|
||||
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
#include <QSharedPointer>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
template <class T, class const_iterator>
|
||||
struct QTokenizerPrivate {
|
||||
typedef typename T::value_type char_type;
|
||||
|
||||
struct State {
|
||||
bool inQuote;
|
||||
bool inEscape;
|
||||
char_type quoteChar;
|
||||
State() : inQuote(false), inEscape(false), quoteChar('\0') {}
|
||||
};
|
||||
|
||||
QTokenizerPrivate(const T& _string, const T& _delims) :
|
||||
string(_string)
|
||||
, begin(string.begin())
|
||||
, end(string.end())
|
||||
, tokenBegin(end)
|
||||
, tokenEnd(begin)
|
||||
, delimiters(_delims)
|
||||
, isDelim(false)
|
||||
, returnDelimiters(false)
|
||||
, returnQuotes(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool isDelimiter(char_type c) const {
|
||||
return delimiters.contains(c);
|
||||
}
|
||||
|
||||
bool isQuote(char_type c) const {
|
||||
return quotes.contains(c);
|
||||
}
|
||||
|
||||
// Returns true if a delimiter was not hit
|
||||
bool nextChar(State* state, char_type c) {
|
||||
if (state->inQuote) {
|
||||
if (state->inEscape) {
|
||||
state->inEscape = false;
|
||||
} else if (c == '\\') {
|
||||
state->inEscape = true;
|
||||
} else if (c == state->quoteChar) {
|
||||
state->inQuote = false;
|
||||
}
|
||||
} else {
|
||||
if (isDelimiter(c))
|
||||
return false;
|
||||
state->inQuote = isQuote(state->quoteChar = c);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
T string;
|
||||
// ### copies begin and end for performance, premature optimization?
|
||||
const_iterator begin;
|
||||
const_iterator end;
|
||||
const_iterator tokenBegin;
|
||||
const_iterator tokenEnd;
|
||||
T delimiters;
|
||||
T quotes;
|
||||
bool isDelim;
|
||||
bool returnDelimiters;
|
||||
bool returnQuotes;
|
||||
};
|
||||
|
||||
template <class T, class const_iterator>
|
||||
class QTokenizer {
|
||||
public:
|
||||
typedef typename T::value_type char_type;
|
||||
|
||||
/*!
|
||||
\class QTokenizer
|
||||
\inmodule QtNetwork
|
||||
\brief QTokenizer tokenizes Strings on QString, QByteArray,
|
||||
std::string or std::wstring
|
||||
|
||||
Example Usage:
|
||||
|
||||
\code
|
||||
QString str = ...;
|
||||
QByteArrayTokenizer tokenizer(str, "; ");
|
||||
tokenizer.setQuoteCharacters("\"'");
|
||||
tokenizer.setReturnDelimiters(true);
|
||||
while (tokenizer.hasNext()) {
|
||||
QByteArray token = tokenizer.next();
|
||||
bool isDelimiter = tokenizer.isDelimiter();
|
||||
...
|
||||
}
|
||||
\endcode
|
||||
|
||||
\param string The string to tokenize
|
||||
\param delimiters A string containing delimiters
|
||||
|
||||
\sa QStringTokenizer, QByteArrayTokenizer, StringTokenizer, WStringTokenizer
|
||||
*/
|
||||
QTokenizer(const T& string, const T& delimiters)
|
||||
: d(new QTokenizerPrivate<T, const_iterator>(string, delimiters))
|
||||
{ }
|
||||
|
||||
/*!
|
||||
Whether or not to return delimiters as tokens
|
||||
\see setQuoteCharacters
|
||||
*/
|
||||
void setReturnDelimiters(bool enable) { d->returnDelimiters = enable; }
|
||||
|
||||
|
||||
/*!
|
||||
Sets characters that are considered to start and end quotes.
|
||||
|
||||
When between two characters considered a quote, delimiters will
|
||||
be ignored.
|
||||
|
||||
When between quotes, blackslash characters will cause the QTokenizer
|
||||
to skip the next character.
|
||||
|
||||
\param quotes Characters that delimit quotes.
|
||||
*/
|
||||
void setQuoteCharacters(const T& quotes) { d->quotes = quotes; }
|
||||
|
||||
|
||||
/*!
|
||||
Whether or not to return delimiters as tokens
|
||||
\see setQuoteCharacters
|
||||
*/
|
||||
void setReturnQuoteCharacters(bool enable) { d->returnQuotes = enable; }
|
||||
|
||||
|
||||
/*!
|
||||
Retrieve next token.
|
||||
|
||||
Returns true if there are more tokens, false otherwise.
|
||||
|
||||
\sa next()
|
||||
*/
|
||||
bool hasNext()
|
||||
{
|
||||
typename QTokenizerPrivate<T, const_iterator>::State state;
|
||||
d->isDelim = false;
|
||||
for (;;) {
|
||||
d->tokenBegin = d->tokenEnd;
|
||||
if (d->tokenEnd == d->end)
|
||||
return false;
|
||||
d->tokenEnd++;
|
||||
if (d->nextChar(&state, *d->tokenBegin))
|
||||
break;
|
||||
if (d->returnDelimiters) {
|
||||
d->isDelim = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
while (d->tokenEnd != d->end && d->nextChar(&state, *d->tokenEnd)) {
|
||||
d->tokenEnd++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Resets the tokenizer to the starting position.
|
||||
*/
|
||||
void reset() {
|
||||
d->tokenEnd = d->begin;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if the current token is a delimiter,
|
||||
if one more more delimiting characters have been set.
|
||||
*/
|
||||
bool isDelimiter() const { return d->isDelim; }
|
||||
|
||||
/*!
|
||||
Returns the current token.
|
||||
|
||||
Use \c hasNext() to fetch the next token.
|
||||
*/
|
||||
T next() const {
|
||||
int len = d->tokenEnd-d->tokenBegin;
|
||||
const_iterator tmpStart = d->tokenBegin;
|
||||
if (!d->returnQuotes && len > 1 && d->isQuote(*d->tokenBegin)) {
|
||||
tmpStart++;
|
||||
len -= 2;
|
||||
}
|
||||
return T(tmpStart, len);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class QStringTokenizer;
|
||||
QSharedPointer<QTokenizerPrivate<T, const_iterator> > d;
|
||||
};
|
||||
|
||||
class QStringTokenizer : public QTokenizer<QString, QString::const_iterator> {
|
||||
public:
|
||||
QStringTokenizer(const QString &string, const QString &delim) :
|
||||
QTokenizer<QString, QString::const_iterator>(string, delim) {}
|
||||
/**
|
||||
* @brief Like \see next(), but returns a lightweight string reference
|
||||
* @return A reference to the token within the string
|
||||
*/
|
||||
QStringRef stringRef() {
|
||||
int begin = d->tokenBegin-d->begin;
|
||||
int end = d->tokenEnd-d->tokenBegin;
|
||||
if (!d->returnQuotes && d->isQuote(*d->tokenBegin)) {
|
||||
begin++;
|
||||
end -= 2;
|
||||
}
|
||||
return QStringRef(&d->string, begin, end);
|
||||
}
|
||||
};
|
||||
|
||||
typedef QTokenizer<QByteArray, QByteArray::const_iterator> QByteArrayTokenizer;
|
||||
typedef QTokenizer<std::string, std::string::const_iterator> StringTokenizer;
|
||||
typedef QTokenizer<std::wstring, std::wstring::const_iterator> WStringTokenizer;
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // TOKENIZER_H
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
TEMPLATE = subdirs
|
||||
SUBDIRS = test
|
||||
@@ -0,0 +1,8 @@
|
||||
TEMPLATE = app
|
||||
QT += testlib
|
||||
CONFIG += testlib
|
||||
TARGET = test
|
||||
INCLUDEPATH += . ..
|
||||
|
||||
# Input
|
||||
SOURCES += tst_qtokenizer.cpp
|
||||
@@ -0,0 +1,139 @@
|
||||
#include <QtTest>
|
||||
|
||||
#include "qtokenizer.h"
|
||||
|
||||
namespace {
|
||||
const QString simple = QLatin1String("A simple tokenizer test");
|
||||
const QString quoted = QLatin1String("\"Wait for me!\" he shouted");
|
||||
}
|
||||
|
||||
class TestTokenizer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void tokenizeQStringSimple() {
|
||||
QStringTokenizer tokenizer(simple, " ");
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("A"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("simple"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("tokenizer"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("test"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), false);
|
||||
}
|
||||
|
||||
void tokenizeQStringSimpleRef() {
|
||||
QStringTokenizer tokenizer(simple, " ");
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QVERIFY(tokenizer.stringRef() == QLatin1String("A"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QVERIFY(tokenizer.stringRef() == QLatin1String("simple"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QVERIFY(tokenizer.stringRef() == QLatin1String("tokenizer"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QVERIFY(tokenizer.stringRef() == QLatin1String("test"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), false);
|
||||
}
|
||||
|
||||
void tokenizeQStringQuoted() {
|
||||
const QString multiquote(QLatin1String("\"'Billy - the Kid' is dead!\""));
|
||||
QStringTokenizer tokenizer(multiquote, " -");
|
||||
tokenizer.setQuoteCharacters("\"");
|
||||
tokenizer.setReturnQuoteCharacters(true);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("\"'Billy - the Kid' is dead!\""));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), false);
|
||||
}
|
||||
|
||||
void tokenizeQStringSkipQuotes() {
|
||||
const QString multiquote(QLatin1String("\"'Billy - the Kid' is dead!\""));
|
||||
QStringTokenizer tokenizer(multiquote, " ");
|
||||
tokenizer.setQuoteCharacters("\"");
|
||||
tokenizer.setReturnQuoteCharacters(false);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("'Billy - the Kid' is dead!"));
|
||||
QCOMPARE(tokenizer.stringRef().toString(), QLatin1String("'Billy - the Kid' is dead!"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), false);
|
||||
}
|
||||
|
||||
|
||||
void tokenizeQStringWithDelims() {
|
||||
const QString delims(QLatin1String("I;Insist,On/a-Delimiter"));
|
||||
QStringTokenizer tokenizer(delims, ";,/-");
|
||||
tokenizer.setReturnDelimiters(true);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), false);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), true);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), false);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), true);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), false);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), true);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), false);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), true);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), false);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), false);
|
||||
}
|
||||
|
||||
void resetTokenizer() {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
QStringTokenizer tokenizer(simple, " ");
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("A"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("simple"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("tokenizer"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("test"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), false);
|
||||
|
||||
tokenizer.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// ### QByteArray, other types
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestTokenizer)
|
||||
|
||||
#include "tst_qtokenizer.moc"
|
||||
|
||||
@@ -111,9 +111,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.9.1"
|
||||
#define SQLITE_VERSION_NUMBER 3009001
|
||||
#define SQLITE_SOURCE_ID "2015-10-16 17:31:12 767c1727fec4ce11b83f25b3f1bfcfe68a2c8b02"
|
||||
#define SQLITE_VERSION "3.12.2"
|
||||
#define SQLITE_VERSION_NUMBER 3012002
|
||||
#define SQLITE_SOURCE_ID "2016-04-18 17:30:31 92dc59fd5ad66f646666042eb04195e3a61a9e8e"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@@ -347,7 +347,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
|
||||
** from [sqlite3_malloc()] and passed back through the 5th parameter.
|
||||
** To avoid memory leaks, the application should invoke [sqlite3_free()]
|
||||
** on error message strings returned through the 5th parameter of
|
||||
** of sqlite3_exec() after the error message string is no longer needed.
|
||||
** sqlite3_exec() after the error message string is no longer needed.
|
||||
** ^If the 5th parameter to sqlite3_exec() is not NULL and no errors
|
||||
** occur, then sqlite3_exec() sets the pointer in its 5th parameter to
|
||||
** NULL before returning.
|
||||
@@ -478,6 +478,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_exec(
|
||||
#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8))
|
||||
#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8))
|
||||
#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
|
||||
#define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8))
|
||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
||||
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
||||
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
|
||||
@@ -793,8 +794,13 @@ struct sqlite3_io_methods {
|
||||
** <li>[[SQLITE_FCNTL_FILE_POINTER]]
|
||||
** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
|
||||
** to the [sqlite3_file] object associated with a particular database
|
||||
** connection. See the [sqlite3_file_control()] documentation for
|
||||
** additional information.
|
||||
** connection. See also [SQLITE_FCNTL_JOURNAL_POINTER].
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_JOURNAL_POINTER]]
|
||||
** The [SQLITE_FCNTL_JOURNAL_POINTER] opcode is used to obtain a pointer
|
||||
** to the [sqlite3_file] object associated with the journal file (either
|
||||
** the [rollback journal] or the [write-ahead log]) for a particular database
|
||||
** connection. See also [SQLITE_FCNTL_FILE_POINTER].
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
|
||||
** No longer in use.
|
||||
@@ -881,6 +887,15 @@ struct sqlite3_io_methods {
|
||||
** pointer in case this file-control is not implemented. This file-control
|
||||
** is intended for diagnostic use only.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_VFS_POINTER]]
|
||||
** ^The [SQLITE_FCNTL_VFS_POINTER] opcode finds a pointer to the top-level
|
||||
** [VFSes] currently in use. ^(The argument X in
|
||||
** sqlite3_file_control(db,SQLITE_FCNTL_VFS_POINTER,X) must be
|
||||
** of type "[sqlite3_vfs] **". This opcodes will set *X
|
||||
** to a pointer to the top-level VFS.)^
|
||||
** ^When there are multiple VFS shims in the stack, this opcode finds the
|
||||
** upper-most shim only.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_PRAGMA]]
|
||||
** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA]
|
||||
** file control is sent to the open [sqlite3_file] object corresponding
|
||||
@@ -999,6 +1014,8 @@ struct sqlite3_io_methods {
|
||||
#define SQLITE_FCNTL_WAL_BLOCK 24
|
||||
#define SQLITE_FCNTL_ZIPVFS 25
|
||||
#define SQLITE_FCNTL_RBU 26
|
||||
#define SQLITE_FCNTL_VFS_POINTER 27
|
||||
#define SQLITE_FCNTL_JOURNAL_POINTER 28
|
||||
|
||||
/* deprecated names */
|
||||
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
|
||||
@@ -1211,7 +1228,7 @@ struct sqlite3_vfs {
|
||||
const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName);
|
||||
/*
|
||||
** The methods above are in versions 1 through 3 of the sqlite_vfs object.
|
||||
** New fields may be appended in figure versions. The iVersion
|
||||
** New fields may be appended in future versions. The iVersion
|
||||
** value will increment whenever this happens.
|
||||
*/
|
||||
};
|
||||
@@ -1598,29 +1615,34 @@ struct sqlite3_mem_methods {
|
||||
** </dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
|
||||
** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a static memory buffer
|
||||
** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool
|
||||
** that SQLite can use for the database page cache with the default page
|
||||
** cache implementation.
|
||||
** This configuration should not be used if an application-define page
|
||||
** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2]
|
||||
** configuration option.
|
||||
** This configuration option is a no-op if an application-define page
|
||||
** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2].
|
||||
** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
|
||||
** 8-byte aligned
|
||||
** memory, the size of each page buffer (sz), and the number of pages (N).
|
||||
** 8-byte aligned memory (pMem), the size of each page cache line (sz),
|
||||
** and the number of cache lines (N).
|
||||
** The sz argument should be the size of the largest database page
|
||||
** (a power of two between 512 and 65536) plus some extra bytes for each
|
||||
** page header. ^The number of extra bytes needed by the page header
|
||||
** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option
|
||||
** to [sqlite3_config()].
|
||||
** can be determined using [SQLITE_CONFIG_PCACHE_HDRSZ].
|
||||
** ^It is harmless, apart from the wasted memory,
|
||||
** for the sz parameter to be larger than necessary. The first
|
||||
** argument should pointer to an 8-byte aligned block of memory that
|
||||
** is at least sz*N bytes of memory, otherwise subsequent behavior is
|
||||
** undefined.
|
||||
** ^SQLite will use the memory provided by the first argument to satisfy its
|
||||
** memory needs for the first N pages that it adds to cache. ^If additional
|
||||
** page cache memory is needed beyond what is provided by this option, then
|
||||
** SQLite goes to [sqlite3_malloc()] for the additional storage space.</dd>
|
||||
** for the sz parameter to be larger than necessary. The pMem
|
||||
** argument must be either a NULL pointer or a pointer to an 8-byte
|
||||
** aligned block of memory of at least sz*N bytes, otherwise
|
||||
** subsequent behavior is undefined.
|
||||
** ^When pMem is not NULL, SQLite will strive to use the memory provided
|
||||
** to satisfy page cache needs, falling back to [sqlite3_malloc()] if
|
||||
** a page cache line is larger than sz bytes or if all of the pMem buffer
|
||||
** is exhausted.
|
||||
** ^If pMem is NULL and N is non-zero, then each database connection
|
||||
** does an initial bulk allocation for page cache memory
|
||||
** from [sqlite3_malloc()] sufficient for N cache lines if N is positive or
|
||||
** of -1024*N bytes if N is negative, . ^If additional
|
||||
** page cache memory is needed beyond what is provided by the initial
|
||||
** allocation, then SQLite goes to [sqlite3_malloc()] separately for each
|
||||
** additional cache line. </dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
|
||||
** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer
|
||||
@@ -1798,6 +1820,20 @@ struct sqlite3_mem_methods {
|
||||
** is enabled (using the [PRAGMA threads] command) and the amount of content
|
||||
** to be sorted exceeds the page size times the minimum of the
|
||||
** [PRAGMA cache_size] setting and this value.
|
||||
**
|
||||
** [[SQLITE_CONFIG_STMTJRNL_SPILL]]
|
||||
** <dt>SQLITE_CONFIG_STMTJRNL_SPILL
|
||||
** <dd>^The SQLITE_CONFIG_STMTJRNL_SPILL option takes a single parameter which
|
||||
** becomes the [statement journal] spill-to-disk threshold.
|
||||
** [Statement journals] are held in memory until their size (in bytes)
|
||||
** exceeds this threshold, at which point they are written to disk.
|
||||
** Or if the threshold is -1, statement journals are always held
|
||||
** exclusively in memory.
|
||||
** Since many statement journals never become large, setting the spill
|
||||
** threshold to a value such as 64KiB can greatly reduce the amount of
|
||||
** I/O required to support statement rollback.
|
||||
** The default value for this setting is controlled by the
|
||||
** [SQLITE_STMTJRNL_SPILL] compile-time option.
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
|
||||
@@ -1825,6 +1861,7 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */
|
||||
#define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */
|
||||
#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */
|
||||
#define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Connection Configuration Options
|
||||
@@ -1882,11 +1919,25 @@ struct sqlite3_mem_methods {
|
||||
** following this call. The second parameter may be a NULL pointer, in
|
||||
** which case the trigger setting is not reported back. </dd>
|
||||
**
|
||||
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
|
||||
** <dd> ^This option is used to enable or disable the two-argument
|
||||
** version of the [fts3_tokenizer()] function which is part of the
|
||||
** [FTS3] full-text search engine extension.
|
||||
** There should be two additional arguments.
|
||||
** The first argument is an integer which is 0 to disable fts3_tokenizer() or
|
||||
** positive to enable fts3_tokenizer() or negative to leave the setting
|
||||
** unchanged.
|
||||
** The second parameter is a pointer to an integer into which
|
||||
** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled
|
||||
** following this call. The second parameter may be a NULL pointer, in
|
||||
** which case the new setting is not reported back. </dd>
|
||||
**
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
|
||||
#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
|
||||
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
|
||||
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
|
||||
#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
|
||||
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
|
||||
#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
|
||||
|
||||
|
||||
/*
|
||||
@@ -4389,8 +4440,8 @@ SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value*);
|
||||
** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer
|
||||
** then sqlite3_value_free(V) is a harmless no-op.
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL sqlite3_value *SQLITE_STDCALL sqlite3_value_dup(const sqlite3_value*);
|
||||
SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_value_free(sqlite3_value*);
|
||||
SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_value_dup(const sqlite3_value*);
|
||||
SQLITE_API void SQLITE_STDCALL sqlite3_value_free(sqlite3_value*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtain Aggregate Function Context
|
||||
@@ -5609,6 +5660,17 @@ struct sqlite3_module {
|
||||
** ^Information about the ORDER BY clause is stored in aOrderBy[].
|
||||
** ^Each term of aOrderBy records a column of the ORDER BY clause.
|
||||
**
|
||||
** The colUsed field indicates which columns of the virtual table may be
|
||||
** required by the current scan. Virtual table columns are numbered from
|
||||
** zero in the order in which they appear within the CREATE TABLE statement
|
||||
** passed to sqlite3_declare_vtab(). For the first 63 columns (columns 0-62),
|
||||
** the corresponding bit is set within the colUsed mask if the column may be
|
||||
** required by SQLite. If the table has at least 64 columns and any column
|
||||
** to the right of the first 63 is required, then bit 63 of colUsed is also
|
||||
** set. In other words, column iCol may be required if the expression
|
||||
** (colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol))) evaluates to
|
||||
** non-zero.
|
||||
**
|
||||
** The [xBestIndex] method must fill aConstraintUsage[] with information
|
||||
** about what parameters to pass to xFilter. ^If argvIndex>0 then
|
||||
** the right-hand side of the corresponding aConstraint[] is evaluated
|
||||
@@ -5664,7 +5726,7 @@ struct sqlite3_index_info {
|
||||
/* Inputs */
|
||||
int nConstraint; /* Number of entries in aConstraint */
|
||||
struct sqlite3_index_constraint {
|
||||
int iColumn; /* Column on left-hand side of constraint */
|
||||
int iColumn; /* Column constrained. -1 for ROWID */
|
||||
unsigned char op; /* Constraint operator */
|
||||
unsigned char usable; /* True if this constraint is usable */
|
||||
int iTermOffset; /* Used internally - xBestIndex should ignore */
|
||||
@@ -5688,6 +5750,8 @@ struct sqlite3_index_info {
|
||||
sqlite3_int64 estimatedRows; /* Estimated number of rows returned */
|
||||
/* Fields below are only available in SQLite 3.9.0 and later */
|
||||
int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */
|
||||
/* Fields below are only available in SQLite 3.10.0 and later */
|
||||
sqlite3_uint64 colUsed; /* Input: Mask of columns used by statement */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -5703,12 +5767,15 @@ struct sqlite3_index_info {
|
||||
** an operator that is part of a constraint term in the wHERE clause of
|
||||
** a query that uses a [virtual table].
|
||||
*/
|
||||
#define SQLITE_INDEX_CONSTRAINT_EQ 2
|
||||
#define SQLITE_INDEX_CONSTRAINT_GT 4
|
||||
#define SQLITE_INDEX_CONSTRAINT_LE 8
|
||||
#define SQLITE_INDEX_CONSTRAINT_LT 16
|
||||
#define SQLITE_INDEX_CONSTRAINT_GE 32
|
||||
#define SQLITE_INDEX_CONSTRAINT_MATCH 64
|
||||
#define SQLITE_INDEX_CONSTRAINT_EQ 2
|
||||
#define SQLITE_INDEX_CONSTRAINT_GT 4
|
||||
#define SQLITE_INDEX_CONSTRAINT_LE 8
|
||||
#define SQLITE_INDEX_CONSTRAINT_LT 16
|
||||
#define SQLITE_INDEX_CONSTRAINT_GE 32
|
||||
#define SQLITE_INDEX_CONSTRAINT_MATCH 64
|
||||
#define SQLITE_INDEX_CONSTRAINT_LIKE 65
|
||||
#define SQLITE_INDEX_CONSTRAINT_GLOB 66
|
||||
#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
|
||||
|
||||
/*
|
||||
** CAPI3REF: Register A Virtual Table Implementation
|
||||
@@ -6572,7 +6639,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_status64(
|
||||
** The value written into the *pCurrent parameter is undefined.</dd>)^
|
||||
**
|
||||
** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
|
||||
** <dd>This parameter records the deepest parser stack. It is only
|
||||
** <dd>The *pHighwater parameter records the deepest parser stack.
|
||||
** The *pCurrent value is undefined. The *pHighwater value is only
|
||||
** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
|
||||
** </dl>
|
||||
**
|
||||
@@ -7358,18 +7426,43 @@ SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *, const char *, int);
|
||||
/*
|
||||
** CAPI3REF: String Globbing
|
||||
*
|
||||
** ^The [sqlite3_strglob(P,X)] interface returns zero if string X matches
|
||||
** the glob pattern P, and it returns non-zero if string X does not match
|
||||
** the glob pattern P. ^The definition of glob pattern matching used in
|
||||
** ^The [sqlite3_strglob(P,X)] interface returns zero if and only if
|
||||
** string X matches the [GLOB] pattern P.
|
||||
** ^The definition of [GLOB] pattern matching used in
|
||||
** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the
|
||||
** SQL dialect used by SQLite. ^The sqlite3_strglob(P,X) function is case
|
||||
** sensitive.
|
||||
** SQL dialect understood by SQLite. ^The [sqlite3_strglob(P,X)] function
|
||||
** is case sensitive.
|
||||
**
|
||||
** Note that this routine returns zero on a match and non-zero if the strings
|
||||
** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()].
|
||||
**
|
||||
** See also: [sqlite3_strlike()].
|
||||
*/
|
||||
SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlob, const char *zStr);
|
||||
|
||||
/*
|
||||
** CAPI3REF: String LIKE Matching
|
||||
*
|
||||
** ^The [sqlite3_strlike(P,X,E)] interface returns zero if and only if
|
||||
** string X matches the [LIKE] pattern P with escape character E.
|
||||
** ^The definition of [LIKE] pattern matching used in
|
||||
** [sqlite3_strlike(P,X,E)] is the same as for the "X LIKE P ESCAPE E"
|
||||
** operator in the SQL dialect understood by SQLite. ^For "X LIKE P" without
|
||||
** the ESCAPE clause, set the E parameter of [sqlite3_strlike(P,X,E)] to 0.
|
||||
** ^As with the LIKE operator, the [sqlite3_strlike(P,X,E)] function is case
|
||||
** insensitive - equivalent upper and lower case ASCII characters match
|
||||
** one another.
|
||||
**
|
||||
** ^The [sqlite3_strlike(P,X,E)] function matches Unicode characters, though
|
||||
** only ASCII characters are case folded.
|
||||
**
|
||||
** Note that this routine returns zero on a match and non-zero if the strings
|
||||
** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()].
|
||||
**
|
||||
** See also: [sqlite3_strglob()].
|
||||
*/
|
||||
SQLITE_API int SQLITE_STDCALL sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Error Logging Interface
|
||||
**
|
||||
@@ -7425,7 +7518,7 @@ SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...)
|
||||
** previously registered write-ahead log callback. ^Note that the
|
||||
** [sqlite3_wal_autocheckpoint()] interface and the
|
||||
** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
|
||||
** those overwrite any prior [sqlite3_wal_hook()] settings.
|
||||
** overwrite any prior [sqlite3_wal_hook()] settings.
|
||||
*/
|
||||
SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook(
|
||||
sqlite3*,
|
||||
@@ -7790,6 +7883,145 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus(
|
||||
*/
|
||||
SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Flush caches to disk mid-transaction
|
||||
**
|
||||
** ^If a write-transaction is open on [database connection] D when the
|
||||
** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
|
||||
** pages in the pager-cache that are not currently in use are written out
|
||||
** to disk. A dirty page may be in use if a database cursor created by an
|
||||
** active SQL statement is reading from it, or if it is page 1 of a database
|
||||
** file (page 1 is always "in use"). ^The [sqlite3_db_cacheflush(D)]
|
||||
** interface flushes caches for all schemas - "main", "temp", and
|
||||
** any [attached] databases.
|
||||
**
|
||||
** ^If this function needs to obtain extra database locks before dirty pages
|
||||
** can be flushed to disk, it does so. ^If those locks cannot be obtained
|
||||
** immediately and there is a busy-handler callback configured, it is invoked
|
||||
** in the usual manner. ^If the required lock still cannot be obtained, then
|
||||
** the database is skipped and an attempt made to flush any dirty pages
|
||||
** belonging to the next (if any) database. ^If any databases are skipped
|
||||
** because locks cannot be obtained, but no other error occurs, this
|
||||
** function returns SQLITE_BUSY.
|
||||
**
|
||||
** ^If any other error occurs while flushing dirty pages to disk (for
|
||||
** example an IO error or out-of-memory condition), then processing is
|
||||
** abandoned and an SQLite [error code] is returned to the caller immediately.
|
||||
**
|
||||
** ^Otherwise, if no error occurs, [sqlite3_db_cacheflush()] returns SQLITE_OK.
|
||||
**
|
||||
** ^This function does not set the database handle error code or message
|
||||
** returned by the [sqlite3_errcode()] and [sqlite3_errmsg()] functions.
|
||||
*/
|
||||
SQLITE_API int SQLITE_STDCALL sqlite3_db_cacheflush(sqlite3*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Low-level system error code
|
||||
**
|
||||
** ^Attempt to return the underlying operating system error code or error
|
||||
** number that caused the most reason I/O error or failure to open a file.
|
||||
** The return value is OS-dependent. For example, on unix systems, after
|
||||
** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be
|
||||
** called to get back the underlying "errno" that caused the problem, such
|
||||
** as ENOSPC, EAUTH, EISDIR, and so forth.
|
||||
*/
|
||||
SQLITE_API int SQLITE_STDCALL sqlite3_system_errno(sqlite3*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Snapshot
|
||||
** KEYWORDS: {snapshot}
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** An instance of the snapshot object records the state of a [WAL mode]
|
||||
** database for some specific point in history.
|
||||
**
|
||||
** In [WAL mode], multiple [database connections] that are open on the
|
||||
** same database file can each be reading a different historical version
|
||||
** of the database file. When a [database connection] begins a read
|
||||
** transaction, that connection sees an unchanging copy of the database
|
||||
** as it existed for the point in time when the transaction first started.
|
||||
** Subsequent changes to the database from other connections are not seen
|
||||
** by the reader until a new read transaction is started.
|
||||
**
|
||||
** The sqlite3_snapshot object records state information about an historical
|
||||
** version of the database file so that it is possible to later open a new read
|
||||
** transaction that sees that historical version of the database rather than
|
||||
** the most recent version.
|
||||
**
|
||||
** The constructor for this object is [sqlite3_snapshot_get()]. The
|
||||
** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer
|
||||
** to an historical snapshot (if possible). The destructor for
|
||||
** sqlite3_snapshot objects is [sqlite3_snapshot_free()].
|
||||
*/
|
||||
typedef struct sqlite3_snapshot sqlite3_snapshot;
|
||||
|
||||
/*
|
||||
** CAPI3REF: Record A Database Snapshot
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a
|
||||
** new [sqlite3_snapshot] object that records the current state of
|
||||
** schema S in database connection D. ^On success, the
|
||||
** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly
|
||||
** created [sqlite3_snapshot] object into *P and returns SQLITE_OK.
|
||||
** ^If schema S of [database connection] D is not a [WAL mode] database
|
||||
** that is in a read transaction, then [sqlite3_snapshot_get(D,S,P)]
|
||||
** leaves the *P value unchanged and returns an appropriate [error code].
|
||||
**
|
||||
** The [sqlite3_snapshot] object returned from a successful call to
|
||||
** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()]
|
||||
** to avoid a memory leak.
|
||||
**
|
||||
** The [sqlite3_snapshot_get()] interface is only available when the
|
||||
** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_get(
|
||||
sqlite3 *db,
|
||||
const char *zSchema,
|
||||
sqlite3_snapshot **ppSnapshot
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Start a read transaction on an historical snapshot
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^The [sqlite3_snapshot_open(D,S,P)] interface attempts to move the
|
||||
** read transaction that is currently open on schema S of
|
||||
** [database connection] D so that it refers to historical [snapshot] P.
|
||||
** ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK on success
|
||||
** or an appropriate [error code] if it fails.
|
||||
**
|
||||
** ^In order to succeed, a call to [sqlite3_snapshot_open(D,S,P)] must be
|
||||
** the first operation, apart from other sqlite3_snapshot_open() calls,
|
||||
** following the [BEGIN] that starts a new read transaction.
|
||||
** ^A [snapshot] will fail to open if it has been overwritten by a
|
||||
** [checkpoint].
|
||||
** ^A [snapshot] will fail to open if the database connection D has not
|
||||
** previously completed at least one read operation against the database
|
||||
** file. (Hint: Run "[PRAGMA application_id]" against a newly opened
|
||||
** database connection in order to make it ready to use snapshots.)
|
||||
**
|
||||
** The [sqlite3_snapshot_open()] interface is only available when the
|
||||
** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_open(
|
||||
sqlite3 *db,
|
||||
const char *zSchema,
|
||||
sqlite3_snapshot *pSnapshot
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Destroy a snapshot
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P.
|
||||
** The application must eventually free every [sqlite3_snapshot] object
|
||||
** using this routine to avoid a memory leak.
|
||||
**
|
||||
** The [sqlite3_snapshot_free()] interface is only available when the
|
||||
** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_snapshot_free(sqlite3_snapshot*);
|
||||
|
||||
/*
|
||||
** Undo the hack that converts floating point types to integer for
|
||||
@@ -8006,6 +8238,9 @@ struct Fts5PhraseIter {
|
||||
** an OOM condition or IO error), an appropriate SQLite error code is
|
||||
** returned.
|
||||
**
|
||||
** This function may be quite inefficient if used with an FTS5 table
|
||||
** created with the "columnsize=0" option.
|
||||
**
|
||||
** xColumnText:
|
||||
** This function attempts to retrieve the text of column iCol of the
|
||||
** current document. If successful, (*pz) is set to point to a buffer
|
||||
@@ -8026,15 +8261,29 @@ struct Fts5PhraseIter {
|
||||
** the query within the current row. Return SQLITE_OK if successful, or
|
||||
** an error code (i.e. SQLITE_NOMEM) if an error occurs.
|
||||
**
|
||||
** This API can be quite slow if used with an FTS5 table created with the
|
||||
** "detail=none" or "detail=column" option. If the FTS5 table is created
|
||||
** with either "detail=none" or "detail=column" and "content=" option
|
||||
** (i.e. if it is a contentless table), then this API always returns 0.
|
||||
**
|
||||
** xInst:
|
||||
** Query for the details of phrase match iIdx within the current row.
|
||||
** Phrase matches are numbered starting from zero, so the iIdx argument
|
||||
** should be greater than or equal to zero and smaller than the value
|
||||
** output by xInstCount().
|
||||
**
|
||||
** Usually, output parameter *piPhrase is set to the phrase number, *piCol
|
||||
** to the column in which it occurs and *piOff the token offset of the
|
||||
** first token of the phrase. The exception is if the table was created
|
||||
** with the offsets=0 option specified. In this case *piOff is always
|
||||
** set to -1.
|
||||
**
|
||||
** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
|
||||
** if an error occurs.
|
||||
**
|
||||
** This API can be quite slow if used with an FTS5 table created with the
|
||||
** "detail=none" or "detail=column" option.
|
||||
**
|
||||
** xRowid:
|
||||
** Returns the rowid of the current row.
|
||||
**
|
||||
@@ -8118,7 +8367,7 @@ struct Fts5PhraseIter {
|
||||
** Fts5PhraseIter iter;
|
||||
** int iCol, iOff;
|
||||
** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff);
|
||||
** iOff>=0;
|
||||
** iCol>=0;
|
||||
** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
|
||||
** ){
|
||||
** // An instance of phrase iPhrase at offset iOff of column iCol
|
||||
@@ -8126,13 +8375,51 @@ struct Fts5PhraseIter {
|
||||
**
|
||||
** The Fts5PhraseIter structure is defined above. Applications should not
|
||||
** modify this structure directly - it should only be used as shown above
|
||||
** with the xPhraseFirst() and xPhraseNext() API methods.
|
||||
** with the xPhraseFirst() and xPhraseNext() API methods (and by
|
||||
** xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below).
|
||||
**
|
||||
** This API can be quite slow if used with an FTS5 table created with the
|
||||
** "detail=none" or "detail=column" option. If the FTS5 table is created
|
||||
** with either "detail=none" or "detail=column" and "content=" option
|
||||
** (i.e. if it is a contentless table), then this API always iterates
|
||||
** through an empty set (all calls to xPhraseFirst() set iCol to -1).
|
||||
**
|
||||
** xPhraseNext()
|
||||
** See xPhraseFirst above.
|
||||
**
|
||||
** xPhraseFirstColumn()
|
||||
** This function and xPhraseNextColumn() are similar to the xPhraseFirst()
|
||||
** and xPhraseNext() APIs described above. The difference is that instead
|
||||
** of iterating through all instances of a phrase in the current row, these
|
||||
** APIs are used to iterate through the set of columns in the current row
|
||||
** that contain one or more instances of a specified phrase. For example:
|
||||
**
|
||||
** Fts5PhraseIter iter;
|
||||
** int iCol;
|
||||
** for(pApi->xPhraseFirstColumn(pFts, iPhrase, &iter, &iCol);
|
||||
** iCol>=0;
|
||||
** pApi->xPhraseNextColumn(pFts, &iter, &iCol)
|
||||
** ){
|
||||
** // Column iCol contains at least one instance of phrase iPhrase
|
||||
** }
|
||||
**
|
||||
** This API can be quite slow if used with an FTS5 table created with the
|
||||
** "detail=none" option. If the FTS5 table is created with either
|
||||
** "detail=none" "content=" option (i.e. if it is a contentless table),
|
||||
** then this API always iterates through an empty set (all calls to
|
||||
** xPhraseFirstColumn() set iCol to -1).
|
||||
**
|
||||
** The information accessed using this API and its companion
|
||||
** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
|
||||
** (or xInst/xInstCount). The chief advantage of this API is that it is
|
||||
** significantly more efficient than those alternatives when used with
|
||||
** "detail=column" tables.
|
||||
**
|
||||
** xPhraseNextColumn()
|
||||
** See xPhraseFirstColumn above.
|
||||
*/
|
||||
struct Fts5ExtensionApi {
|
||||
int iVersion; /* Currently always set to 1 */
|
||||
int iVersion; /* Currently always set to 3 */
|
||||
|
||||
void *(*xUserData)(Fts5Context*);
|
||||
|
||||
@@ -8162,8 +8449,11 @@ struct Fts5ExtensionApi {
|
||||
int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
|
||||
void *(*xGetAuxdata)(Fts5Context*, int bClear);
|
||||
|
||||
void (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
|
||||
int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
|
||||
void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
|
||||
|
||||
int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
|
||||
void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -5,10 +5,32 @@ set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
||||
|
||||
set(synclib_NAME ${APPLICATION_EXECUTABLE}sync)
|
||||
|
||||
include(QtVersionAbstraction)
|
||||
setup_qt()
|
||||
if(HAVE_QT5 AND NOT BUILD_WITH_QT4)
|
||||
if (${Qt5Core_VERSION_MAJOR} EQUAL "5")
|
||||
if (${Qt5Core_VERSION_MINOR} EQUAL "4" OR ${Qt5Core_VERSION_MINOR} GREATER 4)
|
||||
else()
|
||||
message(STATUS "If possible compile me with Qt 5.4 or higher.")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "If possible compile me with Qt 5.4 or higher.")
|
||||
endif()
|
||||
|
||||
|
||||
if (APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
endif()
|
||||
|
||||
if(NOT TOKEN_AUTH_ONLY)
|
||||
if (Qt5Core_DIR)
|
||||
find_package(Qt5Keychain REQUIRED)
|
||||
else()
|
||||
find_package(QtKeychain REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(libsync)
|
||||
if (NOT BUILD_LIBRARIES_ONLY)
|
||||
add_subdirectory(gui)
|
||||
|
||||
@@ -17,6 +17,9 @@ include_directories(${CMAKE_SOURCE_DIR}/csync/src
|
||||
${CMAKE_BINARY_DIR}/csync/src
|
||||
)
|
||||
|
||||
# Need tokenizer for netrc parser
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src/3rdparty/qtokenizer)
|
||||
|
||||
if(NOT BUILD_LIBRARIES_ONLY)
|
||||
add_executable(${cmd_NAME} ${cmd_SRC})
|
||||
qt5_use_modules(${cmd_NAME} Network Sql)
|
||||
|
||||
@@ -153,7 +153,7 @@ void help()
|
||||
std::cout << " Proxy is http://server:port" << std::endl;
|
||||
std::cout << " --trust Trust the SSL certification." << std::endl;
|
||||
std::cout << " --exclude [file] Exclude list file" << std::endl;
|
||||
std::cout << " --unsyncedfolders [file] File containing the list of unsynced folders (selective sync)" << std::endl;
|
||||
std::cout << " --unsyncedfolders [file] File containing the list of unsynced remote folders (selective sync)" << std::endl;
|
||||
std::cout << " --user, -u [name] Use [name] as the login name" << std::endl;
|
||||
std::cout << " --password, -p [pass] Use [pass] as password" << std::endl;
|
||||
std::cout << " -n Use netrc (5) for login" << std::endl;
|
||||
@@ -249,23 +249,23 @@ void parseOptions( const QStringList& app_args, CmdOptions *options )
|
||||
*/
|
||||
void selectiveSyncFixup(OCC::SyncJournalDb *journal, const QStringList &newList)
|
||||
{
|
||||
if (!journal->exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SqlDatabase db;
|
||||
if (!db.openOrCreateReadWrite(journal->databaseFilePath())) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto oldBlackListSet = journal->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList).toSet();
|
||||
auto blackListSet = newList.toSet();
|
||||
auto changes = (oldBlackListSet - blackListSet) + (blackListSet - oldBlackListSet);
|
||||
foreach(const auto &it, changes) {
|
||||
journal->avoidReadFromDbOnNextSync(it);
|
||||
}
|
||||
bool ok;
|
||||
|
||||
journal->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, newList);
|
||||
auto oldBlackListSet = journal->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok).toSet();
|
||||
if( ok ) {
|
||||
auto blackListSet = newList.toSet();
|
||||
auto changes = (oldBlackListSet - blackListSet) + (blackListSet - oldBlackListSet);
|
||||
foreach(const auto &it, changes) {
|
||||
journal->avoidReadFromDbOnNextSync(it);
|
||||
}
|
||||
|
||||
journal->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, newList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -385,26 +385,10 @@ int main(int argc, char **argv) {
|
||||
int restartCount = 0;
|
||||
restart_sync:
|
||||
|
||||
CSYNC *_csync_ctx;
|
||||
|
||||
if( csync_create( &_csync_ctx, options.source_dir.toUtf8(),
|
||||
remUrl.constData()) < 0 ) {
|
||||
qFatal("Unable to create csync-context!");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
csync_set_log_level(options.silent ? 1 : 11);
|
||||
|
||||
opts = &options;
|
||||
|
||||
if( csync_init( _csync_ctx ) < 0 ) {
|
||||
qFatal("Could not initialize csync!");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// ignore hidden files or not
|
||||
_csync_ctx->ignore_hidden_files = options.ignoreHiddenFiles;
|
||||
|
||||
if( !options.proxy.isNull() ) {
|
||||
QString host;
|
||||
int port = 0;
|
||||
@@ -431,18 +415,6 @@ restart_sync:
|
||||
}
|
||||
}
|
||||
|
||||
// Exclude lists
|
||||
QString systemExcludeListFn = ConfigFile::excludeFileFromSystem();
|
||||
int loadedSystemExcludeList = false;
|
||||
if (!systemExcludeListFn.isEmpty()) {
|
||||
loadedSystemExcludeList = csync_add_exclude_list(_csync_ctx, systemExcludeListFn.toLocal8Bit());
|
||||
}
|
||||
|
||||
int loadedUserExcludeList = false;
|
||||
if (!options.exclude.isEmpty()) {
|
||||
loadedUserExcludeList = csync_add_exclude_list(_csync_ctx, options.exclude.toLocal8Bit());
|
||||
}
|
||||
|
||||
QStringList selectiveSyncList;
|
||||
if (!options.unsyncedfolders.isEmpty()) {
|
||||
QFile f(options.unsyncedfolders);
|
||||
@@ -460,30 +432,32 @@ restart_sync:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (loadedSystemExcludeList != 0 && loadedUserExcludeList != 0) {
|
||||
// Always make sure at least one list has been loaded
|
||||
qFatal("Cannot load system exclude list or list supplied via --exclude");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Cmd cmd;
|
||||
SyncJournalDb db(options.source_dir);
|
||||
if (!selectiveSyncList.empty()) {
|
||||
selectiveSyncFixup(&db, selectiveSyncList);
|
||||
}
|
||||
|
||||
SyncEngine engine(account, _csync_ctx, options.source_dir, QUrl(options.target_url).path(), folder, &db);
|
||||
SyncEngine engine(account, options.source_dir, QUrl(options.target_url), folder, &db);
|
||||
engine.setIgnoreHiddenFiles(options.ignoreHiddenFiles);
|
||||
QObject::connect(&engine, SIGNAL(finished(bool)), &app, SLOT(quit()));
|
||||
QObject::connect(&engine, SIGNAL(transmissionProgress(ProgressInfo)), &cmd, SLOT(transmissionProgressSlot()));
|
||||
|
||||
// Exclude lists
|
||||
engine.excludedFiles().addExcludeFilePath(ConfigFile::excludeFileFromSystem());
|
||||
if( QFile::exists(options.exclude) )
|
||||
engine.excludedFiles().addExcludeFilePath(options.exclude);
|
||||
if (!engine.excludedFiles().reloadExcludes()) {
|
||||
// Always make sure at least one list has been loaded
|
||||
qFatal("Cannot load system exclude list or list supplied via --exclude");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Have to be done async, else, an error before exec() does not terminate the event loop.
|
||||
QMetaObject::invokeMethod(&engine, "startSync", Qt::QueuedConnection);
|
||||
|
||||
app.exec();
|
||||
|
||||
csync_destroy(_csync_ctx);
|
||||
|
||||
if (engine.isAnotherSyncNeeded()) {
|
||||
if (restartCount < options.restartTimes) {
|
||||
restartCount++;
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
|
||||
#include <qtokenizer.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "netrcparser.h"
|
||||
|
||||
namespace OCC {
|
||||
@@ -28,11 +32,11 @@ QString passwordKeyword = QLatin1String("password");
|
||||
|
||||
}
|
||||
|
||||
NetrcParser::NetrcParser(const QString &fileName)
|
||||
: _fileName(fileName)
|
||||
NetrcParser::NetrcParser(const QString &file)
|
||||
{
|
||||
if (_fileName.isEmpty()) {
|
||||
_fileName = QDir::homePath()+QLatin1String("/.netrc");
|
||||
_netrcLocation = file;
|
||||
if (_netrcLocation.isEmpty()) {
|
||||
_netrcLocation = QDir::homePath()+QLatin1String("/.netrc");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,29 +53,39 @@ void NetrcParser::tryAddEntryAndClear(QString& machine, LoginPair& pair, bool& i
|
||||
|
||||
bool NetrcParser::parse()
|
||||
{
|
||||
QFile netrc(_fileName);
|
||||
QFile netrc(_netrcLocation);
|
||||
if (!netrc.open(QIODevice::ReadOnly)) {
|
||||
return false;
|
||||
}
|
||||
QString content = netrc.readAll();
|
||||
|
||||
QStringTokenizer tokenizer(content, " \n\t");
|
||||
tokenizer.setQuoteCharacters("\"'");
|
||||
|
||||
QTextStream ts(&netrc);
|
||||
LoginPair pair;
|
||||
QString machine;
|
||||
bool isDefault = false;
|
||||
while (!ts.atEnd()) {
|
||||
QString next;
|
||||
ts >> next;
|
||||
if (next == defaultKeyword) {
|
||||
while (tokenizer.hasNext()) {
|
||||
QString key = tokenizer.next();
|
||||
if (key == defaultKeyword) {
|
||||
tryAddEntryAndClear(machine, pair, isDefault);
|
||||
isDefault = true;
|
||||
continue; // don't read a value
|
||||
}
|
||||
if (next == machineKeyword) {
|
||||
|
||||
if (!tokenizer.hasNext()) {
|
||||
qDebug() << "error fetching value for" << key;
|
||||
return false;
|
||||
}
|
||||
QString value = tokenizer.next();
|
||||
|
||||
if (key == machineKeyword) {
|
||||
tryAddEntryAndClear(machine, pair, isDefault);
|
||||
ts >> machine;
|
||||
} else if (next == loginKeyword) {
|
||||
ts >> pair.first;
|
||||
} else if (next == passwordKeyword) {
|
||||
ts >> pair.second;
|
||||
machine = value;
|
||||
} else if (key == loginKeyword) {
|
||||
pair.first = value;
|
||||
} else if (key == passwordKeyword) {
|
||||
pair.second = value;
|
||||
} // ignore unsupported tokens
|
||||
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ class NetrcParser
|
||||
public:
|
||||
typedef QPair<QString, QString> LoginPair;
|
||||
|
||||
NetrcParser(const QString &fileName = QString::null);
|
||||
NetrcParser(const QString &file = QString());
|
||||
bool parse();
|
||||
LoginPair find(const QString &machine);
|
||||
|
||||
@@ -37,7 +37,7 @@ private:
|
||||
void tryAddEntryAndClear(QString &machine, LoginPair &pair, bool &isDefault);
|
||||
QHash<QString, LoginPair> _entries;
|
||||
LoginPair _default;
|
||||
QString _fileName;
|
||||
QString _netrcLocation;
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -32,6 +32,7 @@ set(client_UI
|
||||
owncloudsetuppage.ui
|
||||
addcertificatedialog.ui
|
||||
proxyauthdialog.ui
|
||||
notificationwidget.ui
|
||||
wizard/owncloudadvancedsetuppage.ui
|
||||
wizard/owncloudconnectionmethoddialog.ui
|
||||
wizard/owncloudhttpcredspage.ui
|
||||
@@ -53,6 +54,7 @@ set(client_SRCS
|
||||
folderwizard.cpp
|
||||
generalsettings.cpp
|
||||
ignorelisteditor.cpp
|
||||
lockwatcher.cpp
|
||||
logbrowser.cpp
|
||||
networksettings.cpp
|
||||
ocsjob.cpp
|
||||
@@ -62,6 +64,8 @@ set(client_SRCS
|
||||
owncloudgui.cpp
|
||||
owncloudsetupwizard.cpp
|
||||
protocolwidget.cpp
|
||||
activitydata.cpp
|
||||
activitylistmodel.cpp
|
||||
activitywidget.cpp
|
||||
activityitemdelegate.cpp
|
||||
selectivesyncdialog.cpp
|
||||
@@ -84,11 +88,16 @@ set(client_SRCS
|
||||
proxyauthhandler.cpp
|
||||
proxyauthdialog.cpp
|
||||
synclogdialog.cpp
|
||||
tooltipupdater.cpp
|
||||
notificationwidget.cpp
|
||||
notificationconfirmjob.cpp
|
||||
servernotificationhandler.cpp
|
||||
creds/credentialsfactory.cpp
|
||||
creds/httpcredentialsgui.cpp
|
||||
creds/shibbolethcredentials.cpp
|
||||
creds/shibboleth/shibbolethwebview.cpp
|
||||
creds/shibboleth/shibbolethuserjob.cpp
|
||||
wizard/postfixlineedit.cpp
|
||||
wizard/abstractcredswizardpage.cpp
|
||||
wizard/owncloudadvancedsetuppage.cpp
|
||||
wizard/owncloudconnectionmethoddialog.cpp
|
||||
@@ -133,7 +142,6 @@ list(APPEND client_SRCS folderwatcher_mac.cpp)
|
||||
ENDIF()
|
||||
|
||||
set(3rdparty_SRC
|
||||
../3rdparty/fancylineedit/fancylineedit.cpp
|
||||
../3rdparty/QProgressIndicator/QProgressIndicator.cpp
|
||||
../3rdparty/qtlockedfile/qtlockedfile.cpp
|
||||
../3rdparty/qtsingleapplication/qtlocalpeer.cpp
|
||||
@@ -157,7 +165,6 @@ else()
|
||||
endif()
|
||||
|
||||
set(3rdparty_INC
|
||||
${CMAKE_SOURCE_DIR}/src/3rdparty/fancylineedit
|
||||
${CMAKE_SOURCE_DIR}/src/3rdparty/qjson
|
||||
${CMAKE_SOURCE_DIR}/src/3rdparty/QProgressIndicator
|
||||
${CMAKE_SOURCE_DIR}/src/3rdparty/qtlockedfile
|
||||
|
||||
@@ -30,6 +30,7 @@ static const char httpUserC[] = "http_user";
|
||||
static const char caCertsKeyC[] = "CaCertificates";
|
||||
static const char accountsC[] = "Accounts";
|
||||
static const char versionC[] = "version";
|
||||
static const char serverVersionC[] = "serverVersion";
|
||||
}
|
||||
|
||||
|
||||
@@ -53,9 +54,11 @@ bool AccountManager::restore()
|
||||
|
||||
foreach (const auto& accountId, settings->childGroups()) {
|
||||
settings->beginGroup(accountId);
|
||||
if (auto acc = load(*settings)) {
|
||||
if (auto acc = loadAccountHelper(*settings)) {
|
||||
acc->_id = accountId;
|
||||
addAccount(acc);
|
||||
if (auto accState = AccountState::loadFromSettings(acc, *settings)) {
|
||||
addAccountState(accState);
|
||||
}
|
||||
}
|
||||
settings->endGroup();
|
||||
}
|
||||
@@ -110,7 +113,7 @@ bool AccountManager::restoreFromLegacySettings()
|
||||
|
||||
// Try to load the single account.
|
||||
if (!settings->childKeys().isEmpty()) {
|
||||
if (auto acc = load(*settings)) {
|
||||
if (auto acc = loadAccountHelper(*settings)) {
|
||||
if (migratedCreds) {
|
||||
acc->setMigrated(true);
|
||||
}
|
||||
@@ -127,7 +130,8 @@ void AccountManager::save(bool saveCredentials)
|
||||
settings->setValue(QLatin1String(versionC), 2);
|
||||
foreach (const auto &acc, _accounts) {
|
||||
settings->beginGroup(acc->account()->id());
|
||||
save(acc->account(), *settings, saveCredentials);
|
||||
saveAccountHelper(acc->account().data(), *settings, saveCredentials);
|
||||
acc->writeToSettings(*settings);
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
@@ -135,21 +139,34 @@ void AccountManager::save(bool saveCredentials)
|
||||
qDebug() << "Saved all account settings, status:" << settings->status();
|
||||
}
|
||||
|
||||
void AccountManager::wantsAccountSavedSlot(AccountPtr a)
|
||||
void AccountManager::saveAccount(Account* a)
|
||||
{
|
||||
qDebug() << "Saving account" << a->url().toString();
|
||||
auto settings = Account::settingsWithGroup(QLatin1String(accountsC));
|
||||
settings->beginGroup(a->id());
|
||||
save(a, *settings, false); // don't save credentials they might not have been loaded yet
|
||||
saveAccountHelper(a, *settings, false); // don't save credentials they might not have been loaded yet
|
||||
settings->endGroup();
|
||||
|
||||
settings->sync();
|
||||
qDebug() << "Saved account settings, status:" << settings->status();
|
||||
}
|
||||
|
||||
void AccountManager::save(const AccountPtr& acc, QSettings& settings, bool saveCredentials)
|
||||
void AccountManager::saveAccountState(AccountState* a)
|
||||
{
|
||||
qDebug() << "Saving account state" << a->account()->url().toString();
|
||||
auto settings = Account::settingsWithGroup(QLatin1String(accountsC));
|
||||
settings->beginGroup(a->account()->id());
|
||||
a->writeToSettings(*settings);
|
||||
settings->endGroup();
|
||||
|
||||
settings->sync();
|
||||
qDebug() << "Saved account state settings, status:" << settings->status();
|
||||
}
|
||||
|
||||
void AccountManager::saveAccountHelper(Account* acc, QSettings& settings, bool saveCredentials)
|
||||
{
|
||||
settings.setValue(QLatin1String(urlC), acc->_url.toString());
|
||||
settings.setValue(QLatin1String(serverVersionC), acc->_serverVersion);
|
||||
if (acc->_credentials) {
|
||||
if (saveCredentials) {
|
||||
// Only persist the credentials if the parameter is set, on migration from 1.8.x
|
||||
@@ -190,22 +207,35 @@ void AccountManager::save(const AccountPtr& acc, QSettings& settings, bool saveC
|
||||
}
|
||||
}
|
||||
|
||||
AccountPtr AccountManager::load(QSettings& settings)
|
||||
AccountPtr AccountManager::loadAccountHelper(QSettings& settings)
|
||||
{
|
||||
auto acc = createAccount();
|
||||
|
||||
acc->setUrl(settings.value(QLatin1String(urlC)).toUrl());
|
||||
QString authType = settings.value(QLatin1String(authTypeC)).toString();
|
||||
QString overrideUrl = Theme::instance()->overrideServerUrl();
|
||||
if( !overrideUrl.isEmpty() ) {
|
||||
// if there is a overrideUrl, don't even bother reading from the config as all the accounts
|
||||
// must use the overrideUrl
|
||||
acc->setUrl(overrideUrl);
|
||||
auto forceAuth = Theme::instance()->forceConfigAuthType();
|
||||
if (!forceAuth.isEmpty()) {
|
||||
authType = forceAuth;
|
||||
}
|
||||
} else {
|
||||
acc->setUrl(settings.value(QLatin1String(urlC)).toUrl());
|
||||
}
|
||||
acc->_serverVersion = settings.value(QLatin1String(serverVersionC)).toString();
|
||||
|
||||
// We want to only restore settings for that auth type and the user value
|
||||
acc->_settingsMap.insert(QLatin1String(userC), settings.value(userC));
|
||||
QString authTypePrefix = settings.value(authTypeC).toString() + "_";
|
||||
QString authTypePrefix = authType + "_";
|
||||
Q_FOREACH(QString key, settings.childKeys()) {
|
||||
if (!key.startsWith(authTypePrefix))
|
||||
continue;
|
||||
acc->_settingsMap.insert(key, settings.value(key));
|
||||
}
|
||||
|
||||
acc->setCredentials(CredentialsFactory::create(settings.value(QLatin1String(authTypeC)).toString()));
|
||||
acc->setCredentials(CredentialsFactory::create(authType));
|
||||
|
||||
// now the cert, it is in the general group
|
||||
settings.beginGroup(QLatin1String("General"));
|
||||
@@ -233,13 +263,9 @@ AccountState *AccountManager::addAccount(const AccountPtr& newAccount)
|
||||
}
|
||||
newAccount->_id = id;
|
||||
|
||||
QObject::connect(newAccount.data(), SIGNAL(wantsAccountSaved(AccountPtr)),
|
||||
this, SLOT(wantsAccountSavedSlot(AccountPtr)));
|
||||
|
||||
AccountStatePtr newAccountState(new AccountState(newAccount));
|
||||
_accounts << newAccountState;
|
||||
emit accountAdded(newAccountState.data());
|
||||
return newAccountState.data();
|
||||
auto newAccountState = new AccountState(newAccount);
|
||||
addAccountState(newAccountState);
|
||||
return newAccountState;
|
||||
}
|
||||
|
||||
void AccountManager::deleteAccount(AccountState* account)
|
||||
@@ -296,4 +322,15 @@ QString AccountManager::generateFreeAccountId() const
|
||||
}
|
||||
}
|
||||
|
||||
void AccountManager::addAccountState(AccountState* accountState)
|
||||
{
|
||||
QObject::connect(accountState->account().data(),
|
||||
SIGNAL(wantsAccountSaved(Account*)),
|
||||
SLOT(saveAccount(Account*)));
|
||||
|
||||
AccountStatePtr ptr(accountState);
|
||||
_accounts << ptr;
|
||||
emit accountAdded(accountState);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
|
||||
namespace OCC {
|
||||
|
||||
typedef QSharedPointer<AccountState> AccountStatePtr;
|
||||
|
||||
/**
|
||||
@brief The AccountManager class
|
||||
@ingroup gui
|
||||
@@ -76,15 +74,24 @@ public:
|
||||
static AccountPtr createAccount();
|
||||
|
||||
private:
|
||||
void save(const AccountPtr& account, QSettings& settings, bool saveCredentials = true);
|
||||
AccountPtr load(QSettings& settings);
|
||||
// saving and loading Account to settings
|
||||
void saveAccountHelper(Account* account, QSettings& settings, bool saveCredentials = true);
|
||||
AccountPtr loadAccountHelper(QSettings& settings);
|
||||
|
||||
bool restoreFromLegacySettings();
|
||||
|
||||
bool isAccountIdAvailable(const QString& id) const;
|
||||
QString generateFreeAccountId() const;
|
||||
|
||||
// Adds an account to the tracked list, emitting accountAdded()
|
||||
void addAccountState(AccountState* accountState);
|
||||
|
||||
public slots:
|
||||
void wantsAccountSavedSlot(AccountPtr a);
|
||||
/// Saves account data, not including the credentials
|
||||
void saveAccount(Account* a);
|
||||
|
||||
/// Saves account state data, not including the account
|
||||
void saveAccountState(AccountState* a);
|
||||
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
@@ -29,11 +29,13 @@
|
||||
#include "accountmanager.h"
|
||||
#include "owncloudsetupwizard.h"
|
||||
#include "creds/abstractcredentials.h"
|
||||
#include "tooltipupdater.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDesktopServices>
|
||||
#include <QDir>
|
||||
#include <QListWidgetItem>
|
||||
#include <QMessageBox>
|
||||
#include <QAction>
|
||||
@@ -87,6 +89,8 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent) :
|
||||
#else
|
||||
ui->_folderList->setMinimumWidth( 300 );
|
||||
#endif
|
||||
new ToolTipUpdater(ui->_folderList);
|
||||
|
||||
createAccountToolbox();
|
||||
connect(AccountManager::instance(), SIGNAL(accountAdded(AccountState*)),
|
||||
SLOT(slotAccountAdded(AccountState*)));
|
||||
@@ -103,11 +107,6 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent) :
|
||||
connect(_model, SIGNAL(rowsInserted(QModelIndex,int,int)),
|
||||
this, SLOT(refreshSelectiveSyncStatus()));
|
||||
|
||||
QAction *resetFolderAction = new QAction(this);
|
||||
resetFolderAction->setShortcut(QKeySequence(Qt::Key_F5));
|
||||
connect(resetFolderAction, SIGNAL(triggered()), SLOT(slotResetCurrentFolder()));
|
||||
addAction(resetFolderAction);
|
||||
|
||||
QAction *syncNowAction = new QAction(this);
|
||||
syncNowAction->setShortcut(QKeySequence(Qt::Key_F6));
|
||||
connect(syncNowAction, SIGNAL(triggered()), SLOT(slotSyncCurrentFolderNow()));
|
||||
@@ -198,8 +197,7 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
|
||||
return;
|
||||
}
|
||||
|
||||
QString alias = _model->data( index, FolderStatusDelegate::FolderAliasRole ).toString();
|
||||
if (alias.isEmpty()) {
|
||||
if (_model->classify(index) != FolderStatusModel::RootFolder) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -213,9 +211,11 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
|
||||
QAction *ac = menu->addAction(tr("Open folder"));
|
||||
connect(ac, SIGNAL(triggered(bool)), this, SLOT(slotOpenCurrentFolder()));
|
||||
|
||||
ac = menu->addAction(tr("Choose what to sync"));
|
||||
ac->setEnabled(folderConnected);
|
||||
connect(ac, SIGNAL(triggered(bool)), this, SLOT(doExpand()));
|
||||
if (!ui->_folderList->isExpanded(index)) {
|
||||
ac = menu->addAction(tr("Choose what to sync"));
|
||||
ac->setEnabled(folderConnected);
|
||||
connect(ac, SIGNAL(triggered(bool)), this, SLOT(doExpand()));
|
||||
}
|
||||
|
||||
ac = menu->addAction(folderPaused ? tr("Resume sync") : tr("Pause sync"));
|
||||
connect(ac, SIGNAL(triggered(bool)), this, SLOT(slotEnableCurrentFolder()));
|
||||
@@ -276,7 +276,6 @@ void AccountSettings::slotFolderWizardAccepted()
|
||||
qDebug() << "* Folder wizard completed";
|
||||
|
||||
FolderDefinition definition;
|
||||
definition.alias = folderWizard->field(QLatin1String("alias")).toString();
|
||||
definition.localPath = FolderDefinition::prepareLocalPath(
|
||||
folderWizard->field(QLatin1String("sourceFolder")).toString());
|
||||
definition.targetPath = folderWizard->property("targetPath").toString();
|
||||
@@ -333,10 +332,13 @@ void AccountSettings::slotRemoveCurrentFolder()
|
||||
QString alias = _model->data( selected, FolderStatusDelegate::FolderAliasRole ).toString();
|
||||
qDebug() << "Remove Folder alias " << alias;
|
||||
if( !alias.isEmpty() ) {
|
||||
FolderMan *folderMan = FolderMan::instance();
|
||||
QString shortGuiLocalPath = folderMan->folder(alias)->shortGuiLocalPath();
|
||||
|
||||
QMessageBox messageBox(QMessageBox::Question,
|
||||
tr("Confirm Folder Sync Connection Removal"),
|
||||
tr("<p>Do you really want to stop syncing the folder <i>%1</i>?</p>"
|
||||
"<p><b>Note:</b> This will <b>not</b> delete any files.</p>").arg(alias),
|
||||
"<p><b>Note:</b> This will <b>not</b> delete any files.</p>").arg(shortGuiLocalPath),
|
||||
QMessageBox::NoButton,
|
||||
this);
|
||||
QPushButton* yesButton =
|
||||
@@ -348,7 +350,6 @@ void AccountSettings::slotRemoveCurrentFolder()
|
||||
return;
|
||||
}
|
||||
|
||||
FolderMan *folderMan = FolderMan::instance();
|
||||
folderMan->slotRemoveFolder( folderMan->folder(alias) );
|
||||
_model->removeRow(row);
|
||||
|
||||
@@ -359,31 +360,6 @@ void AccountSettings::slotRemoveCurrentFolder()
|
||||
}
|
||||
}
|
||||
|
||||
void AccountSettings::slotResetCurrentFolder()
|
||||
{
|
||||
QModelIndex selected = ui->_folderList->selectionModel()->currentIndex();
|
||||
if( selected.isValid() ) {
|
||||
QString alias = _model->data( selected, FolderStatusDelegate::FolderAliasRole ).toString();
|
||||
if (alias.isEmpty())
|
||||
return;
|
||||
int ret = QMessageBox::question( 0, tr("Confirm Folder Reset"),
|
||||
tr("<p>Do you really want to reset folder <i>%1</i> and rebuild your client database?</p>"
|
||||
"<p><b>Note:</b> This function is designed for maintenance purposes only. "
|
||||
"No files will be removed, but this can cause significant data traffic and "
|
||||
"take several minutes or hours to complete, depending on the size of the folder. "
|
||||
"Only use this option if advised by your administrator.</p>").arg(alias),
|
||||
QMessageBox::Yes|QMessageBox::No );
|
||||
if( ret == QMessageBox::Yes ) {
|
||||
FolderMan *folderMan = FolderMan::instance();
|
||||
if(Folder *f = folderMan->folder(alias)) {
|
||||
f->slotTerminateSync();
|
||||
f->wipe();
|
||||
}
|
||||
folderMan->slotScheduleAllFolders();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AccountSettings::slotOpenCurrentFolder()
|
||||
{
|
||||
QModelIndex selected = ui->_folderList->selectionModel()->currentIndex();
|
||||
@@ -465,8 +441,7 @@ void AccountSettings::slotEnableCurrentFolder()
|
||||
if ( f->isBusy() && terminate ) {
|
||||
f->slotTerminateSync();
|
||||
}
|
||||
f->setSyncPaused(!currentlyPaused); // toggle the pause setting
|
||||
folderMan->slotSetFolderPaused( f, !currentlyPaused );
|
||||
f->setSyncPaused(!currentlyPaused);
|
||||
|
||||
// keep state for the icon setting.
|
||||
if( currentlyPaused ) _wasDisabledBefore = true;
|
||||
@@ -541,7 +516,11 @@ void AccountSettings::slotAccountStateChanged(int state)
|
||||
}
|
||||
|
||||
if (state == AccountState::Connected) {
|
||||
showConnectionLabel( tr("Connected to %1.").arg(serverWithUser) );
|
||||
QStringList errors;
|
||||
if (account->serverVersionUnsupported()) {
|
||||
errors << tr("The server version %1 is old and unsupported! Proceed at your own risk.").arg(account->serverVersion());
|
||||
}
|
||||
showConnectionLabel( tr("Connected to %1.").arg(serverWithUser), errors );
|
||||
} else if (state == AccountState::ServiceUnavailable) {
|
||||
showConnectionLabel( tr("Server %1 is temporarily unavailable.").arg(server) );
|
||||
} else if (state == AccountState::SignedOut) {
|
||||
@@ -569,11 +548,10 @@ void AccountSettings::slotAccountStateChanged(int state)
|
||||
}
|
||||
/* set the correct label for the Account toolbox button */
|
||||
if( _accountState ) {
|
||||
bool isConnected = _accountState->isConnected();
|
||||
if( isConnected ) {
|
||||
_toggleSignInOutAction->setText(tr("Log out"));
|
||||
} else {
|
||||
if( _accountState->isSignedOut() ) {
|
||||
_toggleSignInOutAction->setText(tr("Log in"));
|
||||
} else {
|
||||
_toggleSignInOutAction->setText(tr("Log out"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -628,7 +606,8 @@ void AccountSettings::refreshSelectiveSyncStatus()
|
||||
continue;
|
||||
}
|
||||
|
||||
auto undecidedList = folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncUndecidedList);
|
||||
bool ok;
|
||||
auto undecidedList = folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncUndecidedList, &ok);
|
||||
QString p;
|
||||
foreach(const auto &it, undecidedList) {
|
||||
// FIXME: add the folder alias in a hoover hint.
|
||||
@@ -725,7 +704,11 @@ bool AccountSettings::event(QEvent* e)
|
||||
_quotaInfo.setActive(isVisible());
|
||||
}
|
||||
if (e->type() == QEvent::Show) {
|
||||
ui->_folderList->setExpanded(_model->index(0, 0), true);
|
||||
// Expand the folder automatically only if there's only one, see #4283
|
||||
// The 2 is 1 folder + 1 'add folder' button
|
||||
if (_model->rowCount() <= 2) {
|
||||
ui->_folderList->setExpanded(_model->index(0, 0), true);
|
||||
}
|
||||
}
|
||||
return QWidget::event(e);
|
||||
}
|
||||
|
||||