Comparar commits
620 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 22e31b2232 | |||
| 5ec4fd94e0 | |||
| c9ef4d5fa0 | |||
| 1cdf0e8597 | |||
| 7ba88cc9e3 | |||
| 914df32587 | |||
| e0f54428d0 | |||
| 52a11b0835 | |||
| ef17dc6482 | |||
| 9978dc3f6c | |||
| f618ed3dfb | |||
| ef915fb2e5 | |||
| 6e42405113 | |||
| 11ef07c74a | |||
| 486d7690c4 | |||
| 8852911f67 | |||
| e38bc6eab8 | |||
| 459e200ac0 | |||
| c781155b60 | |||
| 87aa1de67a | |||
| ccb871c30b | |||
| 74ed0b4f09 | |||
| becbb7b284 | |||
| ff76a842d0 | |||
| a56926b8d9 | |||
| 0d21503ee5 | |||
| 631cb095dd | |||
| caba719950 | |||
| 786b602c26 | |||
| f4bfce153d | |||
| e1ab50b17c | |||
| 7e4c0bd515 | |||
| ddcec2971e | |||
| 72d119a05f | |||
| d423cf2c7f | |||
| 3d847b50cf | |||
| 731a13cfd1 | |||
| 81296fae9d | |||
| aa38f7a4f2 | |||
| bac69f9984 | |||
| c46547592c | |||
| fd4a5100a6 | |||
| ff4a8c9202 | |||
| c871d721fd | |||
| 05d1cc9a94 | |||
| 196ee05fcc | |||
| e50cfa4e1b | |||
| 3224a959a4 | |||
| 2ccb3648c7 | |||
| 01aa647527 | |||
| eb3388de68 | |||
| beb970646b | |||
| 25c177ca3b | |||
| 1d9c591c08 | |||
| f753960add | |||
| 5e98894a97 | |||
| 15fe3b569b | |||
| 0e0b6026fc | |||
| 17dd199cba | |||
| 8f7dbe71a1 | |||
| 4b5c3d8f09 | |||
| 9955b0756a | |||
| 76d9b9c0e2 | |||
| 175ad6fb77 | |||
| 51896902e3 | |||
| b55220905e | |||
| bd65eb32b7 | |||
| b29d1e94b5 | |||
| b74e812671 | |||
| aa27b5db14 | |||
| 81e3a62360 | |||
| b0dc264369 | |||
| ac3f179420 | |||
| d9af837974 | |||
| 4784b327e7 | |||
| 1a1541ecd6 | |||
| cf9fec73cf | |||
| a1551ef6ab | |||
| 0163839cfb | |||
| 914a942e33 | |||
| 5e482ad4f7 | |||
| 6901fc9e38 | |||
| 0070835330 | |||
| 6431a2aa46 | |||
| 4cf2422a83 | |||
| 806ec98eab | |||
| 20fd349e17 | |||
| dae724b21c | |||
| 3e4612a1f0 | |||
| 6052e49bcc | |||
| 90cbd461ab | |||
| 517f2ed03d | |||
| 5fccc25f36 | |||
| cb1571c6c5 | |||
| 99b0d659bd | |||
| 854264c3d2 | |||
| d2a6cae695 | |||
| be9ed2f6a9 | |||
| 3ee8beb8a3 | |||
| f816e5e2af | |||
| 448d8bff18 | |||
| b82ffb52c7 | |||
| 3bccfb8993 | |||
| 6fb4e59120 | |||
| 309be57a12 | |||
| 37098c96f9 | |||
| 03cc67a2b1 | |||
| cb4fba7658 | |||
| 89734b95c4 | |||
| a59c3ef278 | |||
| b600ac882a | |||
| 71849c4372 | |||
| 9545af0d43 | |||
| 6c6ee358d4 | |||
| 060f4f291b | |||
| 3fb43d2322 | |||
| 4895683bab | |||
| 43800e3d1c | |||
| 3b8e1dcd89 | |||
| 302d6b321e | |||
| 3f85694394 | |||
| 8c5ef2f1c3 | |||
| aa1a2d1247 | |||
| 3993a7f636 | |||
| aaf16ff0e8 | |||
| 16c078963b | |||
| 9279bcdba4 | |||
| 0c467ef5b4 | |||
| 49cd53ee44 | |||
| 0e6a463564 | |||
| d38b190317 | |||
| 29558cb7bb | |||
| d2cd237e25 | |||
| c7b814337a | |||
| ced51813c7 | |||
| dd8d02b8ef | |||
| c3cf6aef7d | |||
| 38a8e5ee03 | |||
| 46269dac4e | |||
| 8c0297f688 | |||
| bc5890d8b5 | |||
| ee65315520 | |||
| 12f7cfde87 | |||
| 6d80f3d756 | |||
| b32f752d31 | |||
| cf8be7de91 | |||
| 30a3498c22 | |||
| 239603e24c | |||
| 390daed3de | |||
| 918c06aba3 | |||
| 726be08917 | |||
| a127debc54 | |||
| 6aa26654f6 | |||
| 0fde7f0e6b | |||
| d9f8edd259 | |||
| 251679253a | |||
| 64756c5dce | |||
| 9788055147 | |||
| 4d7fde59c2 | |||
| 4737c16996 | |||
| c97dfbf60c | |||
| 496b1e907d | |||
| 566131209d | |||
| b7823dc648 | |||
| 6d28a1b645 | |||
| b6aa18bfbc | |||
| d91ffc216a | |||
| a6c9e8c5b4 | |||
| 9337927722 | |||
| c81b02c7d9 | |||
| 5ea09d2668 | |||
| b9fc4c5994 | |||
| f1b500d3e0 | |||
| dff37e11eb | |||
| b1387f801b | |||
| 60b2312ab6 | |||
| 0354289795 | |||
| c11c35c459 | |||
| 7c5e70ac3c | |||
| d2e5ba123d | |||
| 0c9568f6dc | |||
| f1d48a9356 | |||
| 89f2a9e6dc | |||
| a203da3919 | |||
| 1c1ef52cf1 | |||
| 40c82c5c36 | |||
| 81f0c6535e | |||
| 46558d79a5 | |||
| e86b4203b9 | |||
| 05dd9554f9 | |||
| 30a0423f81 | |||
| 26e1223f9a | |||
| 84a04de7be | |||
| 3ff7fa0092 | |||
| 3f2a2cb14b | |||
| fac00348d9 | |||
| 3c93fd4fb7 | |||
| 6b71273380 | |||
| dccf4e9c34 | |||
| 39289a3164 | |||
| 6611d878ea | |||
| c3fc711095 | |||
| 84f1bdbc87 | |||
| 2eb5715599 | |||
| c93defc82d | |||
| bd39c64798 | |||
| 42a6b242c7 | |||
| e5570c24f2 | |||
| 6d87bd15cd | |||
| d657c00b11 | |||
| 6fae06f1d0 | |||
| f18b40f7e7 | |||
| 6a0633083d | |||
| 899f52be4f | |||
| 91525a7d33 | |||
| 455c3ae57d | |||
| b5390b5aa2 | |||
| a608b4e9e0 | |||
| f6a543ada3 | |||
| c7bf09c3d4 | |||
| c8ae54d9e8 | |||
| daf6d8772f | |||
| c80e72da83 | |||
| ec351e00ad | |||
| cf242871ea | |||
| 597d36dcf2 | |||
| 9c388787bb | |||
| f739d8fdd3 | |||
| 78d782601e | |||
| 86a83dc32c | |||
| c67e53c7b2 | |||
| 5659e04e89 | |||
| 8ff3055b47 | |||
| 71827549d6 | |||
| de5de7acc5 | |||
| c8590c4468 | |||
| 5f43c9cfad | |||
| 98b966d274 | |||
| 674b6f2373 | |||
| 407ff0a99d | |||
| 0b6d21e3d5 | |||
| 4c9bc42b69 | |||
| 557b704069 | |||
| d09de79491 | |||
| 4369e31a49 | |||
| 23b5a74c17 | |||
| ee69ab2021 | |||
| 374f29c4d3 | |||
| 67910e7d60 | |||
| c80b033466 | |||
| 671af9f8fe | |||
| 6ea05ff6e3 | |||
| 00485e133f | |||
| c520ee4eab | |||
| 5408ec79f7 | |||
| f8e68ae823 | |||
| 184412d88e | |||
| 82d1d04774 | |||
| 731d4b3d4d | |||
| ccec186b98 | |||
| c66c259447 | |||
| 4ad165ce26 | |||
| 24a801dfd3 | |||
| af79bc9211 | |||
| a3904f4d32 | |||
| 5cac90b3eb | |||
| df135a0bb2 | |||
| b7c927f349 | |||
| 64718fe567 | |||
| 79f14e0933 | |||
| 3ad8c692a4 | |||
| 546cab3f62 | |||
| 4a04dc1a3e | |||
| 0e97fbb730 | |||
| 83edb7fb8a | |||
| 0c59c85127 | |||
| d6098c39dc | |||
| af721118cd | |||
| 0d5f2b5d31 | |||
| 1790a128aa | |||
| 87fa1794a1 | |||
| 4df828d0b0 | |||
| 4d1d6dff3b | |||
| 81e30cd8d2 | |||
| 983671c8cb | |||
| 40ab3ee751 | |||
| eb6b254dc5 | |||
| f95fea9866 | |||
| 03719334ea | |||
| 4441053b1c | |||
| a34b663828 | |||
| db1f4d4016 | |||
| 3ea944d1b3 | |||
| b293aa762c | |||
| b5e75afc17 | |||
| 027a865fbc | |||
| 132b5f5130 | |||
| c3754e1fdd | |||
| 963eb1f29b | |||
| c418d67920 | |||
| 6e09e3af86 | |||
| 67e9a06d30 | |||
| abd63035c1 | |||
| 745cf55abb | |||
| e1c634d000 | |||
| 49a3a3ba7b | |||
| 9982211ced | |||
| 10f59bf3ad | |||
| df2418d9c5 | |||
| 2fdae6d72f | |||
| 05471d0acd | |||
| 05eee16959 | |||
| a752eadd0f | |||
| 028dc8d6c3 | |||
| 4a7242c8f9 | |||
| efdb29d2f9 | |||
| 7487d02a70 | |||
| 225da68832 | |||
| 51a2e6c580 | |||
| 7fe03c715d | |||
| c39f6c3fae | |||
| f4365dcca0 | |||
| fd75d5c679 | |||
| 014a53f990 | |||
| 419d18c128 | |||
| da76ba6c64 | |||
| afeb9e07e2 | |||
| 74a7755ad9 | |||
| c1ba927b37 | |||
| f22535e18a | |||
| 0f4e88eeaa | |||
| 70476c332a | |||
| a8eb913535 | |||
| 79145ff9fd | |||
| a0eb4b9c85 | |||
| cb3a301f2c | |||
| 6d6903ef62 | |||
| f5daf50dc4 | |||
| f6631443a1 | |||
| 87ad4dd264 | |||
| bb289f63f1 | |||
| 67a71ff10f | |||
| b8ccbbc72a | |||
| f0e17fd9c0 | |||
| b09f1d591c | |||
| 6b1bfb4474 | |||
| 8fd2b8d829 | |||
| 8158984ad6 | |||
| 7b61bcfe10 | |||
| d610693af1 | |||
| 7d1886684e | |||
| 95fc792745 | |||
| efefc2d986 | |||
| 9f8d109a7e | |||
| cf9e5ffb0b | |||
| 3cbd63a77a | |||
| 62eeed5201 | |||
| 1383023b2e | |||
| 9558822a7c | |||
| afd081f40b | |||
| 7bf31e56ab | |||
| 3812fd0866 | |||
| 24c41ed0da | |||
| 36e8e9ebf5 | |||
| 12dc372b21 | |||
| d8c5e58fa1 | |||
| 20ea9015ca | |||
| 0c148025a3 | |||
| d0c2ce276a | |||
| 9e813c7dcf | |||
| 440687af21 | |||
| 77a9b28e14 | |||
| f84654c9b3 | |||
| a7cf1b04ad | |||
| 641dece89a | |||
| 2c9d418423 | |||
| a08a90a718 | |||
| 1cb518cb13 | |||
| a897a1805e | |||
| fe88b48fb1 | |||
| 574c699382 | |||
| 7b97b96115 | |||
| e7e0e5b57f | |||
| b72e2b146d | |||
| a1421ff74f | |||
| 57f10c0c8e | |||
| 1f5834b74a | |||
| 836d7e1e5d | |||
| 48df009cea | |||
| 6343417def | |||
| 8c02034838 | |||
| 290cc58a63 | |||
| 5274b2485f | |||
| fc95e47790 | |||
| caaf8c841e | |||
| 6816cdd1c3 | |||
| 5f857a49b8 | |||
| 70ab7f04b3 | |||
| c1045af500 | |||
| c5c1a7a1c3 | |||
| 4144d4672f | |||
| 9cfa63eed8 | |||
| 68ed64e11d | |||
| 043655bd7a | |||
| c71058980a | |||
| 68947525a0 | |||
| 38eaf241fa | |||
| 8f8bf98ca6 | |||
| ef0ab93e05 | |||
| 95e370b70c | |||
| 5f06e3f738 | |||
| 3ba4e38693 | |||
| c09b4e1477 | |||
| ca95276298 | |||
| 5caf1ffb17 | |||
| c2431f2c3b | |||
| 15e4d9e317 | |||
| ef607e29de | |||
| 25d1defd73 | |||
| abfd97949d | |||
| 5347a991cf | |||
| f1a9e669b4 | |||
| 2d4bb31beb | |||
| 57e9f96836 | |||
| 5a791ec11e | |||
| 9dc9a7eac4 | |||
| e695144cd8 | |||
| cb6522e735 | |||
| 78a3453953 | |||
| a08cb3846c | |||
| d0aef138c3 | |||
| 6930cd6687 | |||
| 7bafc92df3 | |||
| 223a162a8b | |||
| 1f6efab318 | |||
| 7128b0122e | |||
| ba542cacb8 | |||
| 2f20c15824 | |||
| 6058b507c8 | |||
| 0d55562869 | |||
| c2fd708ce9 | |||
| 1aff9bca95 | |||
| d76f76f429 | |||
| 1de4d96ab1 | |||
| 78ed4866ce | |||
| d061a4b434 | |||
| 429f8229b3 | |||
| eb154de2a1 | |||
| 8c2b5af7f0 | |||
| 9004fd6d11 | |||
| 5f660bf080 | |||
| 1f55598010 | |||
| 9eec45f9c4 | |||
| cf7726353a | |||
| 93e1ad088c | |||
| 13b6b3989a | |||
| 2a8aa8a108 | |||
| b490be2267 | |||
| cac219aca8 | |||
| a159dfc7ec | |||
| 593ad20e69 | |||
| bae552f386 | |||
| 16d6418d10 | |||
| 995b42d0fc | |||
| c0f8ff1030 | |||
| 8e2b9c6f12 | |||
| 7d191763b5 | |||
| 144a1a1922 | |||
| be3529ebcb | |||
| e00cc4ed5b | |||
| b7061618b1 | |||
| 613736aa41 | |||
| d823809021 | |||
| b83c723e3f | |||
| 6b222c3db7 | |||
| 088c0d471a | |||
| 5e657aadee | |||
| 98e6d61d1b | |||
| df534753b1 | |||
| 02c077e3f8 | |||
| 0329a8be2e | |||
| 79f64abfc3 | |||
| ba2145032e | |||
| 63636aca9b | |||
| bff9d646f7 | |||
| fdfab07d07 | |||
| cc5f8e5122 | |||
| 8495d097bb | |||
| 21dbf97a02 | |||
| 66f340734c | |||
| 794f071561 | |||
| c6794afc3a | |||
| 8920ba3de2 | |||
| 39bff056a6 | |||
| 128d46e19a | |||
| 6d027ebd40 | |||
| 89f69209dd | |||
| 94a57fe8d5 | |||
| 14c55083f3 | |||
| c832a9eee5 | |||
| 699acc99e4 | |||
| 90338499d3 | |||
| 641f56664e | |||
| 419deff861 | |||
| 69f8dd896f | |||
| e49a8a9ffe | |||
| b6e0802203 | |||
| e03fe8bcbf | |||
| 7bfbc21770 | |||
| d853b4f083 | |||
| d8939184db | |||
| e54253d845 | |||
| 141d43a1ee | |||
| 0fac72f3b3 | |||
| cc4bc2e47a | |||
| dcb687929f | |||
| 628957de21 | |||
| bcfc16c0f6 | |||
| 3ba5e27d02 | |||
| 0fa4353841 | |||
| 58ea498a62 | |||
| 688aaadb60 | |||
| f77ae28ed1 | |||
| 0d08bbec74 | |||
| ebee6f0bc2 | |||
| db8f9586cb | |||
| 35318ea9b5 | |||
| 7aeb27d5ee | |||
| 322288bf6c | |||
| 6b7bfc75a8 | |||
| abe96135ff | |||
| 8bf2db27dd | |||
| 950bc578d0 | |||
| c48c5b9286 | |||
| d503221b2e | |||
| b3a462d452 | |||
| 916f522010 | |||
| 967b533e37 | |||
| 9172a5fc4c | |||
| 17e9b65cad | |||
| a976f75783 | |||
| 3ebc422bb5 | |||
| 9f765c940e | |||
| 1a0d0c0a31 | |||
| ce769cb1ef | |||
| 8fb4adf40d | |||
| 03954b5918 | |||
| ab4fa905fc | |||
| 530552820d | |||
| cb1bcdc8e0 | |||
| 1f43c47861 | |||
| 5414c65442 | |||
| f38deb44fb | |||
| 937526b881 | |||
| 7ba97d88d5 | |||
| ccfcdff190 | |||
| 45835f1cf9 | |||
| cf543d1eb0 | |||
| 9f24f10186 | |||
| 64b211f5db | |||
| 32c636a471 | |||
| 2d421a8275 | |||
| ed28a21cb0 | |||
| 3db0db451e | |||
| 035e57cf37 | |||
| 07ca0be3c5 | |||
| e71cca128d | |||
| fe49255bff | |||
| 20f4ec6b67 | |||
| 92f6134ed3 | |||
| a0f9b834b6 | |||
| 2ad57ee8ab | |||
| 6c5328e4ca | |||
| 6cf1caeaf3 | |||
| ce233105b6 | |||
| 30033cdd7d | |||
| 18f54ad758 | |||
| bc37668e9f | |||
| 4eadaeafc9 | |||
| 3414b58b99 | |||
| 14d1919139 | |||
| 7aae5e494a | |||
| 0711a2fc12 | |||
| 577eb1f609 | |||
| 92fc902e0c | |||
| 791c550a8e | |||
| 344d3565f8 | |||
| 73785d0473 | |||
| b155503fa2 | |||
| 2c011dcae6 | |||
| 0e0af1da07 | |||
| a7d0f0cdd4 | |||
| 488d57d81c | |||
| 38aa4cf304 | |||
| 0638f99b79 | |||
| da93f37067 | |||
| 9a0fba5f5e | |||
| 22d87218b7 | |||
| bd39543542 | |||
| 49949084fb | |||
| b584f37906 | |||
| 70f3b91a1e | |||
| 15545168d4 | |||
| 2d797c9408 | |||
| 8d5ffccaf1 | |||
| 855947751e | |||
| 9dd9a9a524 | |||
| 554e5b8f73 | |||
| f368c0e379 | |||
| e54bbcd15f | |||
| 149d6c32c1 | |||
| 0ca3df917e | |||
| 12fe59e3ce | |||
| 3bfb8f6906 | |||
| 7527ee0cd3 | |||
| 080ec49fae | |||
| fe92186ce0 | |||
| 62d64acd7b | |||
| c6ff73f3e5 | |||
| a87602af3f |
@@ -32,7 +32,7 @@ include(Warnings)
|
||||
include(${CMAKE_SOURCE_DIR}/VERSION.cmake)
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/src/mirall/")
|
||||
|
||||
# disable the crashrepoter if libcrashreporter-qt is not available or we're building for ARM
|
||||
# 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")
|
||||
set( WITH_CRASHREPORTER OFF )
|
||||
endif()
|
||||
@@ -114,16 +114,16 @@ endif()
|
||||
# this option creates only libocsync and libowncloudsync
|
||||
option(BUILD_LIBRARIES_ONLY "BUILD_LIBRARIES_ONLY" OFF)
|
||||
|
||||
# When this option is enabled, 5xx errors are not added to the clacklist
|
||||
# Normaly you don't want to enable this option because if a particular file
|
||||
# trigger a bug on the server, you want the file to be blacklisted.
|
||||
# When this option is enabled, 5xx errors are not added to the blacklist
|
||||
# Normally you don't want to enable this option because if a particular file
|
||||
# triggers a bug on the server, you want the file to be blacklisted.
|
||||
option(OWNCLOUD_5XX_NO_BLACKLIST "OWNCLOUD_5XX_NO_BLACKLIST" OFF)
|
||||
if(OWNCLOUD_5XX_NO_BLACKLIST)
|
||||
add_definitions(-DOWNCLOUD_5XX_NO_BLACKLIST=1)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set( SOCKETAPI_TEAM_IDENTIFIER_PREFIX "" CACHE STRING "SocketApi prefix (including a following dot) that must match the codesigh key's TeamIdentifier/Organizational Unit" )
|
||||
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
|
||||
@@ -133,13 +133,9 @@ endif()
|
||||
#endif()
|
||||
|
||||
|
||||
set(USE_NEON TRUE)
|
||||
if(HAVE_QT5)
|
||||
message(STATUS "Using Qt ${Qt5Core_VERSION_MAJOR}.${Qt5Core_VERSION_MINOR}.x")
|
||||
if (${Qt5Core_VERSION_MAJOR} EQUAL "5")
|
||||
if (${Qt5Core_VERSION_MINOR} EQUAL "4" OR ${Qt5Core_VERSION_MINOR} GREATER 4)
|
||||
message(STATUS "We would not require Neon in this setup, compile without!")
|
||||
set(USE_NEON FALSE)
|
||||
else()
|
||||
message(STATUS "If possible compile me with Qt 5.4 or higher.")
|
||||
endif()
|
||||
@@ -148,9 +144,6 @@ else()
|
||||
message(STATUS "If possible compile me with Qt 5.4 or higher.")
|
||||
endif()
|
||||
|
||||
if (USE_NEON)
|
||||
find_package(Neon REQUIRED)
|
||||
endif(USE_NEON)
|
||||
find_package(OpenSSL 1.0.0 REQUIRED)
|
||||
|
||||
if(NOT TOKEN_AUTH_ONLY)
|
||||
|
||||
@@ -6,10 +6,10 @@ We are also available on [IRC][irc].
|
||||
|
||||
### Bug Reporting Guidelines
|
||||
* __Important__: Report the issue using our [template][template], it includes all the
|
||||
informations we need to track down the issue.
|
||||
information we need to track down the issue.
|
||||
* __SECURITY__: Report any potential security bug to security@owncloud.com following our [security policy](https://owncloud.org/security/) instead of filing an issue in our bug tracker
|
||||
* This repository is *only* for issues within the ownCloud desktop client.
|
||||
Issues in other compontents should be reported in their own repositores:
|
||||
Issues in other components should be reported in their own repositores:
|
||||
- [ownCloud server](https://github.com/owncloud/core/issues)
|
||||
- [ownCloud apps](https://github.com/owncloud/apps/issues) (e.g. Calendar,
|
||||
Contacts...)
|
||||
@@ -36,7 +36,7 @@ Before we're able to merge your code to ownCloud Desktop Client, you need to sig
|
||||
our [Contributor Agreement][agreement].
|
||||
|
||||
Please read the [Desktop Client Manual][desktopman] and the [Developer
|
||||
Manuals][devmanual] to get useful infos like how to create your first
|
||||
Manuals][devmanual] to get useful info like how to create your first
|
||||
application or how to test the ownCloud code with phpunit.
|
||||
|
||||
[agreement]: http://owncloud.org/about/contributor-agreement/
|
||||
|
||||
@@ -1,6 +1,60 @@
|
||||
ChangeLog
|
||||
=========
|
||||
version 2.0.0 (release 2015-08-??)
|
||||
version 2.1 (release 2015-yy-zz)
|
||||
* We removed the old libneon-based propagator.
|
||||
It was already disabled on OS X and Windows and only used on
|
||||
Linux when building with Qt < 5.4 and having bandwidth limiting enabled.
|
||||
So now you need Qt 5.4 on Linux if you want bandwidth limiting.
|
||||
|
||||
version 2.0.2 (release 2015-10-21)
|
||||
* csync_file_stat_s: Save a bit of memory
|
||||
* Shibboleth: Add our base user agent to WebKit
|
||||
* SelectiveSync: Increase folder list timeout to 60
|
||||
* Propagation: Try another sync on 423 Locked (#3387)
|
||||
* Propagation: Make 423 Locked a soft error (#3387)
|
||||
* Propagation: Reset upload blacklist if a chunk succeeds
|
||||
* Application: Fix crash on early shutdown (#3898)
|
||||
* Linux: Don't show settings dialog always when launched twice (#3273, #3771, #3485)
|
||||
* win32 vio: Add the OPEN_REPARSE_POINTS flag to the CreateFileW call. (#3813)
|
||||
* AccountSettings: only expand root elements on single click.
|
||||
* AccountSettings: Do not allow to expand the folder list when disconnected.
|
||||
* Use application SHORT name for the name of the MacOSX pkg file (ownBrander).
|
||||
* FolderMan: Fix for removing a syncing folder (#3843)
|
||||
* ConnectionMethodDialog: Don't be insecure on close (#3863)
|
||||
* Updater: Ensure folders are not removed (#3747)
|
||||
* Folder settings: Ensure path is cleaned (#3811)
|
||||
* Propagator: Simplify sub job finished counting (#3844)
|
||||
* Share dialog: Hide settings dialog before showing (#3783)
|
||||
* UI: Only expand 1 level in folder list (#3585)
|
||||
* UI: Allow folder expanding from button click (#3585)
|
||||
* UI: Expand folder treeview on single click (#3585)
|
||||
* GUI: Change tray menu order (#3657)
|
||||
* GUI: Replace term "sign in" with "Log in" and friends.
|
||||
* SetupPage: Fix crash caused by uninitialized Account object.
|
||||
* Use a themable WebDAV path all over.
|
||||
* Units: Back to the "usual" mix units (JEDEC standard).
|
||||
* csync io: Full UNC path support on Win (#3748)
|
||||
* Tray: Don't use the tray workaround with the KDE theme (#3706, #3765)
|
||||
* ShareDialog: Fix folder display (#3659)
|
||||
* AccountSettings: Restore from legacy only once (#3565)
|
||||
* SSL Certificate Error Dialog: show account name (#3729)
|
||||
* Tray notification: Don't show a message about modified folder (#3613)
|
||||
* PropagateLocalRemove: remove entries from the DB even if there was an error.
|
||||
* Settings UI improvements (eg. #3713, #3721, #3619 and others)
|
||||
* Folder: Do not create the sync folder if it does not exist (#3692)
|
||||
* Shell integration: don't show share menu item for top level folders
|
||||
* Tray: Hide while modifying menus (#3656, #3672)
|
||||
* AddFolder: Improve remote path selection error handling (#3573)
|
||||
* csync_update: Use excluded_traversal() to improve performance (#3638)
|
||||
* csync_excluded: Add fast _traversal() function (#3638)
|
||||
* csync_exclude: Speed up significantly (#3638)
|
||||
* AccountSettings: Adjust quota info design (#3644, #3651)
|
||||
* Adjust buttons on remove folder/account questions (#3654)
|
||||
|
||||
version 2.0.1 (release 2015-09-01)
|
||||
* AccountWizard: fix when the theme specify a override URL (#3699)
|
||||
|
||||
version 2.0.0 (release 2015-08-25)
|
||||
* Add support for multiple accounts (#3084)
|
||||
* Do not sync down new big folders from server without users consent (#3148)
|
||||
* Integrate Selective Sync into the default UI
|
||||
@@ -25,6 +79,7 @@ version 2.0.0 (release 2015-08-??)
|
||||
* Several fixes and performance improvements in the sync engine
|
||||
* Network: Try to use SSL session tickets/identifiers. Check the SSL button to see if they are used.
|
||||
* Bandwidth Throttling: Provide automatic limit setting for downloads (#3084)
|
||||
* Systray: Workaround for issue with Qt 5.5.0 #3656
|
||||
|
||||
version 1.8.4 (release 2015-07-13)
|
||||
* Release to ship a security release of openSSL. No source changes of the ownCloud Client code.
|
||||
|
||||
@@ -14,5 +14,5 @@ set( MAC_INSTALLER_BACKGROUND_FILE "${CMAKE_SOURCE_DIR}/admin/osx/installer-back
|
||||
# set( APPLICATION_LICENSE "${OEM_THEME_DIR}/license.txt )
|
||||
|
||||
option( WITH_CRASHREPORTER "Build crashreporter" OFF )
|
||||
set( CRASHREPORTER_SUBMIT_URL "https://crash-reports.owncloud.com/submit" CACHE string "URL for crash repoter" )
|
||||
set( CRASHREPORTER_SUBMIT_URL "https://crash-reports.owncloud.com/submit" CACHE string "URL for crash reporter" )
|
||||
set( CRASHREPORTER_ICON ":/owncloud-icon.png" )
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|-----------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| client-build-matrix | [](https://ci.owncloud.org/job/client-build-matrix-linux/) |
|
||||
| client-test-matrix-linux-no-build | [](https://ci.owncloud.org/job/client-test-matrix-linux-no-build/) |
|
||||
|
||||
| coverity_scan | [](https://scan.coverity.com/projects/owncloud-mirall)
|
||||
|
||||
## Introduction
|
||||
|
||||
@@ -27,7 +27,7 @@ https://github.com/owncloud/client.
|
||||
|
||||
## Building the source code
|
||||
|
||||
[Building the Client](http://doc.owncloud.org/desktop/1.7/building.html)
|
||||
[Building the Client](http://doc.owncloud.org/desktop/2.0/building.html)
|
||||
in the ownCloud Desktop Client manual.
|
||||
|
||||
## Maintainers and Contributors
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
set( MIRALL_VERSION_MAJOR 2 )
|
||||
set( MIRALL_VERSION_MINOR 0 )
|
||||
set( MIRALL_VERSION_MINOR 1 )
|
||||
set( MIRALL_VERSION_PATCH 0 )
|
||||
set( MIRALL_SOVERSION 0 )
|
||||
|
||||
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||
set( MIRALL_VERSION_SUFFIX "git") #e.g. beta1, beta2, rc1
|
||||
set( MIRALL_VERSION_SUFFIX "beta1") #e.g. beta1, beta2, rc1
|
||||
endif( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||
|
||||
if( NOT DEFINED MIRALL_VERSION_BUILD )
|
||||
|
||||
@@ -23,7 +23,7 @@ identity="$3"
|
||||
prjfile=$build_path/admin/osx/macosx.pkgproj
|
||||
|
||||
# The name of the installer package
|
||||
installer="@APPLICATION_NAME@-@MIRALL_VERSION_FULL@@MIRALL_VERSION_SUFFIX@"
|
||||
installer="@APPLICATION_SHORTNAME@-@MIRALL_VERSION_FULL@@MIRALL_VERSION_SUFFIX@"
|
||||
installer_file="$installer.pkg"
|
||||
installer_file_tar="$installer.pkg.tar"
|
||||
installer_file_tar_bz2="$installer.pkg.tar.bz2"
|
||||
|
||||
@@ -38,6 +38,8 @@ QT_PLUGINS = [
|
||||
'imageformats/libqgif.dylib',
|
||||
'imageformats/libqico.dylib',
|
||||
'imageformats/libqjpeg.dylib',
|
||||
'bearer/libqcorewlanbearer.dylib',
|
||||
'bearer/libqgenericbearer.dylib',
|
||||
'imageformats/libqsvg.dylib',
|
||||
'imageformats/libqmng.dylib',
|
||||
]
|
||||
@@ -144,6 +146,10 @@ def FindFramework(path):
|
||||
search_pathes = FRAMEWORK_SEARCH_PATH
|
||||
search_pathes.insert(0, QueryQMake('QT_INSTALL_LIBS'))
|
||||
for search_path in search_pathes:
|
||||
# The following two lines are needed for a custom built Qt from version 5.5 on, possibly not for the one from the Qt SDK.
|
||||
# Looks like the upstream macdeployqt also had an issue there https://bugreports.qt.io/browse/QTBUG-47868
|
||||
if path.find( "\@rpath/"):
|
||||
path = path.replace("@rpath/", "")
|
||||
abs_path = os.path.join(search_path, path)
|
||||
if os.path.exists(abs_path):
|
||||
return abs_path
|
||||
|
||||
@@ -32,7 +32,3 @@ SET(QT_MOC_EXECUTABLE ${MINGW_PREFIX}-moc)
|
||||
SET(QT_RCC_EXECUTABLE ${MINGW_PREFIX}-rcc)
|
||||
SET(QT_UIC_EXECUTABLE ${MINGW_PREFIX}-uic)
|
||||
SET(QT_LRELEASE_EXECUTABLE ${MINGW_PREFIX}-lrelease)
|
||||
|
||||
# neon config
|
||||
SET(NEON_CONFIG_EXECUTABLE ${CMAKE_FIND_ROOT_PATH}/bin/neon-config)
|
||||
# /usr/i686-w64-mingw32/sys-root/mingw/bin/neon-config
|
||||
|
||||
@@ -9,7 +9,6 @@ StrCpy $PageReinstall_NEW_Field_3 "Ez desinstalatu"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Dagoeneko Instalatuta"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Hautatu nola nahi duzun ${APPLICATION_NAME} instalatzea."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "${APPLICATION_NAME}ren bertsio berriago bat instalatuta dago! Ez da aholkatzen bertsio zaharrago bat instalatzea. Benetan bertsio zaharrago hau instalatu nahi baduzu, hobe da lehenengo bertsio berria desinstalatzea. Hautatu nahi duzun aukera eta sakatu Hurrengoa jarraitzeko."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} dagoeneko instalatuta dago.\nHautatu zer operazio egin nahi duzu eta klikatu Hurrengoa jarraitzeko."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Gehitu/Berrinstalatu osagaiak"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Desinstalatu ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalatu ${APPLICATION_NAME}"
|
||||
@@ -39,5 +38,6 @@ StrCpy $INIT_INSTALLER_RUNNING "Instalatzailea dagoeneko martxan da."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Desinstalatzaile honek administratzaile baimenak behar ditu, saiatu berriro"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Desinstalatzailea dagoeneko martxan da."
|
||||
StrCpy $SectionGroup_Shortcuts "Lasterbideak"
|
||||
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_ELEVATE "Unable to elevate, error:"
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Logon service is not running, aborting!"
|
||||
|
||||
@@ -9,7 +9,6 @@ StrCpy $PageReinstall_NEW_Field_3 "No instal·lar"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Ja instal·lat"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Trieu la manera com voleu instal·lar ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Una versió més recent de ${APPLICATION_NAME} ja està instal.lada!! No es recomana instal.lar una versió més antiga. Si realment voleu instal.lar una versió més antiga, és millor primer desinstal.lar la versió actual. Seleccioni l'operació que desitjeu realitzar i feu clic a Següent per a continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} ja està instal.lat.↩\nSeleccioneu l'operació que desitjeu realitzar i feu clic a Següent per continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Afegir/Reinstal.lar components"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Desinstal.lar ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstal.lar ${APPLICATION_NAME}"
|
||||
@@ -40,4 +39,5 @@ StrCpy $INIT_INSTALLER_RUNNING "L'instal·lador ja s'està executant."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Aquest desinstal·lador requereix accés d'administrador, intenteu-ho de nou."
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "El desinstal·lador ja s'està executant."
|
||||
StrCpy $SectionGroup_Shortcuts "Dreceres"
|
||||
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!"
|
||||
|
||||
@@ -9,7 +9,7 @@ StrCpy $PageReinstall_NEW_Field_3 "Neodinstalov
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Ji§ nainstalov no"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Zvolte, jak chcete ${APPLICATION_NAME} nainstalovat."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "NovØjç¡ verze aplikace ${APPLICATION_NAME} je ji§ nainstalov na. Instalace starç¡ verze se nedoporuŸuje. Pokud opravdu chcete tuto starç¡ verzi nainstalovat, je lepç¡ nejprve odinstalovat souŸasnou verzi. Zvolte po§adovanou operaci a kliknØte na Dalç¡ pro pokraŸov n¡."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} je ji§ nainstalov na.\nZvolte po§adovanou operaci a kliknØte na Dalç¡ pro pokraŸov n¡."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} je ji§ nainstalov na.$\n$\nZvolte po§adovanou operaci a kliknØte na Dalç¡ pro pokraŸov n¡."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Pýidat Ÿi znovu instalovat komponenty"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Odinstalovat ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Odinstalovat ${APPLICATION_NAME}"
|
||||
@@ -30,7 +30,7 @@ StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Z
|
||||
StrCpy $UNINSTALLER_FILE_Detail "Zapisuji odinstal tor"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Zapisuji instal tor do registr…"
|
||||
StrCpy $UNINSTALLER_FINISHED_Detail "DokonŸeno"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Nezd se, §e ${APPLICATION_NAME} je nainstalov na ve slo§ce '$INSTDIR'.\nChcete pokraŸovat (nedoporuŸuje se)?"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Nezd se, §e ${APPLICATION_NAME} je nainstalov na ve slo§ce '$INSTDIR'.$\n$\nChcete pokraŸovat (nedoporuŸuje se)?"
|
||||
StrCpy $UNINSTALL_ABORT "Odinstalace zruçena u§ivatelem"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Z stupce rychl‚ho spuçtØn¡ (nen¡ k dispozici)"
|
||||
StrCpy $INIT_NO_DESKTOP "Z stupce na ploçe (pýep¡çe existuj¡c¡)"
|
||||
|
||||
@@ -9,7 +9,7 @@ StrCpy $PageReinstall_NEW_Field_3 "Niet de-installeren"
|
||||
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."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is al geïnstalleerd.\nKies de actie die u wilt uitvoeren en druk op Verder om door te gaan."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is al geïnstalleerd.$\n$\nKies de actie die u uit wil voeren en druk op Verder om door te gaan."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Toevoegen/herinstalleren componenten"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "De-installeer ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "De-installeer ${APPLICATION_NAME}"
|
||||
|
||||
@@ -9,7 +9,7 @@ StrCpy $PageReinstall_NEW_Field_3 "Do not uninstall"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Already Installed"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Choose how you want to install ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "A newer version of ${APPLICATION_NAME} is already installed! It is not recommended that you install an older version. If you really want to install this older version, it is better to uninstall the current version first. Select the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.\r\nSelect the operation you want to perform and click Next to continue."
|
||||
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 $PageReinstall_SAME_Field_2 "Add/Reinstall components"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Uninstall ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Uninstall ${APPLICATION_NAME}"
|
||||
|
||||
@@ -9,7 +9,6 @@ StrCpy $PageReinstall_NEW_Field_3 "
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Juba paigaldatud"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Vali, kuidas sa soovid paigaldada ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Uuem versioon ${APPLICATION_NAME} on juba paigaldatud! Vanema versiooni paigaldus ei ole soovitatav. Kui tõesti tahad paigaldada vanemat versiooni, siis on parem esmalt eemaldada olemasolev. Vali tehtav toiming ning kliki Jätka."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} on juba paigaldatud.\nVali tehtav toiming ning kliki Jätka."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Lisa/Taaspaigalda komponente"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Desinstalli ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalli ${APPLICATION_NAME}"
|
||||
@@ -41,3 +40,4 @@ StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "See desinstallija vajab admini ligip
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Sisselogimisteenus ei tööta, katkestamine!"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "See desinstallija on juba käimas."
|
||||
StrCpy $SectionGroup_Shortcuts "Otseteed"
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.$\r$\nSelect the operation you want to perform and click Next to continue."
|
||||
|
||||
@@ -1,10 +1,22 @@
|
||||
# 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 $PageReinstall_NEW_Field_1 "نسخهی قدیمی از برنامه ${APPLICATION_NAME} بر روی سیستم شما نصب شده است، پیشنهاد میشود نسخهی فعلی را قبل از نصب حذف کنید. عملیات مورد نظر را انتخاب کنید و برای ادامه روی دکمه Next کلیک کنید."
|
||||
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} بر روی سیستم شما نصب شده است، نصب نسخهی قدیمیتر پیشنهاد نمیشود. درصورتیکه میخواهید نسخهی قدیمی را نصب کنید، حذف نسخهی کنونی قبل از اجرای نصب جدید پیشنهاد میشود. عملیات مورد نظر را انتخاب و بر روی دکمهی Next کلیک کنید."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "نسخه ${VERSION} از ${APPLICATION_NAME} هماکنون نصب شده است.$↩$\nعملیات مورد نظر را انتخاب و بر روی دکمه Next کلیک کنید."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "افزودن/نصب مجدد اجزا"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "حذف ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "حذف ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "گزینه نگهداری را به منظور اجرا انتخاب کنید."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "نصب ضروریات ${APPLICATION_NAME}"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "یکپارچهسازی با Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "نصب یکپارچهساز با Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "بازکردن میانبر منو برنامه"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "افزودن میانبر ${APPLICATION_NAME} به استارت منو ."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "میانبر دسکتاپ"
|
||||
@@ -23,21 +35,9 @@ StrCpy $UNINSTALL_ABORT "عمل حذف توسط کاربر متوقف شد"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "میانبر بازکردن سریع ( N/A )"
|
||||
StrCpy $INIT_NO_DESKTOP "میانبر دسکتاپ (رونویسی وجود دارد)"
|
||||
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 $ConfirmEndProcess_MESSAGEBOX_TEXT "Found ${APPLICATION_EXECUTABLE} process(s) which need to be stopped.$\nDo you want the installer to stop these for you?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Killing ${APPLICATION_EXECUTABLE} processes."
|
||||
StrCpy $PageReinstall_NEW_Field_1 "An older version of ${APPLICATION_NAME} is installed on your system. It is recommended that you uninstall the current version before installing. Select the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Choose how you want to install ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "A newer version of ${APPLICATION_NAME} is already installed! It is not recommended that you install an older version. If you really want to install this older version, it is better to uninstall the current version first. Select the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.\r\nSelect the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Uninstall ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Uninstall ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Choose the maintenance option to perform."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Installing ${APPLICATION_NAME} essentials."
|
||||
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_INSTALLER_REQUIRE_ADMIN "This installer requires admin access, try again"
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Logon service is not running, aborting!"
|
||||
|
||||
@@ -9,7 +9,7 @@ StrCpy $PageReinstall_NEW_Field_3 "
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Asennettu jo"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Valitse miten ${APPLICATION_NAME} asennetaan."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Uudempi versio sovelluksesta ${APPLICATION_NAME} on jo asennettu! Vanhan version asennus ei ole suositeltavaa. Jos todella haluat asentaa vanhemman version, kannattaa poistaa nykyisen version asennus ensin. Valitse minkä toimenpiteen haluat suorittaa ja paina Seuraava jatkaaksesi."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} on jo asennettu.\nValitse suoritettava toimenpide ja napsauta Seuraava jatkaaksesi."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} on jo asennettu.$\n$\nValitse haluamasi toiminto ja napsauta Seuraava jatkaaksesi."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Lisää/uudelleenasenna komponentteja"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Poista ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Poista ${APPLICATION_NAME}"
|
||||
|
||||
@@ -9,7 +9,7 @@ StrCpy $PageReinstall_NEW_Field_3 "Ne pas désinstaller"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Déjà installé"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Choisissez comment installer ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Une version plus récente de ${APPLICATION_NAME} est déjà installée ! Il n'est pas recommandé d'installer une version plus ancienne. Si vous voulez vraiment installer cette version plus ancienne, il est préférable de d'abord désinstaller la version courante. Sélectionnez l'opération que vous voulez exécuter et cliquez sur Suivant pour continuer."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} est déjà installé.\nSélectionnez l'opération que vous voulez exécuter et cliquez sur Suivant pour continuer."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} est déjà installé.$\n$\nSélectionnez l'opération que vous souhaitez effectuer et cliquez sur Suivant pour continuer."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Ajouter/Réinstaller des composants"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Désinstaller ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Désinstaller ${APPLICATION_NAME}"
|
||||
@@ -38,6 +38,6 @@ StrCpy $UAC_ERROR_ELEVATE "Échec d'élévation, erreur :"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Cet installateur requiert les droits administrateur, essayez à nouveau"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "Une installation est déjà en cours."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Ce désinstallateur requiert les droits administrateur, essayez à nouveau"
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Service de logon non lancé ! Abandon."
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Une désinstallation est déjà en cours."
|
||||
StrCpy $SectionGroup_Shortcuts "Raccourcis"
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Logon service is not running, aborting!"
|
||||
|
||||
@@ -9,7 +9,6 @@ StrCpy $PageReinstall_NEW_Field_3 "Non desinstalar"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Xa instalado"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Escolla como quere instalar ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Ten instalada unha versión actualizada do ${APPLICATION_NAME}! recomendámoslle que non instale unha versión anterior. Se realmente quere instalar esta versión máis antiga, é preferíbel que desinstale a versión actual antes de instalar. Seleccione a operación que quere realizar e prema en Seguinte para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} xa está instalado.\nSeleccione a operación que que quere realizar e prema en Seguinte para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Engadir/reinstalar compoñentes"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Desinstalar ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalar ${APPLICATION_NAME}"
|
||||
@@ -41,3 +40,4 @@ StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Este desinstalador require acceso de admi
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "O servizo de acceso non está en execución, cancelando!"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "O desinstalador xa está en execución."
|
||||
StrCpy $SectionGroup_Shortcuts "Atallos"
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.$\r$\nSelect the operation you want to perform and click Next to continue."
|
||||
|
||||
@@ -9,7 +9,6 @@ StrCpy $PageReinstall_NEW_Field_3 "Nicht entfernen"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Bereits installiert"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Wählen Sie die Methode, mit der sie ${APPLICATION_NAME} installieren wollen."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Eine neuere Version von ${APPLICATION_NAME} ist bereits installiert! Es wird nicht empfohlen, eine ältere Version zu installieren. Wollen Sie dies trotzdem tun, so sollten Sie die aktuelle Version zunächst entfernen. Wählen Sie eine Vorgehensweise und wählen dann $\"Weiter$\"."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} ist bereits installiert.\nWählen Sie eine Vorgehensweise und klicken Sie auf $\"Weiter$\"."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Komponenten hinzufügen"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "${APPLICATION_NAME} entfernen"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "${APPLICATION_NAME} entfernen"
|
||||
@@ -40,4 +39,5 @@ StrCpy $INIT_INSTALLER_RUNNING "Das Installationsprogramm wird bereits ausgef
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Das Deinstallationsprogramm erfordert Administrator-Rechte. Bitte erneut versuchen."
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Das Deinstallationsprogramm wird bereits ausgeführt."
|
||||
StrCpy $SectionGroup_Shortcuts "Verknüpfungen"
|
||||
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!"
|
||||
|
||||
@@ -9,7 +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_1 "Η ${APPLICATION_NAME} ${VERSION} είναι ήδη εγκατεστημένη.$\n$\nΕπιλέξτε τη λειτουργία που επιθυμείτε να εκτελέσετε και επιλέξτε Επόμενο για να συνεχίσετε."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Προσθήκη/ Επανεγκατάσταση συνιστωσών"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Απεγκατάσταση ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Απεγκατάσταση ${APPLICATION_NAME}"
|
||||
|
||||
@@ -9,7 +9,7 @@ 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_OLD_Field_1 "Az ${APPLICATION_NAME} alklamazá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érem válassza ki milyen műveletet szeretne végrehajtan, és nyomja meg a $\"Következő$\" gombot."
|
||||
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"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "${APPLICATION_NAME} eltávolítása"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "${APPLICATION_NAME} eltávolítása"
|
||||
|
||||
@@ -9,7 +9,7 @@ StrCpy $PageReinstall_NEW_Field_3 "Non disinstallare"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Già installato"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Scegli come desideri installare ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Una versione più recente di ${APPLICATION_NAME} è già installata! Non è consigliabile installare una versione più vecchia. Se vuoi davvero installare una versione più vecchia, ti consigliamo di rimuovere prima la versione attuale. Scegli l'operazione da eseguire e fai clic su Avanti per continuare."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} è già installato.\nSeleziona l'operazione che desideri eseguire e fai clic su Avanti per continuare."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} è già installato.$\n$\nSeleziona l'operazione che desideri eseguire e fai clic su Avanti per continuare.."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Aggiungi/Reinstalla i componenti"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Disinstalla ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Disinstalla ${APPLICATION_NAME}"
|
||||
|
||||
@@ -9,7 +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} の最新バージョンがすでにインストールされています。\n旧バージョンのインストールはお勧めしません。旧バージョンのインストールが本当に必要な場合は、まず最新バージョンをアンインストールしてから、旧バージョンをインストールしてください。\nオペレーションを選択し、次へをクリックする。"
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} はすでにインストールされています。\n実行するオペレーションを選択し、次へをクリックする"
|
||||
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} をアンインストール"
|
||||
|
||||
@@ -9,7 +9,7 @@ StrCpy $PageReinstall_NEW_Field_3 "Ikke avinstaller"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Allerede installert"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Velg hvordan du vil installere ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "En nyere versjon av ${APPLICATION_NAME} er allerede installert! Det anbefales ikke at du installerer en eldre versjon. Hvis du virkelig ønsker å installere denne eldre versjonen, er det bedre å avinstallere gjeldende versjon først. Velg hva du vil gjøre og klikk Neste for å fortsette."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} er allerede installert.\nVelg hva du vil gjøre og klikk Neste for å fortsette."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} er installert allerede.$\n$\nVelg hva du ønsker å gjøre og klikk Neste for å fortsette."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Legg til/installer komponenter på nytt"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Avinstaller ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Avinstaller ${APPLICATION_NAME}"
|
||||
@@ -38,6 +38,6 @@ StrCpy $UAC_ERROR_ELEVATE "Klarte ikke
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Dette installasjonsprogrammet krever administrasjonstilgang. Prøv igjen"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "Installasjonsprogrammet kjører allerede."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Avinstallasjonsprogrammet krever administrasjonstilgang. Prøv igjen"
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Påloggingstjenesten kjører ikke, avbryter!"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Avinstallasjonsprogrammet kjører allerede."
|
||||
StrCpy $SectionGroup_Shortcuts "Snarveier"
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Logon service is not running, aborting!"
|
||||
|
||||
@@ -9,7 +9,6 @@ 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}"
|
||||
@@ -40,4 +39,5 @@ StrCpy $INIT_INSTALLER_RUNNING "Instalator ju
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Ten dezinstalator potrzebuje uprawnieñ administratora, spróbuj ponownie"
|
||||
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!"
|
||||
|
||||
@@ -9,7 +9,7 @@ StrCpy $PageReinstall_NEW_Field_3 "Não desinstale"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Já instalado"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Escolha como pretende instalar ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Uma versão mais recente do ${APPLICATION_NAME} já está instalada! Não é recomendada a instalação de uma versão mais antiga. Se realmente deseja instalar esta versão, aconselha-se a desinstalação da versão atual primeiro. Selecione a operação que deseja executar e clique em Avançar para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} já está instalado.\nSelecione a operação que deseja fazer, e clique Seguinte para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} já está instalada.\nSelecione a operação que deseja realizar e clique em 'Seguinte' para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Adicionar/Reinstalar Componentes"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Desinstalar ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalar ${APPLICATION_NAME}"
|
||||
|
||||
@@ -9,7 +9,7 @@ StrCpy $PageReinstall_NEW_Field_3 "N
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Já Instalado"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Escolha como você deseja instalar ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "A versão mais recente do ${APPLICATION_NAME} já está instalado! Não é recomendado que você instale uma versão mais antiga. Se você realmente deseja instalar esta versão mais antiga, é melhor desinstalar a versão atual primeiro. Selecione a operação que deseja executar e clique em Avançar para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${version} já está instalado. \nSelecione a operação que deseja executar e clique em Avançar para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} já está instalado.$\n$\nSelecione a operação que você quer realizar e clique Próximo para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Adicionar/reinstalar componentes"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Desinstalar ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalar ${APPLICATION_NAME}"
|
||||
|
||||
@@ -9,7 +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Выберите желаемое действие и нажмите Далее для продолжения."
|
||||
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}"
|
||||
|
||||
@@ -9,7 +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请选择想要执行的操作并点击下一步。"
|
||||
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}"
|
||||
|
||||
@@ -9,7 +9,6 @@ StrCpy $PageReinstall_NEW_Field_3 "Neodin
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Už je nainštalovaný"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Vyberte si, ako chcete nainštalova� ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Novšia verzia ${APPLICATION_NAME} je už nainštalovaná! Neodporúèam vám nainštalova� staršiu verziu. Ak naozaj chcete nainštalova� túto staršiu verziu, je lepšie najprv odinštalova� aktuálnu verziu. Vyberte operáciu, ktorú chcete vykona�, a kliknite na tlaèidlo Ïalej pre pokraèovanie."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} je už nainštalovaná.\nVyberte operáciu, ktorú chcete vykona�, a kliknite na tlaèidlo Ïalej pre pokraèovanie."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Prida�/Preinštalova� komponenty"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Odinštalova� ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Odinštalova� ${APPLICATION_NAME}"
|
||||
@@ -40,4 +39,5 @@ StrCpy $INIT_INSTALLER_RUNNING "In
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Tento odinštalátor vyžaduje admin prístup, skúste to znova"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Odinštalátor je už spustený."
|
||||
StrCpy $SectionGroup_Shortcuts "Zástupcovia"
|
||||
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!"
|
||||
|
||||
@@ -9,7 +9,6 @@ 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. Izberite opravilo in pritisnite gumb 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}"
|
||||
@@ -40,4 +39,5 @@ StrCpy $INIT_INSTALLER_RUNNING "Namestilnik je
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Program za odstranjevanje namestitve zahteva skrbniška dovoljenja."
|
||||
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!"
|
||||
|
||||
@@ -8,8 +8,8 @@ StrCpy $PageReinstall_NEW_Field_2 "Desinstalar antes de instalar"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "No desinstalar"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Ya está instalado"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Elija cómo quiere instalar ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Una nueva versión de ${APPLICATION_NAME} ya está instalada. No es recomendable instalar una versión anterior. Si realmente quiere instalar esta versión anterior, es mejor que desinstale la versión actual primero. Seleccione la operación que desea realizar y pulse Next para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} ya está instalada.\nSeleccione la operación que desea realizar y pulse Next para continuar."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Una nueva versión de ${APPLICATION_NAME} ya está instalada. No es recomendable instalar una versión anterior. Si realmente quiere instalar esta versión anterior, es mejor que desinstale la versión actual primero. Seleccione la operación que desea realizar y pulse Siguiente para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} ya está instalado.$\n$\nSeleccione la operación que desea realizar y haga click en Siguiente para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Añadir/Reinstalar componentes"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Desinstalar ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalar ${APPLICATION_NAME}"
|
||||
@@ -30,7 +30,7 @@ StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Lanzador R
|
||||
StrCpy $UNINSTALLER_FILE_Detail "Escribiendo desinstalador"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Escribiendo claves en el registro del instalador"
|
||||
StrCpy $UNINSTALLER_FINISHED_Detail "Terminado"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Parece que ${APPLICATION_NAME} no está instalado en el directorio '$INSTDIR'.$$ ¿Continuar de todos modos? (No Recomendado)"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Parece que ${APPLICATION_NAME} no está instalado en el directorio '$INSTDIR'.$$ ¿Continuar de todos modos? (No recomendado)"
|
||||
StrCpy $UNINSTALL_ABORT "Desinstalación cancelada por el usuario"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Atajo de inicio rápido (N/A)"
|
||||
StrCpy $INIT_NO_DESKTOP "Atajo de escritorio (sobreescribe el existente)"
|
||||
|
||||
@@ -30,7 +30,7 @@ StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Este des-instalador requiere acceso admin
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "El des-instalador ya esta corriendo"
|
||||
StrCpy $SectionGroup_Shortcuts "Accesos Directos"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Found ${APPLICATION_EXECUTABLE} process(s) which need to be stopped.$\nDo you want the installer to stop these for you?"
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.\r\nSelect the operation you want to perform and click Next to continue."
|
||||
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 $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Quick Launch Shortcut"
|
||||
|
||||
@@ -9,7 +9,6 @@ StrCpy $PageReinstall_NEW_Field_3 "Avinstallera inte"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Redan installerad"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Välj hur du vill installera ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "En nyare version av ${APPLICATION_NAME} är redan installerad! Det rekommenderas inte att du installerar en äldre version. Om du verkligen vill installera denna äldre versionen, är det bättre att du avinstallerar den nuvarande versionen först. Välj den åtgärd du vill utföra och klicka Nästa för att fortsätta."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} är redan installerad.\nVälj den åtgärd du vill utföra och klicka Nästa för att fortsätta."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Lägg till/Ominstallera komponenter"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Avinstallera ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Avinstallera ${APPLICATION_NAME}"
|
||||
@@ -38,6 +37,7 @@ 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 $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!"
|
||||
|
||||
@@ -9,7 +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} ได้ถูกติดตั้งแล้ว เลือกการดำเนินการที่คุณต้องการที่จะดำเนินการและคลิกถัดไปเพื่อดำเนินการต่อ"
|
||||
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,7 +9,7 @@ StrCpy $PageReinstall_NEW_Field_3 "Kald
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Zaten Yüklü"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "${APPLICATION_NAME} uygulamasýný nasýl yüklemek istediðinizi seçin."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "${APPLICATION_NAME} uygulamasýnýn daha yeni sürümü zaten yüklü! Daha eski bir sürümünü yüklemeniz önerilmez. Gerçekten bu eski sürümü yüklemek isterseniz, ilk olarak geçerli sürümü kaldýrmanýz tavsiye edilir. Yapmak istediðiniz iþlemi seçin ve devam etmek üzere Ýleri týklayýn."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} zaten yüklü.\n\nYapmak istediðiniz iþlemi seçin ve devam etmek için Ýleri týklayýn."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} zaten yüklü.$\n$\nYapmak istediðiniz iþlemi seçin ve devam etmek için Ýleri týklayýn."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Bileþenleri ekle/yeniden yükle"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "${APPLICATION_NAME} uygulamasýný kaldýr"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "${APPLICATION_NAME} uygulamasýný kaldýr"
|
||||
@@ -38,6 +38,6 @@ StrCpy $UAC_ERROR_ELEVATE "Y
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Bu yükleyici yönetici eriþimi gerektiriyor, yeniden deneyin"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "Yükleyici zaten çalýþýyor."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Bu kaldýrýcý yönetici eriþimi gerektiriyor, yeniden deneyin"
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Oturum açýlacak sunucu çalýþmadýðýndan iptal ediliyor!"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Kaldýrýcý zaten çalýþýyor."
|
||||
StrCpy $SectionGroup_Shortcuts "Kýsayollar"
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Logon service is not running, aborting!"
|
||||
|
||||
@@ -9,7 +9,6 @@ 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_SAME_Field_2 "Додати/Перевстановити компоненти"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Видалити ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Видалити ${APPLICATION_NAME}"
|
||||
@@ -40,4 +39,5 @@ StrCpy $INIT_INSTALLER_RUNNING "Установка вже запущена."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Для видалення потрібні права адміністратора, спробуйте ще раз"
|
||||
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!"
|
||||
|
||||
@@ -65,9 +65,9 @@ msgstr "A newer version of ${APPLICATION_NAME} is already installed! It is not r
|
||||
|
||||
#. PageReinstall_SAME_Field_1
|
||||
msgid ""
|
||||
"${APPLICATION_NAME} ${VERSION} is already installed.\r\n"
|
||||
"${APPLICATION_NAME} ${VERSION} is already installed.$\r$\n"
|
||||
"Select the operation you want to perform and click Next to continue."
|
||||
msgstr "${APPLICATION_NAME} ${VERSION} is already installed.\r\nSelect the operation you want to perform and click Next to continue."
|
||||
msgstr "${APPLICATION_NAME} ${VERSION} is already installed.$\r$\nSelect the operation you want to perform and click Next to continue."
|
||||
|
||||
#. PageReinstall_SAME_Field_2
|
||||
msgid "Add/Reinstall components"
|
||||
|
||||
@@ -20,5 +20,7 @@
|
||||
<file>resources/lock-https.png</file>
|
||||
<file>resources/lock-https@2x.png</file>
|
||||
<file>resources/account.png</file>
|
||||
<file>resources/more.png</file>
|
||||
<file>resources/delete.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -85,7 +85,7 @@ else(UNIX AND NOT WIN32)
|
||||
endif (UNIX AND NOT WIN32)
|
||||
|
||||
if (MSVC)
|
||||
# Use secure functions by defaualt and suppress warnings about
|
||||
# Use secure functions by default and suppress warnings about
|
||||
#"deprecated" functions
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
# - Try to find Neon
|
||||
# Once done this will define
|
||||
#
|
||||
# NEON_FOUND - system has Neon
|
||||
# NEON_INCLUDE_DIRS - the Neon include directory
|
||||
# NEON_LIBRARIES - Link these to use Neon
|
||||
# NEON_DEFINITIONS - Compiler switches required for using Neon
|
||||
#
|
||||
# Copyright (c) 2011-2013 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(_NEON neon)
|
||||
endif (PKG_CONFIG_FOUND)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
find_path(NEON_INCLUDE_DIRS
|
||||
NAMES
|
||||
neon/ne_basic.h
|
||||
HINTS
|
||||
${_NEON_INCLUDEDIR}
|
||||
${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
|
||||
find_library(NEON_LIBRARIES
|
||||
NAMES
|
||||
neon neon-27
|
||||
HINTS
|
||||
${_NEON_LIBDIR}
|
||||
${CMAKE_INSTALL_LIBDIR}
|
||||
${CMAKE_INSTALL_PREFIX}/lib
|
||||
${CMAKE_INSTALL_PREFIX}/lib64
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Neon DEFAULT_MSG NEON_LIBRARIES NEON_INCLUDE_DIRS)
|
||||
|
||||
# show the NEON_INCLUDE_DIRS and NEON_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(NEON_INCLUDE_DIRS NEON_LIBRARIES)
|
||||
|
||||
# Check if neon was compiled with LFS support, if so, the NE_LFS variable has to
|
||||
# be defined in the owncloud module.
|
||||
# If neon was not compiled with LFS its also ok since the underlying system
|
||||
# than probably supports large files anyway.
|
||||
IF( CMAKE_FIND_ROOT_PATH )
|
||||
FIND_PROGRAM( NEON_CONFIG_EXECUTABLE NAMES neon-config HINTS ${CMAKE_FIND_ROOT_PATH}/bin )
|
||||
ELSE( CMAKE_FIND_ROOT_PATH )
|
||||
FIND_PROGRAM( NEON_CONFIG_EXECUTABLE NAMES neon-config )
|
||||
ENDIF( CMAKE_FIND_ROOT_PATH )
|
||||
|
||||
IF ( NEON_CONFIG_EXECUTABLE )
|
||||
MESSAGE(STATUS "neon-config executable: ${NEON_CONFIG_EXECUTABLE}")
|
||||
# neon-config --support lfs
|
||||
EXECUTE_PROCESS( COMMAND ${NEON_CONFIG_EXECUTABLE} "--support" "lfs"
|
||||
RESULT_VARIABLE LFS
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE )
|
||||
|
||||
IF (LFS EQUAL 0)
|
||||
MESSAGE(STATUS "libneon has been compiled with LFS support")
|
||||
SET(NEON_WITH_LFS 1)
|
||||
ELSE (LFS EQUAL 0)
|
||||
MESSAGE(STATUS "libneon has not been compiled with LFS support, rely on OS")
|
||||
ENDIF (LFS EQUAL 0)
|
||||
ELSE ( NEON_CONFIG_EXECUTABLE )
|
||||
MESSAGE(STATUS, "neon-config could not be found.")
|
||||
ENDIF ( NEON_CONFIG_EXECUTABLE )
|
||||
@@ -134,13 +134,7 @@ if(NOT DEFINED CMAKE_INSTALL_LIBDIR OR (_libdir_set
|
||||
AND NOT CMAKE_CROSSCOMPILING)
|
||||
if (EXISTS "/etc/debian_version") # is this a debian system ?
|
||||
if(CMAKE_LIBRARY_ARCHITECTURE)
|
||||
if("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/?$")
|
||||
set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
|
||||
endif()
|
||||
if(DEFINED _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX
|
||||
AND "${_GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/?$")
|
||||
set(__LAST_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
|
||||
endif()
|
||||
set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
|
||||
endif()
|
||||
else() # not debian, rely on CMAKE_SIZEOF_VOID_P:
|
||||
if(NOT DEFINED CMAKE_SIZEOF_VOID_P)
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
!define QT_DLL_PATH "${MING_BIN}"
|
||||
!define ACCESSIBLE_DLL_PATH "${MING_LIB}/qt5/plugins/accessible"
|
||||
!define SQLITE_DLL_PATH "${MING_LIB}/qt5/plugins/sqldrivers"
|
||||
!define BEARER_DLL_PATH "${MING_LIB}/qt5/plugins/bearer"
|
||||
!define IMAGEFORMATS_DLL_PATH "${MING_LIB}/qt5/plugins/imageformats"
|
||||
!define PLATFORMS_DLL_PATH "${MING_LIB}/qt5/plugins/platforms"
|
||||
|
||||
@@ -107,7 +108,7 @@ ReserveFile "${NSISDIR}\Plugins\InstallOptions.dll"
|
||||
!define MEMENTO_REGISTRY_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPLICATION_NAME}"
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Modern User Interface (MUI) defintions and setup.
|
||||
; Modern User Interface (MUI) definitions and setup.
|
||||
;-----------------------------------------------------------------------------
|
||||
!define MUI_ABORTWARNING
|
||||
!define MUI_ICON ${NSI_PATH}\installer.ico
|
||||
@@ -406,6 +407,10 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
|
||||
SetOutPath "$INSTDIR\sqldrivers"
|
||||
File "${SQLITE_DLL_PATH}\qsqlite.dll"
|
||||
|
||||
SetOutPath "$INSTDIR\bearer"
|
||||
File "${BEARER_DLL_PATH}\qgenericbearer.dll"
|
||||
File "${BEARER_DLL_PATH}\qnativewifibearer.dll"
|
||||
|
||||
SetOutPath "$INSTDIR"
|
||||
;License & release notes.
|
||||
File "@CPACK_RESOURCE_FILE_LICENSE@"
|
||||
@@ -556,7 +561,7 @@ Section -post
|
||||
DetailPrint $UNINSTALLER_REGISTRY_Detail
|
||||
SetDetailsPrint listonly
|
||||
|
||||
;Version numbers used to detect existing installation version for comparisson.
|
||||
;Version numbers used to detect existing installation version for comparison.
|
||||
WriteRegStr HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "" $INSTDIR
|
||||
WriteRegDWORD HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "VersionMajor" "${VER_MAJOR}"
|
||||
WriteRegDWORD HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "VersionMinor" "${VER_MINOR}"
|
||||
|
||||
@@ -22,7 +22,9 @@ if( Qt5Core_FOUND )
|
||||
find_package(Qt5WebKitWidgets REQUIRED)
|
||||
find_package(Qt5WebKit REQUIRED)
|
||||
find_package(Qt5PrintSupport REQUIRED)
|
||||
find_package(Qt5Quick REQUIRED)
|
||||
if(NOT APPLE)
|
||||
find_package(Qt5Quick REQUIRED) # only needed on Windows because of OBS dependencies(?)
|
||||
endif()
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
if(APPLE)
|
||||
find_package(Qt5MacExtras REQUIRED)
|
||||
@@ -31,7 +33,9 @@ if( Qt5Core_FOUND )
|
||||
|
||||
else( Qt5Core_FOUND )
|
||||
if(WIN32 OR APPLE)
|
||||
if (NOT BUILD_WITH_QT4)
|
||||
message(FATAL_ERROR "Qt 5 not found, but application depends on Qt5 on Windows and Mac OS X")
|
||||
endif ()
|
||||
endif(WIN32 OR APPLE)
|
||||
endif( Qt5Core_FOUND )
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ IF (DOXYGEN_FOUND)
|
||||
# we need latex for doxygen because of the formulas
|
||||
FIND_PACKAGE(LATEX)
|
||||
IF (NOT LATEX_COMPILER)
|
||||
MESSAGE(STATUS "latex command LATEX_COMPILER not found but usually required. You will probably get warnings and user inetraction on doxy run.")
|
||||
MESSAGE(STATUS "latex command LATEX_COMPILER not found but usually required. You will probably get warnings and user interaction on doxy run.")
|
||||
ENDIF (NOT LATEX_COMPILER)
|
||||
IF (NOT MAKEINDEX_COMPILER)
|
||||
MESSAGE(STATUS "makeindex command MAKEINDEX_COMPILER not found but usually required.")
|
||||
|
||||
@@ -29,12 +29,12 @@ project=gets.chomp
|
||||
|
||||
printf("\n")
|
||||
|
||||
print("Other projects to includes (e.g. \"owutil tinyxml\", leave emtpy to skip): ")
|
||||
print("Other projects to include (e.g. \"owutil tinyxml\", leave emtpy to skip): ")
|
||||
otherprojects=gets.chomp
|
||||
|
||||
printf("\n")
|
||||
|
||||
print("Defininitions (leave empty to skip): ")
|
||||
print("Definitions (leave empty to skip): ")
|
||||
definitions=gets.chomp
|
||||
|
||||
cmakePublicIncDirName = project.upcase+"_PUBLIC_INCLUDE_DIRS"
|
||||
|
||||
@@ -23,8 +23,4 @@
|
||||
#cmakedefine SYSCONFDIR "@SYSCONFDIR@"
|
||||
#cmakedefine SHAREDIR "@SHAREDIR@"
|
||||
|
||||
#ifndef NEON_WITH_LFS
|
||||
#cmakedefine NEON_WITH_LFS "@NEON_WITH_LFS@"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,9 +21,9 @@ version 0.91.3 (released 2013-12-11, ownCloud Client 1.5.0rc1)
|
||||
version 0.91.2 (released 2013-12-10, ownCloud Client 1.5.0beta3)
|
||||
* have translatable error message for indiv. file errors.
|
||||
* Use uint64_t for inode on win32 to fix a type glitch.
|
||||
* Add test that directrories are properly moved.
|
||||
* Add test that directories are properly moved.
|
||||
* Handle symlinks correctly.
|
||||
* Do not longer recurse into ignored directories in update
|
||||
* No longer recurse into ignored directories in update
|
||||
phase.
|
||||
* Added proper symlink detection for win32 platform.
|
||||
|
||||
@@ -77,7 +77,7 @@ version 0.90.0 (released 2013-09-04, ownCloud Client 1.4.0)
|
||||
* Added c_rename function to csync std.
|
||||
* Fix: Do renames of files before any puts.
|
||||
* Improved database integrity checks.
|
||||
* Improvements of database writing efficiendy.
|
||||
* Improvements of database writing efficiency.
|
||||
* Fix: stat file on win32 even if its opened by application.
|
||||
* httpbf: configurable block size and threshold.
|
||||
* Many fixes found by a Coverity check.
|
||||
@@ -159,7 +159,7 @@ version 0.70.0 and 0.70.1 were beta versions.
|
||||
|
||||
version 0.60.2 (released 2012-11-26)
|
||||
* Migration to cross platform testing system cmocka.
|
||||
* Fixed variuos minor things incl. potential mem leaks.
|
||||
* Fixed various minor things incl. potential mem leaks.
|
||||
* Clang fixes.
|
||||
* Moved journal database to sync directory.
|
||||
* Fixed more csync->ocsync renaming issues.
|
||||
@@ -247,7 +247,7 @@ version 0.50.0 (released 2013-08-01)
|
||||
* Added new logging framework (removed log4c dependency).
|
||||
* Added new config parser (removed iniparser dependency).
|
||||
* Added cmocka tests.
|
||||
* Added a way to exported file_tree_walk functions.
|
||||
* Added a way to export file_tree_walk functions.
|
||||
* Added capabilities for modules.
|
||||
* Added possiblity to push information to the modules.
|
||||
* Added iconv support to support various char sets.
|
||||
|
||||
@@ -20,7 +20,7 @@ sqlite3 is a runtime requirement. libsmbclient is needed for
|
||||
the smb plugin, libssh for the sftp plugin. libneon is required for the
|
||||
ownCloud plugin.
|
||||
|
||||
Note that these version numbers are version we know works correctly. If you
|
||||
Note that these version numbers are versions we know work correctly. If you
|
||||
build and run csync successfully with an older version, please let us know.
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ CMake options using `cmakesetup` (Windows) or `ccmake` (GNU/Linux and MacOS X).
|
||||
|
||||
## Installing
|
||||
|
||||
Befor installing you can run the tests if everything is working:
|
||||
Before installing you can run the tests if everything is working:
|
||||
|
||||
make test
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ CONTRIBUTIONS
|
||||
=============
|
||||
|
||||
If you want to contribute to the development of the software then please join
|
||||
the mailing list. Patches are accepted preferebly created with git and we are
|
||||
the mailing list. Patches are accepted preferably created with git and we are
|
||||
always glad to receive feedback or suggestions to the address
|
||||
csync-devel@csync.org.
|
||||
More information on the various mailing lists can be found at
|
||||
|
||||
@@ -24,10 +24,6 @@
|
||||
#cmakedefine HAVE_ICONV 1
|
||||
#cmakedefine HAVE_ICONV_CONST 1
|
||||
|
||||
#ifndef NEON_WITH_LFS
|
||||
#cmakedefine NEON_WITH_LFS 1
|
||||
#endif
|
||||
|
||||
#cmakedefine HAVE___MINGW_ASPRINTF 1
|
||||
#cmakedefine HAVE_ASPRINTF 1
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
project(libcsync)
|
||||
|
||||
add_subdirectory(std)
|
||||
if(USE_NEON)
|
||||
add_subdirectory(httpbf)
|
||||
endif()
|
||||
|
||||
# Statically include sqlite
|
||||
|
||||
@@ -71,19 +68,6 @@ else()
|
||||
endif()
|
||||
|
||||
|
||||
if(USE_NEON)
|
||||
list(APPEND csync_SRCS
|
||||
csync_owncloud.c
|
||||
csync_owncloud_util.c
|
||||
)
|
||||
list(APPEND CSYNC_LINK_LIBRARIES
|
||||
${NEON_LIBRARIES}
|
||||
)
|
||||
include_directories(${NEON_INCLUDE_DIRS})
|
||||
add_definitions(-DUSE_NEON)
|
||||
endif(USE_NEON)
|
||||
|
||||
|
||||
configure_file(csync_version.h.in ${CMAKE_CURRENT_BINARY_DIR}/csync_version.h)
|
||||
|
||||
set(csync_HDRS
|
||||
|
||||
@@ -58,12 +58,6 @@
|
||||
#include "csync_rename.h"
|
||||
#include "c_jhash.h"
|
||||
|
||||
|
||||
#ifdef USE_NEON
|
||||
// Breaking the abstraction for fun and profit.
|
||||
#include "csync_owncloud.h"
|
||||
#endif
|
||||
|
||||
static int _key_cmp(const void *key, const void *data) {
|
||||
uint64_t a;
|
||||
csync_file_stat_t *b;
|
||||
@@ -154,9 +148,6 @@ int csync_init(CSYNC *ctx) {
|
||||
|
||||
ctx->local.type = LOCAL_REPLICA;
|
||||
|
||||
#ifdef USE_NEON
|
||||
owncloud_init(ctx);
|
||||
#endif
|
||||
ctx->remote.type = REMOTE_REPLICA;
|
||||
|
||||
if (c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp) < 0) {
|
||||
@@ -216,14 +207,6 @@ int csync_update(CSYNC *ctx) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "No exclude file loaded or defined!");
|
||||
}
|
||||
|
||||
#ifdef USE_NEON
|
||||
/* This is not actually connecting, just setting the info for neon. The legacy propagator can use it.. */
|
||||
if (dav_connect( ctx, ctx->remote.uri ) < 0) {
|
||||
ctx->status_code = CSYNC_STATUS_CONNECT_ERROR;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* update detection for local replica */
|
||||
csync_gettime(&start);
|
||||
ctx->current = LOCAL_REPLICA;
|
||||
@@ -646,10 +629,6 @@ int csync_destroy(CSYNC *ctx) {
|
||||
SAFE_FREE(ctx->remote.uri);
|
||||
SAFE_FREE(ctx->error_string);
|
||||
|
||||
#ifdef USE_NEON
|
||||
owncloud_destroy(ctx);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_ICONV
|
||||
c_close_iconv();
|
||||
#endif
|
||||
@@ -672,21 +651,6 @@ void csync_clear_exclude_list(CSYNC *ctx)
|
||||
csync_exclude_clear(ctx);
|
||||
}
|
||||
|
||||
int csync_set_auth_callback(CSYNC *ctx, csync_auth_callback cb) {
|
||||
if (ctx == NULL || cb == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ctx->status & CSYNC_STATUS_INIT) {
|
||||
ctx->status_code = CSYNC_STATUS_CSYNC_STATUS_ERROR;
|
||||
fprintf(stderr, "This function must be called before initialization.");
|
||||
return -1;
|
||||
}
|
||||
ctx->callbacks.auth_function = cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *csync_get_userdata(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return NULL;
|
||||
@@ -781,14 +745,3 @@ void csync_file_stat_free(csync_file_stat_t *st)
|
||||
SAFE_FREE(st);
|
||||
}
|
||||
}
|
||||
|
||||
int csync_set_module_property(CSYNC* ctx, const char* key, void* value)
|
||||
{
|
||||
#ifdef USE_NEON
|
||||
return owncloud_set_property(ctx, key, value);
|
||||
#else
|
||||
(void)ctx, (void)key, (void)value;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ enum csync_ftw_type_e {
|
||||
};
|
||||
|
||||
|
||||
#define FILE_ID_BUF_SIZE 21
|
||||
#define FILE_ID_BUF_SIZE 36
|
||||
|
||||
// currently specified at https://github.com/owncloud/core/issues/8322 are 9 to 10
|
||||
#define REMOTE_PERM_BUF_SIZE 15
|
||||
@@ -173,7 +173,7 @@ enum csync_vio_file_stat_fields_e {
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_TYPE = 1 << 0,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_MODE = 1 << 1, // local POSIX mode
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_FLAGS = 1 << 2,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_DEVICE = 1 << 3,
|
||||
// CSYNC_VIO_FILE_STAT_FIELDS_DEVICE = 1 << 3,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_INODE = 1 << 4,
|
||||
// CSYNC_VIO_FILE_STAT_FIELDS_LINK_COUNT = 1 << 5,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_SIZE = 1 << 6,
|
||||
@@ -212,7 +212,6 @@ struct csync_vio_file_stat_s {
|
||||
|
||||
mode_t mode;
|
||||
|
||||
dev_t device;
|
||||
uint64_t inode;
|
||||
|
||||
int fields; // actually enum csync_vio_file_stat_fields_e fields;
|
||||
@@ -519,19 +518,6 @@ const char *csync_get_status_string(CSYNC *ctx);
|
||||
int csync_set_iconv_codec(const char *from);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set a property to module
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*
|
||||
* @param key The property key
|
||||
*
|
||||
* @param value An opaque pointer to the data.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
*/
|
||||
int csync_set_module_property(CSYNC *ctx, const char *key, void *value);
|
||||
|
||||
/**
|
||||
* @brief Aborts the current sync run as soon as possible. Can be called from another thread.
|
||||
*
|
||||
|
||||
@@ -44,24 +44,7 @@
|
||||
static
|
||||
#endif
|
||||
int _csync_exclude_add(c_strlist_t **inList, const char *string) {
|
||||
c_strlist_t *list;
|
||||
|
||||
if (*inList == NULL) {
|
||||
*inList = c_strlist_new(32);
|
||||
if (*inList == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((*inList)->count == (*inList)->size) {
|
||||
list = c_strlist_expand(*inList, 2 * (*inList)->size);
|
||||
if (list == NULL) {
|
||||
return -1;
|
||||
}
|
||||
*inList = list;
|
||||
}
|
||||
|
||||
return c_strlist_add(*inList, string);
|
||||
return c_strlist_add_grow(inList, string);
|
||||
}
|
||||
|
||||
int csync_exclude_load(const char *fname, c_strlist_t **list) {
|
||||
@@ -186,19 +169,56 @@ bool csync_is_windows_reserved_word(const char* filename) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype) {
|
||||
size_t i = 0;
|
||||
const char *p = NULL;
|
||||
char *bname = NULL;
|
||||
char *dname = NULL;
|
||||
char *prev_dname = NULL;
|
||||
char *conflict = NULL;
|
||||
int rc = -1;
|
||||
CSYNC_EXCLUDE_TYPE match = CSYNC_NOT_EXCLUDED;
|
||||
CSYNC_EXCLUDE_TYPE type = CSYNC_NOT_EXCLUDED;
|
||||
static CSYNC_EXCLUDE_TYPE _csync_excluded_common(c_strlist_t *excludes, const char *path, int filetype, bool check_leading_dirs) {
|
||||
size_t i = 0;
|
||||
const char *bname = NULL;
|
||||
size_t blen = 0;
|
||||
char *conflict = NULL;
|
||||
int rc = -1;
|
||||
CSYNC_EXCLUDE_TYPE match = CSYNC_NOT_EXCLUDED;
|
||||
CSYNC_EXCLUDE_TYPE type = CSYNC_NOT_EXCLUDED;
|
||||
|
||||
/* split up the path */
|
||||
bname = strrchr(path, '/');
|
||||
if (bname) {
|
||||
bname += 1; // don't include the /
|
||||
} else {
|
||||
bname = path;
|
||||
}
|
||||
blen = strlen(bname);
|
||||
|
||||
rc = csync_fnmatch(".csync_journal.db*", bname, 0);
|
||||
if (rc == 0) {
|
||||
match = CSYNC_FILE_SILENTLY_EXCLUDED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// check the strlen and ignore the file if its name is longer than 254 chars.
|
||||
// whenever changing this also check createDownloadTmpFileName
|
||||
if (blen > 254) {
|
||||
match = CSYNC_FILE_EXCLUDE_LONG_FILENAME;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Windows cannot sync files ending in spaces (#2176). It also cannot
|
||||
// distinguish files ending in '.' from files without an ending,
|
||||
// as '.' is a separator that is not stored internally, so let's
|
||||
// not allow to sync those to avoid file loss/ambiguities (#416)
|
||||
if (blen > 1 && (bname[blen-1]== ' ' || bname[blen-1]== '.' )) {
|
||||
match = CSYNC_FILE_EXCLUDE_INVALID_CHAR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (csync_is_windows_reserved_word(bname)) {
|
||||
match = CSYNC_FILE_EXCLUDE_INVALID_CHAR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Filter out characters not allowed in a filename on windows
|
||||
const char *p = NULL;
|
||||
for (p = path; *p; p++) {
|
||||
switch (*p) {
|
||||
switch (*p) {
|
||||
case '\\':
|
||||
case ':':
|
||||
case '?':
|
||||
@@ -207,189 +227,146 @@ CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path
|
||||
case '>':
|
||||
case '<':
|
||||
case '|':
|
||||
return CSYNC_FILE_EXCLUDE_INVALID_CHAR;
|
||||
match = CSYNC_FILE_EXCLUDE_INVALID_CHAR;
|
||||
goto out;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* split up the path */
|
||||
dname = c_dirname(path);
|
||||
bname = c_basename(path);
|
||||
|
||||
if (bname == NULL || dname == NULL) {
|
||||
match = CSYNC_NOT_EXCLUDED;
|
||||
SAFE_FREE(bname);
|
||||
SAFE_FREE(dname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = csync_fnmatch(".csync_journal.db*", bname, 0);
|
||||
if (rc == 0) {
|
||||
match = CSYNC_FILE_SILENTLY_EXCLUDED;
|
||||
SAFE_FREE(bname);
|
||||
SAFE_FREE(dname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
// check the strlen and ignore the file if its name is longer than 254 chars.
|
||||
// whenever changing this also check createDownloadTmpFileName
|
||||
if (strlen(bname) > 254) {
|
||||
match = CSYNC_FILE_EXCLUDE_LONG_FILENAME;
|
||||
SAFE_FREE(bname);
|
||||
SAFE_FREE(dname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Windows cannot sync files ending in spaces (#2176). It also cannot
|
||||
// distinguish files ending in '.' from files without an ending,
|
||||
// as '.' is a separator that is not stored internally, so let's
|
||||
// not allow to sync those to avoid file loss/ambiguities (#416)
|
||||
size_t blen = strlen(bname);
|
||||
if (blen > 1 && (bname[blen-1]== ' ' || bname[blen-1]== '.' )) {
|
||||
match = CSYNC_FILE_EXCLUDE_INVALID_CHAR;
|
||||
SAFE_FREE(bname);
|
||||
SAFE_FREE(dname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (csync_is_windows_reserved_word(bname)) {
|
||||
match = CSYNC_FILE_EXCLUDE_INVALID_CHAR;
|
||||
SAFE_FREE(bname);
|
||||
SAFE_FREE(dname);
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = csync_fnmatch(".owncloudsync.log*", bname, 0);
|
||||
if (rc == 0) {
|
||||
match = CSYNC_FILE_SILENTLY_EXCLUDED;
|
||||
SAFE_FREE(bname);
|
||||
SAFE_FREE(dname);
|
||||
goto out;
|
||||
}
|
||||
rc = csync_fnmatch(".owncloudsync.log*", bname, 0);
|
||||
if (rc == 0) {
|
||||
match = CSYNC_FILE_SILENTLY_EXCLUDED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Always ignore conflict files, not only via the exclude list */
|
||||
rc = csync_fnmatch("*_conflict-*", bname, 0);
|
||||
if (rc == 0) {
|
||||
match = CSYNC_FILE_SILENTLY_EXCLUDED;
|
||||
SAFE_FREE(bname);
|
||||
SAFE_FREE(dname);
|
||||
goto out;
|
||||
}
|
||||
/* Always ignore conflict files, not only via the exclude list */
|
||||
rc = csync_fnmatch("*_conflict-*", bname, 0);
|
||||
if (rc == 0) {
|
||||
match = CSYNC_FILE_SILENTLY_EXCLUDED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (getenv("CSYNC_CONFLICT_FILE_USERNAME")) {
|
||||
rc = asprintf(&conflict, "*_conflict_%s-*", getenv("CSYNC_CONFLICT_FILE_USERNAME"));
|
||||
if (rc < 0) {
|
||||
SAFE_FREE(bname);
|
||||
SAFE_FREE(dname);
|
||||
goto out;
|
||||
}
|
||||
rc = csync_fnmatch(conflict, path, 0);
|
||||
if (rc == 0) {
|
||||
match = CSYNC_FILE_SILENTLY_EXCLUDED;
|
||||
SAFE_FREE(conflict);
|
||||
SAFE_FREE(bname);
|
||||
SAFE_FREE(dname);
|
||||
goto out;
|
||||
}
|
||||
SAFE_FREE(conflict);
|
||||
}
|
||||
if (getenv("CSYNC_CONFLICT_FILE_USERNAME")) {
|
||||
rc = asprintf(&conflict, "*_conflict_%s-*", getenv("CSYNC_CONFLICT_FILE_USERNAME"));
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
rc = csync_fnmatch(conflict, path, 0);
|
||||
if (rc == 0) {
|
||||
match = CSYNC_FILE_SILENTLY_EXCLUDED;
|
||||
SAFE_FREE(conflict);
|
||||
goto out;
|
||||
}
|
||||
SAFE_FREE(conflict);
|
||||
}
|
||||
|
||||
SAFE_FREE(bname);
|
||||
SAFE_FREE(dname);
|
||||
if( ! excludes ) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if( ! excludes ) {
|
||||
goto out;
|
||||
}
|
||||
c_strlist_t *path_components = NULL;
|
||||
if (check_leading_dirs) {
|
||||
/* Build a list of path components to check. */
|
||||
path_components = c_strlist_new(32);
|
||||
char *path_split = strdup(path);
|
||||
size_t len = strlen(path_split);
|
||||
for (i = len; ; --i) {
|
||||
// read backwards until a path separator is found
|
||||
if (i != 0 && path_split[i-1] != '/') {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Loop over all exclude patterns and evaluate the given path */
|
||||
for (i = 0; match == CSYNC_NOT_EXCLUDED && i < excludes->count; i++) {
|
||||
bool match_dirs_only = false;
|
||||
char *pattern_stored = c_strdup(excludes->vector[i]);
|
||||
char* pattern = pattern_stored;
|
||||
// check 'basename', i.e. for "/foo/bar/fi" we'd check 'fi', 'bar', 'foo'
|
||||
if (path_split[i] != 0) {
|
||||
c_strlist_add_grow(&path_components, path_split + i);
|
||||
}
|
||||
|
||||
type = CSYNC_FILE_EXCLUDE_LIST;
|
||||
if (strlen(pattern) < 1) {
|
||||
SAFE_FREE(pattern_stored);
|
||||
continue;
|
||||
}
|
||||
/* Ecludes starting with ']' means it can be cleanup */
|
||||
if (pattern[0] == ']') {
|
||||
++pattern;
|
||||
if (filetype == CSYNC_FTW_TYPE_FILE) {
|
||||
type = CSYNC_FILE_EXCLUDE_AND_REMOVE;
|
||||
}
|
||||
}
|
||||
/* Check if the pattern applies to pathes only. */
|
||||
if (pattern[strlen(pattern)-1] == '/') {
|
||||
match_dirs_only = true;
|
||||
pattern[strlen(pattern)-1] = '\0'; /* Cut off the slash */
|
||||
}
|
||||
if (i == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* check if the pattern contains a / and if, compare to the whole path */
|
||||
if (strchr(pattern, '/')) {
|
||||
rc = csync_fnmatch(pattern, path, FNM_PATHNAME);
|
||||
if( rc == 0 ) {
|
||||
match = type;
|
||||
}
|
||||
/* if the pattern requires a dir, but path is not, its still not excluded. */
|
||||
if (match_dirs_only && filetype != CSYNC_FTW_TYPE_DIR) {
|
||||
match = CSYNC_NOT_EXCLUDED;
|
||||
}
|
||||
}
|
||||
// check 'dirname', i.e. for "/foo/bar/fi" we'd check '/foo/bar', '/foo'
|
||||
path_split[i-1] = '\0';
|
||||
c_strlist_add_grow(&path_components, path_split);
|
||||
}
|
||||
SAFE_FREE(path_split);
|
||||
}
|
||||
|
||||
/* if still not excluded, check each component of the path */
|
||||
if (match == CSYNC_NOT_EXCLUDED) {
|
||||
int trailing_component = 1;
|
||||
dname = c_dirname(path);
|
||||
bname = c_basename(path);
|
||||
/* Loop over all exclude patterns and evaluate the given path */
|
||||
for (i = 0; match == CSYNC_NOT_EXCLUDED && i < excludes->count; i++) {
|
||||
bool match_dirs_only = false;
|
||||
char *pattern = excludes->vector[i];
|
||||
|
||||
if (bname == NULL || dname == NULL) {
|
||||
match = CSYNC_NOT_EXCLUDED;
|
||||
SAFE_FREE(bname);
|
||||
SAFE_FREE(dname);
|
||||
SAFE_FREE(pattern_stored);
|
||||
goto out;
|
||||
}
|
||||
type = CSYNC_FILE_EXCLUDE_LIST;
|
||||
if (!pattern[0]) { /* empty pattern */
|
||||
continue;
|
||||
}
|
||||
/* Excludes starting with ']' means it can be cleanup */
|
||||
if (pattern[0] == ']') {
|
||||
++pattern;
|
||||
if (filetype == CSYNC_FTW_TYPE_FILE) {
|
||||
type = CSYNC_FILE_EXCLUDE_AND_REMOVE;
|
||||
}
|
||||
}
|
||||
/* Check if the pattern applies to pathes only. */
|
||||
if (pattern[strlen(pattern)-1] == '/') {
|
||||
if (!check_leading_dirs && filetype == CSYNC_FTW_TYPE_FILE) {
|
||||
continue;
|
||||
}
|
||||
match_dirs_only = true;
|
||||
pattern[strlen(pattern)-1] = '\0'; /* Cut off the slash */
|
||||
}
|
||||
|
||||
/* Check each component of the path */
|
||||
do {
|
||||
/* Do not check the bname if its a file and the pattern matches dirs only. */
|
||||
if ( !(trailing_component == 1 /* it is the trailing component */
|
||||
&& match_dirs_only /* but only directories are matched by the pattern */
|
||||
&& filetype == CSYNC_FTW_TYPE_FILE) ) {
|
||||
/* Check the name component against the pattern */
|
||||
rc = csync_fnmatch(pattern, bname, 0);
|
||||
if (rc == 0) {
|
||||
match = type;
|
||||
}
|
||||
}
|
||||
if (!(c_streq(dname, ".") || c_streq(dname, "/"))) {
|
||||
rc = csync_fnmatch(pattern, dname, 0);
|
||||
if (rc == 0) {
|
||||
match = type;
|
||||
}
|
||||
}
|
||||
trailing_component = 0;
|
||||
prev_dname = dname;
|
||||
SAFE_FREE(bname);
|
||||
bname = c_basename(prev_dname);
|
||||
dname = c_dirname(prev_dname);
|
||||
SAFE_FREE(prev_dname);
|
||||
/* check if the pattern contains a / and if, compare to the whole path */
|
||||
if (strchr(pattern, '/')) {
|
||||
rc = csync_fnmatch(pattern, path, FNM_PATHNAME);
|
||||
if( rc == 0 ) {
|
||||
match = type;
|
||||
}
|
||||
/* if the pattern requires a dir, but path is not, its still not excluded. */
|
||||
if (match_dirs_only && filetype != CSYNC_FTW_TYPE_DIR) {
|
||||
match = CSYNC_NOT_EXCLUDED;
|
||||
}
|
||||
}
|
||||
|
||||
} while( match == CSYNC_NOT_EXCLUDED && !c_streq(dname, ".")
|
||||
&& !c_streq(dname, "/") );
|
||||
}
|
||||
SAFE_FREE(pattern_stored);
|
||||
SAFE_FREE(bname);
|
||||
SAFE_FREE(dname);
|
||||
}
|
||||
/* if still not excluded, check each component and leading directory of the path */
|
||||
if (match == CSYNC_NOT_EXCLUDED && check_leading_dirs) {
|
||||
size_t j = 0;
|
||||
if (match_dirs_only && filetype == CSYNC_FTW_TYPE_FILE) {
|
||||
j = 1; // skip the first entry, which is bname
|
||||
}
|
||||
for (; j < path_components->count; ++j) {
|
||||
rc = csync_fnmatch(pattern, path_components->vector[j], 0);
|
||||
if (rc == 0) {
|
||||
match = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (match == CSYNC_NOT_EXCLUDED && !check_leading_dirs) {
|
||||
rc = csync_fnmatch(pattern, bname, 0);
|
||||
if (rc == 0) {
|
||||
match = type;
|
||||
}
|
||||
}
|
||||
if (match_dirs_only) {
|
||||
/* restore the '/' */
|
||||
pattern[strlen(pattern)] = '/';
|
||||
}
|
||||
}
|
||||
c_strlist_destroy(path_components);
|
||||
|
||||
out:
|
||||
|
||||
out:
|
||||
|
||||
return match;
|
||||
return match;
|
||||
}
|
||||
|
||||
CSYNC_EXCLUDE_TYPE csync_excluded_traversal(c_strlist_t *excludes, const char *path, int filetype) {
|
||||
return _csync_excluded_common(excludes, path, filetype, false);
|
||||
}
|
||||
|
||||
CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype) {
|
||||
return _csync_excluded_common(excludes, path, filetype, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,11 @@ void csync_exclude_destroy(CSYNC *ctx);
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
@@ -73,6 +78,23 @@ void csync_exclude_destroy(CSYNC *ctx);
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* It does only part of the work that csync_excluded does because it's assumed
|
||||
* that all leading directories have been run through csync_excluded_traversal()
|
||||
* before. This can be significantly faster.
|
||||
*
|
||||
* That means for '/foo/bar/file' only ('/foo/bar/file', 'file') is checked
|
||||
* against the exclude patterns.
|
||||
*
|
||||
* @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_traversal(c_strlist_t *excludes, const char *path, int filetype);
|
||||
|
||||
/**
|
||||
* @brief csync_excluded_no_ctx
|
||||
* @param excludes
|
||||
|
||||
@@ -57,20 +57,13 @@ int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags) {
|
||||
#else /* HAVE_FNMATCH */
|
||||
|
||||
#include <shlwapi.h>
|
||||
int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags) {
|
||||
wchar_t *pat = NULL;
|
||||
wchar_t *name = NULL;
|
||||
int csync_fnmatch(const char *pattern, const char *name, int flags) {
|
||||
BOOL match;
|
||||
|
||||
(void) __flags;
|
||||
(void) flags;
|
||||
|
||||
name = c_utf8_string_to_locale(__name);
|
||||
pat = c_utf8_string_to_locale(__pattern);
|
||||
match = PathMatchSpecA(name, pattern);
|
||||
|
||||
match = PathMatchSpecW(name, pat);
|
||||
|
||||
c_free_locale_string(pat);
|
||||
c_free_locale_string(name);
|
||||
if(match)
|
||||
return 0;
|
||||
else
|
||||
|
||||
@@ -1,617 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2011 by Andreas Schneider <asn@cryptomilk.org>
|
||||
* Copyright (c) 2012 by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "csync_owncloud.h"
|
||||
#include "csync_owncloud_private.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "csync_private.h"
|
||||
|
||||
#include "csync_version.h"
|
||||
|
||||
|
||||
/*
|
||||
* helper method to build up a user text for SSL problems, called from the
|
||||
* verify_sslcert callback.
|
||||
*/
|
||||
static void addSSLWarning( char *ptr, const char *warn, int len )
|
||||
{
|
||||
char *concatHere = ptr;
|
||||
int remainingLen = 0;
|
||||
|
||||
if( ! (warn && ptr )) return;
|
||||
remainingLen = len - strlen(ptr);
|
||||
if( remainingLen <= 0 ) return;
|
||||
concatHere = ptr + strlen(ptr); /* put the write pointer to the end. */
|
||||
strncpy( concatHere, warn, remainingLen );
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback to verify the SSL certificate, called from libneon.
|
||||
* It analyzes the SSL problem, creates a user information text and passes
|
||||
* it to the csync callback to ask the user.
|
||||
*/
|
||||
#define LEN 4096
|
||||
static int ssl_callback_by_neon(void *userdata, int failures,
|
||||
const ne_ssl_certificate *certificate)
|
||||
{
|
||||
char problem[LEN];
|
||||
char buf[MAX(NE_SSL_DIGESTLEN, NE_ABUFSIZ)];
|
||||
int ret = -1;
|
||||
const ne_ssl_certificate *cert = certificate;
|
||||
csync_auth_callback authcb = NULL;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
|
||||
memset( problem, 0, LEN );
|
||||
|
||||
while( cert ) {
|
||||
|
||||
addSSLWarning( problem, "There are problems with the SSL certificate:\n", LEN );
|
||||
if( failures & NE_SSL_NOTYETVALID ) {
|
||||
addSSLWarning( problem, " * The certificate is not yet valid.\n", LEN );
|
||||
}
|
||||
if( failures & NE_SSL_EXPIRED ) {
|
||||
addSSLWarning( problem, " * The certificate has expired.\n", LEN );
|
||||
}
|
||||
|
||||
if( failures & NE_SSL_UNTRUSTED ) {
|
||||
addSSLWarning( problem, " * The certificate is not trusted!\n", LEN );
|
||||
}
|
||||
if( failures & NE_SSL_IDMISMATCH ) {
|
||||
addSSLWarning( problem, " * The hostname for which the certificate was "
|
||||
"issued does not match the hostname of the server\n", LEN );
|
||||
}
|
||||
if( failures & NE_SSL_BADCHAIN ) {
|
||||
addSSLWarning( problem, " * The certificate chain contained a certificate other than the server cert\n", LEN );
|
||||
}
|
||||
if( failures & NE_SSL_REVOKED ) {
|
||||
addSSLWarning( problem, " * The server certificate has been revoked by the issuing authority.\n", LEN );
|
||||
}
|
||||
|
||||
if (ne_ssl_cert_digest(cert, buf) == 0) {
|
||||
addSSLWarning( problem, "Certificate fingerprint: ", LEN );
|
||||
addSSLWarning( problem, buf, LEN );
|
||||
addSSLWarning( problem, "\n", LEN );
|
||||
}
|
||||
cert = ne_ssl_cert_signedby( cert );
|
||||
}
|
||||
addSSLWarning( problem, "Do you want to accept the certificate chain anyway?\nAnswer yes to do so and take the risk: ", LEN );
|
||||
|
||||
if( ctx->csync_ctx ) {
|
||||
authcb = csync_get_auth_callback( ctx->csync_ctx );
|
||||
}
|
||||
if( authcb ){
|
||||
/* call the csync callback */
|
||||
DEBUG_WEBDAV("Call the csync callback for SSL problems");
|
||||
memset( buf, 0, NE_ABUFSIZ );
|
||||
(*authcb) ( problem, buf, NE_ABUFSIZ-1, 1, 0, csync_get_userdata(ctx->csync_ctx) );
|
||||
if( buf[0] == 'y' || buf[0] == 'Y') {
|
||||
ret = 0;
|
||||
} else {
|
||||
DEBUG_WEBDAV("Authentication callback replied %s", buf );
|
||||
|
||||
}
|
||||
}
|
||||
DEBUG_WEBDAV("## VERIFY_SSL CERT: %d", ret );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Authentication callback. Is set by ne_set_server_auth to be called
|
||||
* from the neon lib to authenticate a request.
|
||||
*/
|
||||
static int authentication_callback_by_neon( void *userdata, const char *realm, int attempt,
|
||||
char *username, char *password)
|
||||
{
|
||||
char buf[NE_ABUFSIZ];
|
||||
csync_auth_callback authcb = NULL;
|
||||
int re = attempt;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
|
||||
(void) realm;
|
||||
|
||||
/* DEBUG_WEBDAV( "Authentication required %s", realm ); */
|
||||
if( username && password ) {
|
||||
DEBUG_WEBDAV( "Authentication required %s", username );
|
||||
if( ctx->dav_session.user ) {
|
||||
/* allow user without password */
|
||||
if( strlen( ctx->dav_session.user ) < NE_ABUFSIZ ) {
|
||||
strcpy( username, ctx->dav_session.user );
|
||||
}
|
||||
if( ctx->dav_session.pwd && strlen( ctx->dav_session.pwd ) < NE_ABUFSIZ ) {
|
||||
strcpy( password, ctx->dav_session.pwd );
|
||||
}
|
||||
} else {
|
||||
authcb = csync_get_auth_callback( ctx->csync_ctx );
|
||||
if( authcb != NULL ){
|
||||
/* call the csync callback */
|
||||
DEBUG_WEBDAV("Call the csync callback for %s", realm );
|
||||
memset( buf, 0, NE_ABUFSIZ );
|
||||
(*authcb) ("Enter your username: ", buf, NE_ABUFSIZ-1, 1, 0, csync_get_userdata(ctx->csync_ctx) );
|
||||
if( strlen(buf) < NE_ABUFSIZ ) {
|
||||
strcpy( username, buf );
|
||||
}
|
||||
memset( buf, 0, NE_ABUFSIZ );
|
||||
(*authcb) ("Enter your password: ", buf, NE_ABUFSIZ-1, 0, 0, csync_get_userdata(ctx->csync_ctx) );
|
||||
if( strlen(buf) < NE_ABUFSIZ) {
|
||||
strcpy( password, buf );
|
||||
}
|
||||
} else {
|
||||
re = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return re;
|
||||
}
|
||||
|
||||
/*
|
||||
* Authentication callback. Is set by ne_set_proxy_auth to be called
|
||||
* from the neon lib to authenticate against a proxy. The data to authenticate
|
||||
* against comes from mirall throught vio_module_init function.
|
||||
*/
|
||||
static int proxy_authentication_callback_by_neon( void *userdata, const char *realm, int attempt,
|
||||
char *username, char *password)
|
||||
{
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
(void) realm;
|
||||
if( ctx->dav_session.proxy_user && strlen( ctx->dav_session.proxy_user ) < NE_ABUFSIZ) {
|
||||
strcpy( username, ctx->dav_session.proxy_user );
|
||||
if( ctx->dav_session.proxy_pwd && strlen( ctx->dav_session.proxy_pwd ) < NE_ABUFSIZ) {
|
||||
strcpy( password, ctx->dav_session.proxy_pwd );
|
||||
}
|
||||
}
|
||||
/* NTLM needs several attempts */
|
||||
return (attempt < 3) ? 0 : -1;
|
||||
}
|
||||
|
||||
/* Configure the proxy depending on the variables */
|
||||
static int configureProxy( csync_owncloud_ctx_t *ctx, ne_session *session )
|
||||
{
|
||||
int port = 8080;
|
||||
int re = -1;
|
||||
|
||||
if( ! session ) return -1;
|
||||
if( ! ctx->dav_session.proxy_type ) return 0; /* Go by NoProxy per default */
|
||||
|
||||
if( ctx->dav_session.proxy_port > 0 ) {
|
||||
port = ctx->dav_session.proxy_port;
|
||||
}
|
||||
|
||||
if( c_streq(ctx->dav_session.proxy_type, "NoProxy" )) {
|
||||
DEBUG_WEBDAV("No proxy configured.");
|
||||
re = 0;
|
||||
} else if( c_streq(ctx->dav_session.proxy_type, "DefaultProxy") ||
|
||||
c_streq(ctx->dav_session.proxy_type, "HttpProxy") ||
|
||||
c_streq(ctx->dav_session.proxy_type, "HttpCachingProxy") ||
|
||||
c_streq(ctx->dav_session.proxy_type, "Socks5Proxy")) {
|
||||
|
||||
if( ctx->dav_session.proxy_host ) {
|
||||
DEBUG_WEBDAV("%s at %s:%d", ctx->dav_session.proxy_type, ctx->dav_session.proxy_host, port );
|
||||
if (c_streq(ctx->dav_session.proxy_type, "Socks5Proxy")) {
|
||||
ne_session_socks_proxy(session, NE_SOCK_SOCKSV5, ctx->dav_session.proxy_host, port,
|
||||
ctx->dav_session.proxy_user, ctx->dav_session.proxy_pwd);
|
||||
} else {
|
||||
ne_session_proxy(session, ctx->dav_session.proxy_host, port );
|
||||
}
|
||||
re = 2;
|
||||
} else {
|
||||
DEBUG_WEBDAV("%s requested but no proxy host defined.", ctx->dav_session.proxy_type );
|
||||
/* we used to try ne_system_session_proxy here, but we should rather err out
|
||||
to behave exactly like the caller. */
|
||||
}
|
||||
} else {
|
||||
DEBUG_WEBDAV( "Unsupported Proxy: %s", ctx->dav_session.proxy_type );
|
||||
}
|
||||
|
||||
return re;
|
||||
}
|
||||
|
||||
/*
|
||||
* This hook is called for with the response of a request. Here its checked
|
||||
* if a Set-Cookie header is there for the PHPSESSID. The key is stored into
|
||||
* the webdav session to be added to subsequent requests.
|
||||
*/
|
||||
static void post_request_hook(ne_request *req, void *userdata, const ne_status *status)
|
||||
{
|
||||
const char *set_cookie_header = NULL;
|
||||
const char *sc = NULL;
|
||||
char *key = NULL;
|
||||
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
|
||||
if (ctx->dav_session.session_key)
|
||||
return; /* We already have a session cookie, and we should ignore other ones */
|
||||
|
||||
if(!(status && req)) return;
|
||||
if( status->klass == 2 || status->code == 401 ) {
|
||||
/* successful request */
|
||||
set_cookie_header = ne_get_response_header( req, "Set-Cookie" );
|
||||
if( set_cookie_header ) {
|
||||
DEBUG_WEBDAV(" Set-Cookie found: %s", set_cookie_header);
|
||||
/* try to find a ', ' sequence which is the separator of neon if multiple Set-Cookie
|
||||
* headers are there.
|
||||
* The following code parses a string like this:
|
||||
* Set-Cookie: 50ace6bd8a669=p537brtt048jh8srlp2tuep7em95nh9u98mj992fbqc47d1aecp1;
|
||||
*/
|
||||
sc = set_cookie_header;
|
||||
while(sc) {
|
||||
const char *sc_val = sc;
|
||||
const char *sc_end = sc_val;
|
||||
int cnt = 0;
|
||||
int len = strlen(sc_val); /* The length of the rest of the header string. */
|
||||
|
||||
while( cnt < len && *sc_end != ';' && *sc_end != ',') {
|
||||
cnt++;
|
||||
sc_end++;
|
||||
}
|
||||
if( cnt == len ) {
|
||||
/* exit: We are at the end. */
|
||||
sc = NULL;
|
||||
} else if( *sc_end == ';' ) {
|
||||
/* We are at the end of the session key. */
|
||||
int keylen = sc_end-sc_val;
|
||||
if( key ) {
|
||||
int oldlen = strlen(key);
|
||||
key = c_realloc(key, oldlen + 2 + keylen+1);
|
||||
strcpy(key + oldlen, "; ");
|
||||
strncpy(key + oldlen + 2, sc_val, keylen);
|
||||
key[oldlen + 2 + keylen] = '\0';
|
||||
} else {
|
||||
key = c_malloc(keylen+1);
|
||||
strncpy( key, sc_val, keylen );
|
||||
key[keylen] = '\0';
|
||||
}
|
||||
|
||||
/* now search for a ',' to find a potential other header entry */
|
||||
while(cnt < len && *sc_end != ',') {
|
||||
cnt++;
|
||||
sc_end++;
|
||||
}
|
||||
if( cnt < len )
|
||||
sc = sc_end+2; /* mind the space after the comma */
|
||||
else
|
||||
sc = NULL;
|
||||
} else if( *sc_end == ',' ) {
|
||||
/* A new entry is to check. */
|
||||
if( *(sc_end + 1) == ' ') {
|
||||
sc = sc_end+2;
|
||||
} else {
|
||||
/* error condition */
|
||||
sc = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DEBUG_WEBDAV("Request failed, don't take session header.");
|
||||
}
|
||||
if( key ) {
|
||||
DEBUG_WEBDAV("----> Session-key: %s", key);
|
||||
SAFE_FREE(ctx->dav_session.session_key);
|
||||
ctx->dav_session.session_key = key;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* this hook is called just after a request has been created, before its sent.
|
||||
* Here it is used to set the proxy connection header if available.
|
||||
*/
|
||||
static void request_created_hook(ne_request *req, void *userdata,
|
||||
const char *method, const char *requri)
|
||||
{
|
||||
// FIXME Can possibly be merged with pre_send_hook
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t *) userdata;
|
||||
(void) method;
|
||||
(void) requri;
|
||||
|
||||
if( !req ) return;
|
||||
|
||||
if(ctx->dav_session.proxy_type) {
|
||||
/* required for NTLM */
|
||||
ne_add_request_header(req, "Proxy-Connection", "Keep-Alive");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* this hook is called just before a request has been sent.
|
||||
* Here it is used to set the session cookie if available.
|
||||
*/
|
||||
static void pre_send_hook(ne_request *req, void *userdata,
|
||||
ne_buffer *header)
|
||||
{
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t *) userdata;
|
||||
|
||||
if( !req ) return;
|
||||
|
||||
if(ctx->dav_session.session_key) {
|
||||
ne_buffer_concat(header, "Cookie: ", ctx->dav_session.session_key, "\r\n", NULL);
|
||||
} else {
|
||||
DEBUG_WEBDAV("csync pre_send_hook We don't have a Auth Cookie (session_key), this is wrong!");
|
||||
}
|
||||
}
|
||||
|
||||
static int post_send_hook(ne_request *req, void *userdata,
|
||||
const ne_status *status)
|
||||
{
|
||||
const char *location;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t *) userdata;
|
||||
(void) status;
|
||||
|
||||
location = ne_get_response_header(req, "Location");
|
||||
|
||||
if( !location ) return NE_OK;
|
||||
|
||||
if( ctx->dav_session.redir_callback ) {
|
||||
if( ctx->dav_session.redir_callback( ctx->csync_ctx, location ) ) {
|
||||
return NE_REDIRECT;
|
||||
} else {
|
||||
return NE_RETRY;
|
||||
}
|
||||
}
|
||||
|
||||
return NE_REDIRECT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Connect to a DAV server
|
||||
* This function sets the flag _connected if the connection is established
|
||||
* and returns if the flag is set, so calling it frequently is save.
|
||||
*/
|
||||
int dav_connect(CSYNC *csyncCtx, const char *base_url) {
|
||||
int useSSL = 0;
|
||||
int rc;
|
||||
char protocol[6] = {'\0'};
|
||||
char uaBuf[256];
|
||||
char *path = NULL;
|
||||
char *scheme = NULL;
|
||||
char *host = NULL;
|
||||
unsigned int port = 0;
|
||||
int proxystate = -1;
|
||||
csync_owncloud_ctx_t *ctx = csyncCtx->owncloud_context;
|
||||
struct csync_client_certs_s* clientCerts = csyncCtx->clientCerts;
|
||||
|
||||
if (ctx->_connected) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = c_parse_uri( base_url, &scheme,
|
||||
&ctx->dav_session.user,
|
||||
&ctx->dav_session.pwd,
|
||||
&host, &port, &path );
|
||||
if( rc < 0 ) {
|
||||
DEBUG_WEBDAV("Failed to parse uri %s", base_url );
|
||||
goto out;
|
||||
}
|
||||
|
||||
DEBUG_WEBDAV("* scheme %s", scheme );
|
||||
DEBUG_WEBDAV("* host %s", host );
|
||||
DEBUG_WEBDAV("* port %u", port );
|
||||
DEBUG_WEBDAV("* path %s", path );
|
||||
|
||||
if( strcmp( scheme, "owncloud" ) == 0 || strcmp( scheme, "http" ) == 0 ) {
|
||||
strcpy( protocol, "http");
|
||||
} else if( strcmp( scheme, "ownclouds" ) == 0 || strcmp( scheme, "https") == 0 ) {
|
||||
strcpy( protocol, "https");
|
||||
useSSL = 1;
|
||||
} else {
|
||||
DEBUG_WEBDAV("Invalid scheme %s, go out here!", scheme );
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
DEBUG_WEBDAV("* user %s", ctx->dav_session.user ? ctx->dav_session.user : "");
|
||||
|
||||
if (port == 0) {
|
||||
port = ne_uri_defaultport(protocol);
|
||||
}
|
||||
|
||||
ctx->dav_session.ctx = ne_session_create( protocol, host, port);
|
||||
|
||||
if (ctx->dav_session.ctx == NULL) {
|
||||
DEBUG_WEBDAV("Session create with protocol %s failed", protocol );
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ctx->dav_session.read_timeout != 0) {
|
||||
ne_set_read_timeout(ctx->dav_session.ctx, ctx->dav_session.read_timeout);
|
||||
DEBUG_WEBDAV("Timeout set to %u seconds", ctx->dav_session.read_timeout );
|
||||
}
|
||||
// Should never take more than some seconds, 30 is really a max.
|
||||
ne_set_connect_timeout(ctx->dav_session.ctx, 30);
|
||||
|
||||
snprintf( uaBuf, sizeof(uaBuf), "Mozilla/5.0 (%s) mirall/%s (csyncoC)",
|
||||
CSYNC_STRINGIFY( MIRALL_VERSION ), csync_owncloud_get_platform() );
|
||||
ne_set_useragent( ctx->dav_session.ctx, uaBuf);
|
||||
ne_set_server_auth(ctx->dav_session.ctx, authentication_callback_by_neon, ctx);
|
||||
|
||||
if( useSSL ) {
|
||||
if (!ne_has_support(NE_FEATURE_SSL)) {
|
||||
DEBUG_WEBDAV("Error: SSL is not enabled.");
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(clientCerts != NULL) {
|
||||
ne_ssl_client_cert *clicert;
|
||||
|
||||
DEBUG_WEBDAV("dav_connect: certificatePath and certificatePasswd are set, so we use it" );
|
||||
DEBUG_WEBDAV(" with certificatePath: %s", clientCerts->certificatePath );
|
||||
DEBUG_WEBDAV(" with certificatePasswd: %s", clientCerts->certificatePasswd );
|
||||
clicert = ne_ssl_clicert_read ( clientCerts->certificatePath );
|
||||
if ( clicert == NULL ) {
|
||||
DEBUG_WEBDAV ( "Error read certificate : %s", ne_get_error ( ctx->dav_session.ctx ) );
|
||||
} else {
|
||||
if ( ne_ssl_clicert_encrypted ( clicert ) ) {
|
||||
int rtn = ne_ssl_clicert_decrypt ( clicert, clientCerts->certificatePasswd );
|
||||
if ( !rtn ) {
|
||||
DEBUG_WEBDAV ( "Certificate was deciphered successfully." );
|
||||
ne_ssl_set_clicert ( ctx->dav_session.ctx, clicert );
|
||||
} else {
|
||||
DEBUG_WEBDAV ( "Errors while deciphering certificate: %s", ne_get_error ( ctx->dav_session.ctx ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DEBUG_WEBDAV("dav_connect: error with csync_client_certs_s* clientCerts");
|
||||
}
|
||||
ne_ssl_trust_default_ca( ctx->dav_session.ctx );
|
||||
ne_ssl_set_verify( ctx->dav_session.ctx, ssl_callback_by_neon, ctx);
|
||||
}
|
||||
|
||||
/* Hook called when a request is created. It sets the proxy connection header. */
|
||||
ne_hook_create_request( ctx->dav_session.ctx, request_created_hook, ctx );
|
||||
/* Hook called after response headers are read. It gets the Session ID. */
|
||||
ne_hook_post_headers( ctx->dav_session.ctx, post_request_hook, ctx );
|
||||
/* Hook called before a request is sent. It sets the cookies. */
|
||||
ne_hook_pre_send( ctx->dav_session.ctx, pre_send_hook, ctx );
|
||||
/* Hook called after request is dispatched. Used for handling possible redirections. */
|
||||
ne_hook_post_send( ctx->dav_session.ctx, post_send_hook, ctx );
|
||||
|
||||
/* Proxy support */
|
||||
proxystate = configureProxy( ctx, ctx->dav_session.ctx );
|
||||
if( proxystate < 0 ) {
|
||||
DEBUG_WEBDAV("Error: Proxy-Configuration failed.");
|
||||
} else if( proxystate > 0 ) {
|
||||
ne_set_proxy_auth( ctx->dav_session.ctx, proxy_authentication_callback_by_neon, ctx );
|
||||
}
|
||||
|
||||
ctx->_connected = 1;
|
||||
rc = 0;
|
||||
out:
|
||||
SAFE_FREE(path);
|
||||
SAFE_FREE(host);
|
||||
SAFE_FREE(scheme);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
char *owncloud_error_string(CSYNC* ctx)
|
||||
{
|
||||
return ctx->owncloud_context->dav_session.error_string;
|
||||
}
|
||||
|
||||
int owncloud_commit(CSYNC* ctx) {
|
||||
if (!ctx->owncloud_context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( ctx->owncloud_context->dav_session.ctx ) {
|
||||
ne_forget_auth(ctx->owncloud_context->dav_session.ctx);
|
||||
ne_session_destroy(ctx->owncloud_context->dav_session.ctx );
|
||||
ctx->owncloud_context->dav_session.ctx = 0;
|
||||
}
|
||||
|
||||
/* DEBUG_WEBDAV( "********** vio_module_shutdown" ); */
|
||||
|
||||
ctx->owncloud_context->dav_session.ctx = 0;
|
||||
|
||||
// ne_sock_exit();
|
||||
ctx->owncloud_context->_connected = 0; /* triggers dav_connect to go through the whole neon setup */
|
||||
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.user );
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.pwd );
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.session_key);
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.error_string );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void owncloud_destroy(CSYNC* ctx)
|
||||
{
|
||||
owncloud_commit(ctx);
|
||||
SAFE_FREE(ctx->owncloud_context);
|
||||
|
||||
if (ctx->clientCerts) {
|
||||
SAFE_FREE(ctx->clientCerts->certificatePasswd);
|
||||
SAFE_FREE(ctx->clientCerts->certificatePath);
|
||||
SAFE_FREE(ctx->clientCerts);
|
||||
}
|
||||
ne_sock_exit();
|
||||
}
|
||||
|
||||
int owncloud_set_property(CSYNC* ctx, const char *key, void *data) {
|
||||
#define READ_STRING_PROPERTY(P) \
|
||||
if (c_streq(key, #P)) { \
|
||||
SAFE_FREE(ctx->owncloud_context->dav_session.P); \
|
||||
ctx->owncloud_context->dav_session.P = c_strdup((const char*)data); \
|
||||
return 0; \
|
||||
}
|
||||
READ_STRING_PROPERTY(session_key)
|
||||
READ_STRING_PROPERTY(proxy_type)
|
||||
READ_STRING_PROPERTY(proxy_host)
|
||||
READ_STRING_PROPERTY(proxy_user)
|
||||
READ_STRING_PROPERTY(proxy_pwd)
|
||||
#undef READ_STRING_PROPERTY
|
||||
|
||||
if (c_streq(key, "proxy_port")) {
|
||||
ctx->owncloud_context->dav_session.proxy_port = *(int*)(data);
|
||||
return 0;
|
||||
}
|
||||
if (c_streq(key, "read_timeout") || c_streq(key, "timeout")) {
|
||||
ctx->owncloud_context->dav_session.read_timeout = *(int*)(data);
|
||||
return 0;
|
||||
}
|
||||
if( c_streq(key, "get_dav_session")) {
|
||||
/* Give the ne_session to the caller */
|
||||
*(ne_session**)data = ctx->owncloud_context->dav_session.ctx;
|
||||
return 0;
|
||||
}
|
||||
if( c_streq(key, "redirect_callback")) {
|
||||
if (data) {
|
||||
csync_owncloud_redirect_callback_t* cb_wrapper = data;
|
||||
ctx->owncloud_context->dav_session.redir_callback = *cb_wrapper;
|
||||
} else {
|
||||
ctx->owncloud_context->dav_session.redir_callback = NULL;
|
||||
}
|
||||
}
|
||||
if( c_streq(key, "SSLClientCerts")) {
|
||||
if(ctx->clientCerts != NULL) {
|
||||
SAFE_FREE(ctx->clientCerts->certificatePasswd);
|
||||
SAFE_FREE(ctx->clientCerts->certificatePath);
|
||||
SAFE_FREE(ctx->clientCerts);
|
||||
ctx->clientCerts = NULL;
|
||||
}
|
||||
if (data) {
|
||||
struct csync_client_certs_s* clientCerts = (struct csync_client_certs_s*) data;
|
||||
struct csync_client_certs_s* newCerts = c_malloc(sizeof(struct csync_client_certs_s));
|
||||
newCerts->certificatePath = c_strdup(clientCerts->certificatePath);
|
||||
newCerts->certificatePasswd = c_strdup(clientCerts->certificatePasswd);
|
||||
ctx->clientCerts = newCerts;
|
||||
} else {
|
||||
DEBUG_WEBDAV("error: in owncloud_set_property for 'SSLClientCerts'" );
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void owncloud_init(CSYNC* ctx) {
|
||||
|
||||
ne_sock_init();
|
||||
|
||||
ctx->owncloud_context = c_malloc( sizeof( struct csync_owncloud_ctx_s ));
|
||||
ctx->owncloud_context->csync_ctx = ctx; // back reference
|
||||
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et cindent: */
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2011 by Andreas Schneider <asn@cryptomilk.org>
|
||||
* Copyright (c) 2012 by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef CSYNC_OWNCLOUD_H
|
||||
#define CSYNC_OWNCLOUD_H
|
||||
|
||||
#include "csync.h"
|
||||
#include "vio/csync_vio.h"
|
||||
|
||||
// Public API used by csync
|
||||
int owncloud_commit(CSYNC* ctx);
|
||||
void owncloud_destroy(CSYNC* ctx);
|
||||
char *owncloud_error_string(CSYNC* ctx);
|
||||
int owncloud_set_property(CSYNC* ctx, const char *key, void *data);
|
||||
void owncloud_init(CSYNC* ctx);
|
||||
|
||||
int dav_connect(CSYNC* ctx, const char *base_url);
|
||||
|
||||
#endif /* CSYNC_OWNCLOUD_H */
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2011 by Andreas Schneider <asn@cryptomilk.org>
|
||||
* Copyright (c) 2012 by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef CSYNC_OWNCLOUD_PRIVATE_H
|
||||
#define CSYNC_OWNCLOUD_PRIVATE_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "config_csync.h"
|
||||
#ifdef NEON_WITH_LFS /* Switch on LFS in libneon. Never remove the NE_LFS! */
|
||||
#define NE_LFS
|
||||
#endif
|
||||
|
||||
#include <neon/ne_basic.h>
|
||||
#include <neon/ne_socket.h>
|
||||
#include <neon/ne_session.h>
|
||||
#include <neon/ne_request.h>
|
||||
#include <neon/ne_props.h>
|
||||
#include <neon/ne_auth.h>
|
||||
#include <neon/ne_dates.h>
|
||||
#include <neon/ne_compress.h>
|
||||
#include <neon/ne_redirect.h>
|
||||
|
||||
|
||||
#include "c_rbtree.h"
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "csync.h"
|
||||
#include "csync_misc.h"
|
||||
#include "csync_macros.h"
|
||||
#include "c_private.h"
|
||||
|
||||
#include "vio/csync_vio.h"
|
||||
|
||||
#include "csync_log.h"
|
||||
|
||||
#include "csync_owncloud.h"
|
||||
|
||||
|
||||
#define DEBUG_WEBDAV(...) csync_log( 9, "oc_module", __VA_ARGS__);
|
||||
|
||||
typedef int (*csync_owncloud_redirect_callback_t)(CSYNC* ctx, const char* uri);
|
||||
|
||||
/* Struct with the WebDAV session */
|
||||
struct dav_session_s {
|
||||
ne_session *ctx;
|
||||
char *user;
|
||||
char *pwd;
|
||||
|
||||
char *proxy_type;
|
||||
char *proxy_host;
|
||||
int proxy_port;
|
||||
char *proxy_user;
|
||||
char *proxy_pwd;
|
||||
|
||||
char *session_key;
|
||||
|
||||
char *error_string;
|
||||
|
||||
int read_timeout;
|
||||
|
||||
csync_owncloud_redirect_callback_t redir_callback;
|
||||
};
|
||||
|
||||
struct csync_owncloud_ctx_s {
|
||||
CSYNC *csync_ctx;
|
||||
|
||||
// For the WebDAV connection
|
||||
struct dav_session_s dav_session; /* The DAV Session, initialised in dav_connect */
|
||||
int _connected; /* flag to indicate if a connection exists, ie.
|
||||
the dav_session is valid */
|
||||
};
|
||||
|
||||
typedef struct csync_owncloud_ctx_s csync_owncloud_ctx_t;
|
||||
//typedef csync_owncloud_ctx_t* csync_owncloud_ctx_p;
|
||||
|
||||
void set_errno_from_http_errcode( int err );
|
||||
void set_error_message( csync_owncloud_ctx_t *ctx, const char *msg );
|
||||
void set_errno_from_neon_errcode(csync_owncloud_ctx_t *ctx, int neon_code );
|
||||
int http_result_code_from_session(csync_owncloud_ctx_t *ctx);
|
||||
void set_errno_from_session(csync_owncloud_ctx_t *ctx);
|
||||
|
||||
time_t oc_httpdate_parse( const char *date );
|
||||
|
||||
const char* csync_owncloud_get_platform(void);
|
||||
|
||||
char *_cleanPath( const char* uri );
|
||||
|
||||
#endif // CSYNC_OWNCLOUD_PRIVATE_H
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2011 by Andreas Schneider <asn@cryptomilk.org>
|
||||
* Copyright (c) 2012 by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "csync_owncloud.h"
|
||||
#include "csync_owncloud_private.h"
|
||||
|
||||
#include "csync_misc.h"
|
||||
|
||||
void set_errno_from_http_errcode( int err ) {
|
||||
int new_errno = 0;
|
||||
|
||||
switch(err) {
|
||||
case 200: /* OK */
|
||||
case 201: /* Created */
|
||||
case 202: /* Accepted */
|
||||
case 203: /* Non-Authoritative Information */
|
||||
case 204: /* No Content */
|
||||
case 205: /* Reset Content */
|
||||
case 207: /* Multi-Status */
|
||||
case 304: /* Not Modified */
|
||||
new_errno = 0;
|
||||
break;
|
||||
case 401: /* Unauthorized */
|
||||
case 402: /* Payment Required */
|
||||
case 407: /* Proxy Authentication Required */
|
||||
case 405:
|
||||
new_errno = EPERM;
|
||||
break;
|
||||
case 301: /* Moved Permanently */
|
||||
case 303: /* See Other */
|
||||
case 404: /* Not Found */
|
||||
case 410: /* Gone */
|
||||
new_errno = ENOENT;
|
||||
break;
|
||||
case 408: /* Request Timeout */
|
||||
case 504: /* Gateway Timeout */
|
||||
new_errno = EAGAIN;
|
||||
break;
|
||||
case 423: /* Locked */
|
||||
new_errno = EACCES;
|
||||
break;
|
||||
case 400: /* Bad Request */
|
||||
case 403: /* Forbidden */
|
||||
case 409: /* Conflict */
|
||||
case 411: /* Length Required */
|
||||
case 412: /* Precondition Failed */
|
||||
case 414: /* Request-URI Too Long */
|
||||
case 415: /* Unsupported Media Type */
|
||||
case 424: /* Failed Dependency */
|
||||
case 501: /* Not Implemented */
|
||||
new_errno = EINVAL;
|
||||
break;
|
||||
case 507: /* Insufficient Storage */
|
||||
new_errno = ENOSPC;
|
||||
break;
|
||||
case 206: /* Partial Content */
|
||||
case 300: /* Multiple Choices */
|
||||
case 302: /* Found */
|
||||
case 305: /* Use Proxy */
|
||||
case 306: /* (Unused) */
|
||||
case 307: /* Temporary Redirect */
|
||||
case 406: /* Not Acceptable */
|
||||
case 416: /* Requested Range Not Satisfiable */
|
||||
case 417: /* Expectation Failed */
|
||||
case 422: /* Unprocessable Entity */
|
||||
case 500: /* Internal Server Error */
|
||||
case 502: /* Bad Gateway */
|
||||
case 505: /* HTTP Version Not Supported */
|
||||
new_errno = EIO;
|
||||
break;
|
||||
case 503: /* Service Unavailable */
|
||||
new_errno = ERRNO_SERVICE_UNAVAILABLE;
|
||||
break;
|
||||
case 413: /* Request Entity too Large */
|
||||
new_errno = EFBIG;
|
||||
break;
|
||||
default:
|
||||
new_errno = EIO;
|
||||
}
|
||||
|
||||
errno = new_errno;
|
||||
}
|
||||
|
||||
// as per http://sourceforge.net/p/predef/wiki/OperatingSystems/
|
||||
// extend as required
|
||||
const char* csync_owncloud_get_platform() {
|
||||
#if defined (_WIN32)
|
||||
return "Windows";
|
||||
#elif defined(__APPLE__)
|
||||
return "Macintosh";
|
||||
#elif defined(__gnu_linux__)
|
||||
return "Linux";
|
||||
#elif defined(__DragonFly__)
|
||||
/* might also define __FreeBSD__ */
|
||||
return "DragonFlyBSD";
|
||||
#elif defined(__FreeBSD__)
|
||||
return "FreeBSD";
|
||||
#elif defined(__NetBSD__)
|
||||
return "NetBSD";
|
||||
#elif defined(__OpenBSD__)
|
||||
return "OpenBSD";
|
||||
#elif defined(sun) || defined(__sun)
|
||||
return "Solaris";
|
||||
#else
|
||||
return "Unknown OS";
|
||||
#endif
|
||||
}
|
||||
@@ -77,9 +77,6 @@ enum csync_replica_e {
|
||||
|
||||
typedef struct csync_file_stat_s csync_file_stat_t;
|
||||
|
||||
struct csync_owncloud_ctx_s; // csync_owncloud.c
|
||||
|
||||
|
||||
/**
|
||||
* @brief csync public structure
|
||||
*/
|
||||
@@ -169,9 +166,6 @@ struct csync_s {
|
||||
bool db_is_empty;
|
||||
|
||||
bool ignore_hidden_files;
|
||||
|
||||
struct csync_owncloud_ctx_s *owncloud_context;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -185,11 +179,11 @@ struct csync_file_stat_s {
|
||||
size_t pathlen; /* u64 */
|
||||
uint64_t inode; /* u64 */
|
||||
mode_t mode; /* u32 */
|
||||
int type; /* u32 */
|
||||
int child_modified;/*bool*/
|
||||
int should_update_metadata; /*bool: specify that the etag, or the remote perm or fileid has
|
||||
unsigned int type : 4;
|
||||
unsigned int child_modified : 1;
|
||||
unsigned int should_update_metadata : 1; /*specify that the etag, or the remote perm or fileid has
|
||||
changed and need to be updated on the db even for INSTRUCTION_NONE */
|
||||
int has_ignored_files; /*bool: specify that a directory, or child directory contains ignored files */
|
||||
unsigned int has_ignored_files : 1; /* specify that a directory, or child directory contains ignored files */
|
||||
|
||||
char *destpath; /* for renames */
|
||||
const char *etag;
|
||||
|
||||
@@ -416,37 +416,10 @@ csync_file_stat_t *csync_statedb_get_stat_by_inode(CSYNC *ctx,
|
||||
return st;
|
||||
}
|
||||
|
||||
/* Get the etag. */
|
||||
char *csync_statedb_get_etag( CSYNC *ctx, uint64_t jHash ) {
|
||||
char *ret = NULL;
|
||||
csync_file_stat_t *fs = NULL;
|
||||
|
||||
if( !ctx ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( ! csync_get_statedb_exists(ctx)) return ret;
|
||||
|
||||
fs = csync_statedb_get_stat_by_hash(ctx, jHash );
|
||||
if( fs ) {
|
||||
if( fs->etag ) {
|
||||
ret = c_strdup(fs->etag);
|
||||
}
|
||||
csync_file_stat_free(fs);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define BELOW_PATH_QUERY "SELECT phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize, ignoredChildrenRemote FROM metadata WHERE pathlen>? AND path LIKE(?)"
|
||||
|
||||
int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
||||
int rc;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
int64_t cnt = 0;
|
||||
char *likepath;
|
||||
int asp;
|
||||
int min_path_len;
|
||||
|
||||
if( !path ) {
|
||||
return -1;
|
||||
@@ -456,7 +429,12 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SQLITE_BUSY_HANDLED(sqlite3_prepare_v2(ctx->statedb.db, BELOW_PATH_QUERY, -1, &stmt, NULL));
|
||||
/* Select the entries for anything that starts with (path+'/')
|
||||
* In other words, anything that is between path+'/' and path+'0',
|
||||
* (because '0' follows '/' in ascii)
|
||||
*/
|
||||
const char *below_path_query = "SELECT phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize, ignoredChildrenRemote FROM metadata WHERE path > (?||'/') AND path < (?||'0')";
|
||||
SQLITE_BUSY_HANDLED(sqlite3_prepare_v2(ctx->statedb.db, below_path_query, -1, &stmt, NULL));
|
||||
ctx->statedb.lastReturnValue = rc;
|
||||
if( rc != SQLITE_OK ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for below path query.");
|
||||
@@ -467,15 +445,8 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
asp = asprintf( &likepath, "%s/%%%%", path);
|
||||
if (asp < 0) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "asprintf failed!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
min_path_len = strlen(path);
|
||||
sqlite3_bind_int(stmt, 1, min_path_len);
|
||||
sqlite3_bind_text(stmt, 2, likepath, -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 1, path, -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 2, path, -1, SQLITE_STATIC);
|
||||
|
||||
cnt = 0;
|
||||
|
||||
@@ -488,7 +459,7 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
||||
/* Check for exclusion from the tree.
|
||||
* Note that this is only a safety net in case the ignore list changes
|
||||
* without a full remote discovery being triggered. */
|
||||
CSYNC_EXCLUDE_TYPE excluded = csync_excluded(ctx, st->path, st->type);
|
||||
CSYNC_EXCLUDE_TYPE excluded = csync_excluded_traversal(ctx->excludes, st->path, st->type);
|
||||
if (excluded != CSYNC_NOT_EXCLUDED) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "%s excluded (%d)", st->path, excluded);
|
||||
|
||||
@@ -518,7 +489,6 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "%" PRId64 " entries read below path %s from db.", cnt, path);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
SAFE_FREE(likepath);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
excluded =CSYNC_FILE_EXCLUDE_STAT_FAILED;
|
||||
} else {
|
||||
/* Check if file is excluded */
|
||||
excluded = csync_excluded(ctx, path,type);
|
||||
excluded = csync_excluded_traversal(ctx->excludes, path, type);
|
||||
}
|
||||
|
||||
if( excluded == CSYNC_NOT_EXCLUDED ) {
|
||||
@@ -270,10 +270,6 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
((int64_t) fs->mtime), ((int64_t) tmp->modtime),
|
||||
fs->etag, tmp->etag, (uint64_t) fs->inode, (uint64_t) tmp->inode,
|
||||
(uint64_t) fs->size, (uint64_t) tmp->size, fs->remotePerm, tmp->remotePerm, tmp->has_ignored_files );
|
||||
if( !fs->etag) {
|
||||
st->instruction = CSYNC_INSTRUCTION_EVAL;
|
||||
goto out;
|
||||
}
|
||||
if((ctx->current == REMOTE_REPLICA && !c_streq(fs->etag, tmp->etag ))
|
||||
|| (ctx->current == LOCAL_REPLICA && (!_csync_mtime_equal(fs->mtime, tmp->modtime)
|
||||
// zero size in statedb can happen during migration
|
||||
@@ -584,7 +580,6 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
char *d_name = NULL;
|
||||
csync_vio_handle_t *dh = NULL;
|
||||
csync_vio_file_stat_t *dirent = NULL;
|
||||
csync_vio_file_stat_t *fs = NULL;
|
||||
csync_file_stat_t *previous_fs = NULL;
|
||||
int read_from_db = 0;
|
||||
int rc = 0;
|
||||
@@ -630,7 +625,15 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
/* permission denied */
|
||||
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_OPENDIR_ERROR);
|
||||
if (errno == EACCES) {
|
||||
return 0;
|
||||
if (ctx->current_fs) {
|
||||
ctx->current_fs->instruction = CSYNC_INSTRUCTION_IGNORE;
|
||||
ctx->current_fs->error_status = CSYNC_STATUS_PERMISSION_DENIED;
|
||||
/* If a directory has ignored files, put the flag on the parent directory as well */
|
||||
if( previous_fs ) {
|
||||
previous_fs->has_ignored_files = true;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
} else if(errno == ENOENT) {
|
||||
asp = asprintf( &ctx->error_string, "%s", uri);
|
||||
if (asp < 0) {
|
||||
@@ -652,6 +655,7 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
/* if current_fs is not defined here, better throw an error */
|
||||
} else {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "opendir failed for %s - errno %d", uri, errno);
|
||||
}
|
||||
@@ -679,8 +683,8 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
}
|
||||
|
||||
/* skip "." and ".." */
|
||||
if (d_name[0] == '.' && (d_name[1] == '\0'
|
||||
|| (d_name[1] == '.' && d_name[2] == '\0'))) {
|
||||
if ( (d_name[0] == '.' && d_name[1] == '\0')
|
||||
|| (d_name[0] == '.' && d_name[1] == '.' && d_name[2] == '\0')) {
|
||||
csync_vio_file_stat_destroy(dirent);
|
||||
dirent = NULL;
|
||||
continue;
|
||||
@@ -732,15 +736,21 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
|
||||
/* Only for the local replica we have to stat(), for the remote one we have all data already */
|
||||
if (ctx->replica == LOCAL_REPLICA) {
|
||||
fs = csync_vio_file_stat_new();
|
||||
res = csync_vio_stat(ctx, filename, fs);
|
||||
res = csync_vio_stat(ctx, filename, dirent);
|
||||
} else {
|
||||
fs = dirent;
|
||||
res = 0;
|
||||
}
|
||||
|
||||
/* if the filename starts with a . we consider it a hidden file
|
||||
* For windows, the hidden state is also discovered within the vio
|
||||
* local stat function.
|
||||
*/
|
||||
if( d_name[0] == '.' ) {
|
||||
dirent->flags |= CSYNC_VIO_FILE_FLAGS_HIDDEN;
|
||||
}
|
||||
|
||||
if( res == 0) {
|
||||
switch (fs->type) {
|
||||
switch (dirent->type) {
|
||||
case CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK:
|
||||
flag = CSYNC_FTW_FLAG_SLINK;
|
||||
break;
|
||||
@@ -763,42 +773,12 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
flag = CSYNC_FTW_FLAG_NSTAT;
|
||||
}
|
||||
|
||||
if( ctx->current == LOCAL_REPLICA ) {
|
||||
char *etag = NULL;
|
||||
int len = strlen( path );
|
||||
uint64_t h = c_jhash64((uint8_t *) path, len, 0);
|
||||
etag = csync_statedb_get_etag( ctx, h );
|
||||
|
||||
if(_last_db_return_error(ctx)) {
|
||||
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||
SAFE_FREE(etag);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if( etag ) {
|
||||
SAFE_FREE(fs->etag);
|
||||
fs->etag = etag;
|
||||
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG;
|
||||
|
||||
if( c_streq(etag, "")) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Uniq ID from Database is EMPTY: %s", path);
|
||||
} else {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Uniq ID from Database: %s -> %s", path, fs->etag ? fs->etag : "<NULL>" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
previous_fs = ctx->current_fs;
|
||||
|
||||
/* Call walker function for each file */
|
||||
rc = fn(ctx, filename, fs, flag);
|
||||
rc = fn(ctx, filename, dirent, flag);
|
||||
/* this function may update ctx->current and ctx->read_from_db */
|
||||
|
||||
/* Only for the local replica we have to destroy stat(), for the remote one it is a pointer to dirent */
|
||||
if (ctx->replica == LOCAL_REPLICA) {
|
||||
csync_vio_file_stat_destroy(fs);
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
if (CSYNC_STATUS_IS_OK(ctx->status_code)) {
|
||||
ctx->status_code = CSYNC_STATUS_UPDATE_ERROR;
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
project(httpbflib C)
|
||||
|
||||
find_package(Neon)
|
||||
|
||||
|
||||
set(HTTPBF_PUBLIC_INCLUDE_DIRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${NEON_INCLUDE_DIRS}
|
||||
CACHE INTERNAL "httpbflib public include directories"
|
||||
)
|
||||
|
||||
set(HTTPBF_LIBRARY
|
||||
httpbf
|
||||
CACHE INTERNAL "httpbf library"
|
||||
)
|
||||
|
||||
set(HTTPBF_LINK_LIBRARIES
|
||||
${HTTPBF_LIBRARY}
|
||||
)
|
||||
|
||||
set(httpbf_SRCS
|
||||
src/httpbf.c
|
||||
)
|
||||
set(httpbf_HEADERS
|
||||
src/httpbf.h
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${HTTPBF_PUBLIC_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
add_library(${HTTPBF_LIBRARY} STATIC ${httpbf_SRCS})
|
||||
target_link_libraries(${HTTPBF_LIBRARY} ${NEON_LIBRARIES})
|
||||
|
||||
if(NOT WIN32)
|
||||
add_definitions( -fPIC )
|
||||
endif()
|
||||
|
||||
INSTALL(
|
||||
TARGETS
|
||||
${HTTPBF_LIBRARY}
|
||||
LIBRARY DESTINATION
|
||||
${LIB_INSTALL_DIR}
|
||||
ARCHIVE DESTINATION
|
||||
${LIB_INSTALL_DIR}
|
||||
RUNTIME DESTINATION
|
||||
${BIN_INSTALL_DIR}
|
||||
)
|
||||
|
||||
if (NOT APPLE)
|
||||
INSTALL(
|
||||
FILES
|
||||
${httpbf_HEADERS}
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
endif (NOT APPLE)
|
||||
@@ -1,29 +0,0 @@
|
||||
This is a little code that does ownCloud file chunking.
|
||||
|
||||
Basically to put a local file to an url:
|
||||
(Also see the client example code in client dir.)
|
||||
|
||||
/* Initialize the transfer, get a transfer struct. */
|
||||
hbf_transfer_t *trans = hbf_init_transfer( url );
|
||||
|
||||
Hbf_State state;
|
||||
if( trans ) {
|
||||
int fd = open_local_file( file );
|
||||
|
||||
/* create a neon session to use for the transfer */
|
||||
ne_session *session = create_neon_session(uri);
|
||||
|
||||
if( session && fd > -1 ) {
|
||||
/* Prepare the list of chunks, ie. calculate chunks and write back to trans. */
|
||||
state = hbf_splitlist(trans, fd);
|
||||
|
||||
if( state == HBF_SUCCESS ) {
|
||||
/* Transfer all the chunks through the HTTP session using PUT. */
|
||||
state = hbf_transfer( session, trans, "PUT" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GET a large file:
|
||||
Do GET Range requests.
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
project(client C)
|
||||
|
||||
set(CLIENT_EXECUTABLE httpbfclient CACHE INTERNAL "httpbf client")
|
||||
|
||||
set(CLIENT_LINK_LIBRARIES ${NEON_LIBRARIES} ${HBF_LIBRARY})
|
||||
|
||||
set(HTTPBF_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/src})
|
||||
|
||||
if(NOT LINUX)
|
||||
list(APPEND CLIENT_LINK_LIBRARIES ${ARGP_LIBRARIES})
|
||||
endif()
|
||||
|
||||
set(client_SRCS
|
||||
httpbf_client.c
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${HTTPBF_INCLUDE_DIR}
|
||||
${HTTPBF_PUBLIC_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
add_executable(${CLIENT_EXECUTABLE} ${client_SRCS})
|
||||
|
||||
target_link_libraries(${CLIENT_EXECUTABLE} ${CLIENT_LINK_LIBRARIES})
|
||||
|
||||
set_target_properties(
|
||||
${CLIENT_EXECUTABLE}
|
||||
PROPERTIES
|
||||
OUTPUT_NAME
|
||||
httpbf
|
||||
)
|
||||
|
||||
# install( TARGETS ${CLIENT_EXECUTABLE} DESTINATION ${BIN_INSTALL_DIR} )
|
||||
install(TARGETS ${CLIENT_EXECUTABLE} DESTINATION bin)
|
||||
|
||||
|
||||
@@ -1,225 +0,0 @@
|
||||
/*
|
||||
* httpbf - send big files via http
|
||||
*
|
||||
* Copyright (c) 2012 Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <neon/ne_auth.h>
|
||||
|
||||
#include "httpbf.h"
|
||||
|
||||
/* Program documentation. */
|
||||
static char doc[] = "Usage: httpbf [OPTION...] LOCAL REMOTEDIR\n\
|
||||
httpbf - command line client to upload big files via http.\n\
|
||||
\n\
|
||||
Transfer a big file to a remote directory on ownCloud.\n\
|
||||
\n\
|
||||
-?, --help Give this help list\n\
|
||||
--usage Give a short usage message\n\
|
||||
-V, --version Print program version\n\
|
||||
";
|
||||
|
||||
static char _user[NE_ABUFSIZ];
|
||||
static char _pwd[NE_ABUFSIZ];
|
||||
|
||||
/* The options we understand. */
|
||||
static const struct option long_options[] =
|
||||
{
|
||||
{"version", no_argument, 0, 'V' },
|
||||
{"usage", no_argument, 0, 'h' },
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static const char* httpbf_version = "0.1";
|
||||
|
||||
static void print_version()
|
||||
{
|
||||
printf( "%s\n", httpbf_version );
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void print_help()
|
||||
{
|
||||
printf( "%s\n", doc );
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int ne_auth( void *userdata, const char *realm, int attempt,
|
||||
char *username, char *password)
|
||||
{
|
||||
(void) userdata;
|
||||
(void) realm;
|
||||
|
||||
if( username && password ) {
|
||||
if( _user ) {
|
||||
/* allow user without password */
|
||||
if( strlen( _user ) < NE_ABUFSIZ ) {
|
||||
strcpy( username, _user );
|
||||
}
|
||||
if( _pwd && strlen( _pwd ) < NE_ABUFSIZ ) {
|
||||
strcpy( password, _pwd );
|
||||
}
|
||||
}
|
||||
}
|
||||
return attempt;
|
||||
}
|
||||
|
||||
|
||||
static int parse_args(int argc, char **argv)
|
||||
{
|
||||
while(optind < argc) {
|
||||
int c = -1;
|
||||
struct option *opt = NULL;
|
||||
int result = getopt_long( argc, argv, "Vh", long_options, &c );
|
||||
|
||||
if( result == -1 ) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch(result) {
|
||||
case 'V':
|
||||
print_version();
|
||||
break;
|
||||
case 'h':
|
||||
print_help();
|
||||
break;
|
||||
case 0:
|
||||
opt = (struct option*)&(long_options[c]);
|
||||
if(strcmp(opt->name, "no-name-yet")) {
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "Argument: No idea what!\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return optind;
|
||||
}
|
||||
|
||||
static ne_session* create_neon_session( const char *url )
|
||||
{
|
||||
ne_uri uri;
|
||||
ne_session *sess = NULL;
|
||||
|
||||
memset( _user, 0, NE_ABUFSIZ );
|
||||
memset( _pwd, 0, NE_ABUFSIZ );
|
||||
|
||||
if( ne_uri_parse( url, &uri ) == 0 ) {
|
||||
unsigned int port = ne_uri_defaultport(uri.scheme);
|
||||
if( uri.userinfo ) {
|
||||
char *slash = NULL;
|
||||
strcpy( _user, uri.userinfo );
|
||||
slash = strchr( _user, ':');
|
||||
if( slash ) {
|
||||
strcpy( _pwd, slash+1);
|
||||
*slash = 0;
|
||||
}
|
||||
}
|
||||
sess = ne_session_create(uri.scheme, uri.host, port);
|
||||
ne_set_server_auth(sess, ne_auth, 0 );
|
||||
|
||||
ne_uri_free(&uri);
|
||||
}
|
||||
return sess;
|
||||
}
|
||||
|
||||
static int open_local_file( const char *file )
|
||||
{
|
||||
int fd = -1;
|
||||
|
||||
if( !file ) return -1;
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void transfer( const char* local, const char* uri )
|
||||
{
|
||||
if( !(local && uri )) return;
|
||||
char *whole_url;
|
||||
int len;
|
||||
char *filename = basename(local);
|
||||
if( ! filename ) {
|
||||
return;
|
||||
}
|
||||
|
||||
len = strlen(filename)+strlen(uri)+2;
|
||||
whole_url = malloc( len );
|
||||
strcpy(whole_url, uri);
|
||||
strcat(whole_url, "/");
|
||||
strcat(whole_url, filename);
|
||||
|
||||
hbf_transfer_t *trans = hbf_init_transfer( whole_url );
|
||||
Hbf_State state;
|
||||
|
||||
if( trans ) {
|
||||
ne_session *session = create_neon_session(uri);
|
||||
if( session ) {
|
||||
int fd = open_local_file( local );
|
||||
if( fd > -1 ) {
|
||||
state = hbf_splitlist(trans, fd );
|
||||
if( state == HBF_SUCCESS ) {
|
||||
state = hbf_transfer( session, trans, "PUT" );
|
||||
}
|
||||
}
|
||||
ne_session_destroy(session);
|
||||
}
|
||||
}
|
||||
|
||||
if( state != HBF_SUCCESS ) {
|
||||
printf("Upload failed: %s\n", hbf_error_string(state));
|
||||
printf(" HTTP result %d, Server Error: %s\n",
|
||||
trans->status_code, trans->error_string ? trans->error_string : "<empty>" );
|
||||
}
|
||||
/* Print the result of the recent transfer */
|
||||
hbf_free_transfer( trans );
|
||||
free(whole_url);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int rc = 0;
|
||||
char errbuf[256] = {0};
|
||||
|
||||
parse_args(argc, argv);
|
||||
/* two options must remain as source and target */
|
||||
/* printf("ARGC: %d -> optind: %d\n", argc, optind ); */
|
||||
if( argc - optind < 2 ) {
|
||||
print_help();
|
||||
}
|
||||
|
||||
transfer( argv[optind], argv[optind+1]);
|
||||
|
||||
}
|
||||
|
||||
/* vim: set ts=8 sw=2 et cindent: */
|
||||
@@ -1,38 +0,0 @@
|
||||
project(httpbf C)
|
||||
|
||||
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
||||
|
||||
set(HTTPBF_PUBLIC_INCLUDE_DIRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
CACHE INTERNAL "httpbf public include directories"
|
||||
)
|
||||
|
||||
set(HTTPBFLIB_PRIVATE_INCLUDE_DIRS
|
||||
)
|
||||
|
||||
set(HBF_LIBRARY
|
||||
httpbf
|
||||
CACHE INTERNAL "httpbflib library"
|
||||
)
|
||||
|
||||
set(HTTPBFLIB_LINK_LIBRARIES
|
||||
${HBF_LIBRARY}
|
||||
)
|
||||
|
||||
set(httpbflib_SRCS
|
||||
httpbf.c
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${NEON_INCLUDE_DIRS}
|
||||
${GLIB2_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
if(NOT WIN32)
|
||||
add_definitions( -fPIC )
|
||||
endif()
|
||||
|
||||
add_library(${HBF_LIBRARY} SHARED ${httpbflib_SRCS} )
|
||||
|
||||
target_link_libraries(${HBF_LIBRARY} ${NEON_LIBRARIES})
|
||||
|
||||
@@ -1,688 +0,0 @@
|
||||
/*
|
||||
* httpbf - send big files via http
|
||||
*
|
||||
* Copyright (c) 2012 Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <sys/timeb.h>
|
||||
#include <sys/time.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "httpbf.h"
|
||||
|
||||
#include <neon/ne_session.h>
|
||||
#include <neon/ne_request.h>
|
||||
#include <neon/ne_basic.h>
|
||||
|
||||
// #ifdef NDEBUG
|
||||
// #define DEBUG_HBF(...)
|
||||
// #else
|
||||
#define DEBUG_HBF(...) { if(transfer->log_cb) { \
|
||||
char buf[1024]; \
|
||||
snprintf(buf, 1024, __VA_ARGS__); \
|
||||
transfer->log_cb(__func__, buf, transfer->user_data); \
|
||||
} }
|
||||
|
||||
// #endif
|
||||
|
||||
#define DEFAULT_BLOCK_SIZE (10*1024*1024)
|
||||
|
||||
/* Platform specific defines go here. */
|
||||
#ifdef _WIN32
|
||||
#define _hbf_fstat _fstat64
|
||||
typedef struct stat64 hbf_stat_t;
|
||||
#else
|
||||
#define _hbf_fstat fstat
|
||||
typedef struct stat hbf_stat_t;
|
||||
#endif
|
||||
|
||||
static int transfer_id( hbf_stat_t *sb ) {
|
||||
struct timeval tp;
|
||||
int res;
|
||||
int r;
|
||||
|
||||
if( gettimeofday(&tp, 0) < 0 ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* build a Unique ID:
|
||||
* take the current epoch and shift 8 bits up to keep the least bits.
|
||||
* than add the milliseconds, again shift by 8
|
||||
* and finally add the least 8 bit of the inode of the file.
|
||||
*/
|
||||
res = tp.tv_sec; /* epoche value in seconds */
|
||||
res = res << 8;
|
||||
r = (sb->st_ino & 0xFF);
|
||||
res += r; /* least six bit of inode */
|
||||
res = res << sizeof(tp.tv_usec);
|
||||
res += tp.tv_usec; /* milliseconds */
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
hbf_transfer_t *hbf_init_transfer( const char *dest_uri ) {
|
||||
hbf_transfer_t * transfer = NULL;
|
||||
|
||||
transfer = malloc( sizeof(hbf_transfer_t) );
|
||||
memset(transfer, 0, sizeof(hbf_transfer_t));
|
||||
|
||||
/* store the target uri */
|
||||
transfer->url = strdup(dest_uri);
|
||||
transfer->status_code = 200;
|
||||
transfer->error_string = NULL;
|
||||
transfer->start_id = 0;
|
||||
transfer->block_size = DEFAULT_BLOCK_SIZE;
|
||||
transfer->threshold = transfer->block_size;
|
||||
transfer->modtime_accepted = 0;
|
||||
transfer->oc_header_modtime = 0;
|
||||
|
||||
return transfer;
|
||||
}
|
||||
|
||||
/* Create the splitlist of a given file descriptor */
|
||||
Hbf_State hbf_splitlist(hbf_transfer_t *transfer, int fd ) {
|
||||
hbf_stat_t sb;
|
||||
int64_t num_blocks;
|
||||
int64_t blk_size;
|
||||
int64_t remainder = 0;
|
||||
|
||||
if( ! transfer ) {
|
||||
return HBF_PARAM_FAIL;
|
||||
}
|
||||
|
||||
if( fd <= 0 ) {
|
||||
DEBUG_HBF("File descriptor is invalid.");
|
||||
return HBF_PARAM_FAIL;
|
||||
}
|
||||
|
||||
if( _hbf_fstat(fd, &sb) < 0 ) {
|
||||
DEBUG_HBF("Failed to stat the file descriptor: errno = %d", errno);
|
||||
return HBF_FILESTAT_FAIL;
|
||||
}
|
||||
|
||||
/* Store the file characteristics. */
|
||||
transfer->fd = fd;
|
||||
transfer->stat_size = sb.st_size;
|
||||
transfer->modtime = sb.st_mtime;
|
||||
transfer->previous_etag = NULL;
|
||||
#ifndef NDEBUG
|
||||
transfer->calc_size = 0;
|
||||
#endif
|
||||
|
||||
DEBUG_HBF("block_size: %" PRId64 " threshold: %" PRId64 " st_size: %" PRId64, transfer->block_size, transfer->threshold, sb.st_size );
|
||||
|
||||
|
||||
/* calc the number of blocks to split in */
|
||||
blk_size = transfer->block_size;
|
||||
if (sb.st_size < transfer->threshold) {
|
||||
blk_size = transfer->threshold;
|
||||
}
|
||||
|
||||
num_blocks = sb.st_size / blk_size;
|
||||
|
||||
/* there migth be a remainder. */
|
||||
remainder = sb.st_size - num_blocks * blk_size;
|
||||
|
||||
/* if there is a remainder, add one block */
|
||||
if( remainder > 0 ) {
|
||||
num_blocks++;
|
||||
}
|
||||
|
||||
/* The file has size 0. There still needs to be at least one block. */
|
||||
if( sb.st_size == 0 ) {
|
||||
num_blocks = 1;
|
||||
blk_size = 0;
|
||||
}
|
||||
|
||||
DEBUG_HBF("num_blocks: %" PRId64 " rmainder: %" PRId64 " blk_size: %" PRId64, num_blocks, remainder, blk_size );
|
||||
|
||||
|
||||
if( num_blocks ) {
|
||||
int cnt;
|
||||
int64_t overall = 0;
|
||||
/* create a datastructure for the transfer data */
|
||||
transfer->block_arr = calloc(num_blocks, sizeof(hbf_block_t*));
|
||||
transfer->block_cnt = num_blocks;
|
||||
transfer->transfer_id = transfer_id(&sb);
|
||||
transfer->start_id = 0;
|
||||
|
||||
for( cnt=0; cnt < num_blocks; cnt++ ) {
|
||||
/* allocate a block struct and fill */
|
||||
hbf_block_t *block = malloc( sizeof(hbf_block_t) );
|
||||
memset(block, 0, sizeof(hbf_block_t));
|
||||
|
||||
block->seq_number = cnt;
|
||||
if( cnt > 0 ) {
|
||||
block->start = cnt * blk_size;
|
||||
}
|
||||
block->size = blk_size;
|
||||
block->state = HBF_NOT_TRANSFERED;
|
||||
|
||||
/* consider the remainder if we're already at the end */
|
||||
if( cnt == num_blocks-1 && remainder > 0 ) {
|
||||
block->size = remainder;
|
||||
}
|
||||
overall += block->size;
|
||||
/* store the block data into the result array in the transfer */
|
||||
*((transfer->block_arr)+cnt) = block;
|
||||
|
||||
DEBUG_HBF("created block %d (start: %" PRId64 " size: %" PRId64 ")", cnt, block->start, block->size );
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
transfer->calc_size = overall;
|
||||
#endif
|
||||
}
|
||||
return HBF_SUCCESS;
|
||||
}
|
||||
|
||||
void hbf_free_transfer( hbf_transfer_t *transfer ) {
|
||||
int cnt;
|
||||
|
||||
if( !transfer ) return;
|
||||
|
||||
for( cnt = 0; cnt < transfer->block_cnt; cnt++ ) {
|
||||
hbf_block_t *block = transfer->block_arr[cnt];
|
||||
if( !block ) continue;
|
||||
if( block->http_error_msg ) free( block->http_error_msg );
|
||||
if( block->etag ) free( block->etag );
|
||||
}
|
||||
free( transfer->block_arr );
|
||||
free( transfer->url );
|
||||
free( transfer->file_id );
|
||||
if( transfer->error_string) free( (void*) transfer->error_string );
|
||||
|
||||
free( transfer );
|
||||
}
|
||||
|
||||
static char* get_transfer_url( hbf_transfer_t *transfer, int indx ) {
|
||||
char *res = NULL;
|
||||
|
||||
hbf_block_t *block = NULL;
|
||||
|
||||
if( ! transfer ) return NULL;
|
||||
if( indx >= transfer->block_cnt ) return NULL;
|
||||
|
||||
block = transfer->block_arr[indx];
|
||||
if( ! block ) return NULL;
|
||||
|
||||
if( transfer->block_cnt == 1 ) {
|
||||
/* Just one chunk. We send as an ordinary request without chunking. */
|
||||
res = strdup( transfer->url );
|
||||
} else {
|
||||
char trans_id_str[32];
|
||||
char trans_block_str[32];
|
||||
char indx_str[32];
|
||||
int len = 1; /* trailing zero. */
|
||||
int tlen = 0;
|
||||
|
||||
tlen = sprintf( trans_id_str, "%u", transfer->transfer_id );
|
||||
if( tlen < 0 ) {
|
||||
return NULL;
|
||||
}
|
||||
len += tlen;
|
||||
|
||||
tlen = sprintf( trans_block_str, "%u", transfer->block_cnt );
|
||||
if( tlen < 0 ) {
|
||||
return NULL;
|
||||
}
|
||||
len += tlen;
|
||||
|
||||
tlen = sprintf( indx_str, "%u", indx );
|
||||
if( tlen < 0 ) {
|
||||
return NULL;
|
||||
}
|
||||
len += tlen;
|
||||
|
||||
len += strlen(transfer->url);
|
||||
len += strlen("-chunking---");
|
||||
|
||||
res = malloc(len);
|
||||
|
||||
/* Note: must be %u for unsigned because one does not want '--' */
|
||||
if( sprintf(res, "%s-chunking-%u-%u-%u", transfer->url, transfer->transfer_id,
|
||||
transfer->block_cnt, indx ) < 0 ) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* perform one transfer of one block.
|
||||
* returns HBF_TRANSFER_SUCCESS if the transfer of this block was a success
|
||||
* returns HBF_SUCCESS if the server aknoweldge that he received all the blocks
|
||||
*/
|
||||
static int _hbf_dav_request(hbf_transfer_t *transfer, ne_request *req, int fd, hbf_block_t *blk ) {
|
||||
Hbf_State state = HBF_TRANSFER_SUCCESS;
|
||||
int res;
|
||||
const ne_status *req_status = NULL;
|
||||
const char *etag = NULL;
|
||||
|
||||
(void) transfer;
|
||||
|
||||
if( ! (blk && req) ) return HBF_PARAM_FAIL;
|
||||
|
||||
ne_set_request_body_fd(req, fd, blk->start, blk->size);
|
||||
DEBUG_HBF("Block: %d , Start: %" PRId64 " and Size: %" PRId64 "", blk->seq_number, blk->start, blk->size );
|
||||
res = ne_request_dispatch(req);
|
||||
|
||||
req_status = ne_get_status( req );
|
||||
|
||||
switch(res) {
|
||||
case NE_OK:
|
||||
blk->state = HBF_TRANSFER_FAILED;
|
||||
state = HBF_FAIL;
|
||||
etag = 0;
|
||||
if( req_status->klass == 2 ) {
|
||||
state = HBF_TRANSFER_SUCCESS;
|
||||
blk->state = HBF_TRANSFER_SUCCESS;
|
||||
etag = ne_get_response_header(req, "ETag");
|
||||
if (etag && etag[0]) {
|
||||
/* When there is an etag, it means the transfer was complete */
|
||||
state = HBF_SUCCESS;
|
||||
|
||||
if( etag[0] == '"' && etag[ strlen(etag)-1] == '"') {
|
||||
int len = strlen( etag )-2;
|
||||
blk->etag = malloc( len+1 );
|
||||
strncpy( blk->etag, etag+1, len );
|
||||
blk->etag[len] = '\0';
|
||||
} else {
|
||||
blk->etag = strdup( etag );
|
||||
}
|
||||
} else {
|
||||
/* DEBUG_HBF("OOOOOOOO No etag returned!"); */
|
||||
}
|
||||
|
||||
/* check if the server was able to set the mtime already. */
|
||||
etag = ne_get_response_header(req, "X-OC-MTime");
|
||||
if( etag && strcmp(etag, "accepted") == 0 ) {
|
||||
/* the server acknowledged that the mtime was set. */
|
||||
transfer->modtime_accepted = 1;
|
||||
}
|
||||
|
||||
etag = ne_get_response_header(req, "OC-FileID");
|
||||
if( etag ) {
|
||||
transfer->file_id = strdup( etag );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NE_AUTH:
|
||||
state = HBF_AUTH_FAIL;
|
||||
blk->state = HBF_TRANSFER_FAILED;
|
||||
break;
|
||||
case NE_PROXYAUTH:
|
||||
state = HBF_PROXY_AUTH_FAIL;
|
||||
blk->state = HBF_TRANSFER_FAILED;
|
||||
break;
|
||||
case NE_CONNECT:
|
||||
state = HBF_CONNECT_FAIL;
|
||||
blk->state = HBF_TRANSFER_FAILED;
|
||||
break;
|
||||
case NE_TIMEOUT:
|
||||
state = HBF_TIMEOUT_FAIL;
|
||||
blk->state = HBF_TRANSFER_FAILED;
|
||||
break;
|
||||
case NE_ERROR:
|
||||
state = HBF_FAIL;
|
||||
blk->state = HBF_TRANSFER_FAILED;
|
||||
break;
|
||||
}
|
||||
|
||||
blk->http_result_code = req_status->code;
|
||||
if( req_status->reason_phrase ) {
|
||||
blk->http_error_msg = strdup(req_status->reason_phrase);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
Hbf_State hbf_validate_source_file( hbf_transfer_t *transfer ) {
|
||||
Hbf_State state = HBF_SUCCESS;
|
||||
hbf_stat_t sb;
|
||||
|
||||
if( transfer == NULL ) {
|
||||
state = HBF_PARAM_FAIL;
|
||||
}
|
||||
|
||||
if( state == HBF_SUCCESS ) {
|
||||
if( transfer->fd <= 0 ) {
|
||||
state = HBF_PARAM_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if( state == HBF_SUCCESS ) {
|
||||
int rc = _hbf_fstat( transfer->fd, &sb );
|
||||
if( rc != 0 ) {
|
||||
state = HBF_STAT_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if( state == HBF_SUCCESS ) {
|
||||
if( sb.st_mtime != transfer->modtime || sb.st_size != transfer->stat_size ) {
|
||||
state = HBF_SOURCE_FILE_CHANGE;
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
/* Get the HTTP error code for the last request */
|
||||
static int _hbf_http_error_code(ne_session *session) {
|
||||
const char *msg = ne_get_error( session );
|
||||
char *msg2;
|
||||
int err;
|
||||
err = strtol(msg, &msg2, 10);
|
||||
if (msg == msg2) {
|
||||
err = 0;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static Hbf_State _hbf_transfer_no_chunk(ne_session *session, hbf_transfer_t *transfer, const char *verb) {
|
||||
int res;
|
||||
const ne_status* req_status;
|
||||
|
||||
ne_request *req = ne_request_create(session, verb ? verb : "PUT", transfer->url);
|
||||
if (!req)
|
||||
return HBF_MEMORY_FAIL;
|
||||
|
||||
ne_add_request_header( req, "Content-Type", "application/octet-stream");
|
||||
|
||||
ne_set_request_body_fd(req, transfer->fd, 0, transfer->stat_size);
|
||||
DEBUG_HBF("HBF: chunking not supported for %s", transfer->url);
|
||||
res = ne_request_dispatch(req);
|
||||
req_status = ne_get_status( req );
|
||||
|
||||
if (res == NE_OK && req_status->klass == 2) {
|
||||
ne_request_destroy(req);
|
||||
return HBF_SUCCESS;
|
||||
}
|
||||
|
||||
if( transfer->error_string ) free( transfer->error_string );
|
||||
transfer->error_string = strdup( ne_get_error(session) );
|
||||
transfer->status_code = req_status->code;
|
||||
ne_request_destroy(req);
|
||||
return HBF_FAIL;
|
||||
}
|
||||
|
||||
Hbf_State hbf_transfer( ne_session *session, hbf_transfer_t *transfer, const char *verb ) {
|
||||
Hbf_State state = HBF_TRANSFER_SUCCESS;
|
||||
int cnt;
|
||||
|
||||
if( ! session ) {
|
||||
state = HBF_SESSION_FAIL;
|
||||
}
|
||||
if( ! transfer ) {
|
||||
state = HBF_SPLITLIST_FAIL;
|
||||
}
|
||||
if( ! verb ) {
|
||||
state = HBF_PARAM_FAIL;
|
||||
}
|
||||
|
||||
if(state == HBF_TRANSFER_SUCCESS) {
|
||||
DEBUG_HBF("%s request to %s", verb, transfer->url);
|
||||
}
|
||||
|
||||
for( cnt=0; state == HBF_TRANSFER_SUCCESS && cnt < transfer->block_cnt; cnt++ ) {
|
||||
/* cnt goes from O to block_cnt, but block_id starts at start_id and wrap around
|
||||
* That way if we have not finished uploaded when we reach block_cnt, we re-upload
|
||||
* the beginning of the file that the server did not have in cache anymore.
|
||||
*/
|
||||
int block_id = (cnt + transfer->start_id) % transfer->block_cnt;
|
||||
hbf_block_t *block = transfer->block_arr[block_id];
|
||||
char *transfer_url = NULL;
|
||||
|
||||
if( ! block ) state = HBF_PARAM_FAIL;
|
||||
|
||||
if( transfer->abort_cb ) {
|
||||
int do_abort = (transfer->abort_cb)(transfer->user_data);
|
||||
if( do_abort ) {
|
||||
state = HBF_USER_ABORTED;
|
||||
transfer->start_id = block_id % transfer->block_cnt;
|
||||
}
|
||||
}
|
||||
|
||||
if( state == HBF_TRANSFER_SUCCESS ) {
|
||||
transfer_url = get_transfer_url( transfer, block_id );
|
||||
if( ! transfer_url ) {
|
||||
state = HBF_PARAM_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if( state == HBF_TRANSFER_SUCCESS ) {
|
||||
if( transfer->block_cnt > 1 && cnt > 0 ) {
|
||||
/* The block count is > 1, check size and mtime before transmitting. */
|
||||
state = hbf_validate_source_file(transfer);
|
||||
if( state == HBF_SOURCE_FILE_CHANGE ) {
|
||||
/* The source file has changed meanwhile */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( state == HBF_TRANSFER_SUCCESS || state == HBF_SUCCESS ) {
|
||||
ne_request *req = ne_request_create(session, verb, transfer_url);
|
||||
|
||||
if( req ) {
|
||||
char buf[21];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%"PRId64, transfer->stat_size);
|
||||
ne_add_request_header(req, "OC-Total-Length", buf);
|
||||
if( transfer->oc_header_modtime > 0 ) {
|
||||
snprintf(buf, sizeof(buf), "%"PRId64, transfer->oc_header_modtime);
|
||||
ne_add_request_header(req, "X-OC-Mtime", buf);
|
||||
}
|
||||
|
||||
if( transfer->previous_etag ) {
|
||||
ne_add_request_header(req, "If-Match", transfer->previous_etag);
|
||||
}
|
||||
|
||||
if( transfer->block_cnt > 1 ) {
|
||||
ne_add_request_header(req, "OC-Chunked", "1");
|
||||
snprintf(buf, sizeof(buf), "%"PRId64, transfer->threshold);
|
||||
ne_add_request_header(req, "OC-Chunk-Size", buf);
|
||||
}
|
||||
ne_add_request_header( req, "Content-Type", "application/octet-stream");
|
||||
|
||||
state = _hbf_dav_request(transfer, req, transfer->fd, block );
|
||||
|
||||
if( state != HBF_TRANSFER_SUCCESS && state != HBF_SUCCESS) {
|
||||
if( transfer->error_string ) free( transfer->error_string );
|
||||
transfer->error_string = strdup( ne_get_error(session) );
|
||||
transfer->start_id = block_id % transfer->block_cnt;
|
||||
/* Set the code of the last transmission. */
|
||||
state = HBF_FAIL;
|
||||
transfer->status_code = transfer->block_arr[block_id]->http_result_code;
|
||||
}
|
||||
ne_request_destroy(req);
|
||||
|
||||
if (transfer->block_cnt > 1 && state == HBF_SUCCESS && cnt == 0) {
|
||||
/* Success on the first chunk is suspicious.
|
||||
It could happen that the server did not support chunking */
|
||||
int rc = ne_delete(session, transfer_url);
|
||||
if (rc == NE_OK && _hbf_http_error_code(session) == 204) {
|
||||
/* If delete suceeded, it means some proxy strips the OC_CHUNKING header
|
||||
start again without chunking: */
|
||||
free( transfer_url );
|
||||
return _hbf_transfer_no_chunk(session, transfer, verb);
|
||||
}
|
||||
}
|
||||
|
||||
if (state == HBF_TRANSFER_SUCCESS && transfer->chunk_finished_cb) {
|
||||
transfer->chunk_finished_cb(transfer, block_id, transfer->user_data);
|
||||
}
|
||||
|
||||
} else {
|
||||
state = HBF_MEMORY_FAIL;
|
||||
}
|
||||
}
|
||||
free( transfer_url );
|
||||
}
|
||||
|
||||
/* do the source file validation finally (again). */
|
||||
if( state == HBF_TRANSFER_SUCCESS ) {
|
||||
/* This means that no etag was returned on one of the chunks to indicate
|
||||
* that the upload was finished. */
|
||||
state = HBF_TRANSFER_NOT_ACKED;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
int hbf_fail_http_code( hbf_transfer_t *transfer )
|
||||
{
|
||||
int cnt;
|
||||
|
||||
if( ! transfer ) return 0;
|
||||
|
||||
for( cnt = 0; cnt < transfer->block_cnt; cnt++ ) {
|
||||
int block_id = (cnt + transfer->start_id) % transfer->block_cnt;
|
||||
hbf_block_t *block = transfer->block_arr[block_id];
|
||||
|
||||
if( block->state != HBF_NOT_TRANSFERED && block->state != HBF_TRANSFER_SUCCESS ) {
|
||||
return block->http_result_code;
|
||||
}
|
||||
}
|
||||
return 200;
|
||||
}
|
||||
|
||||
const char *hbf_transfer_etag( hbf_transfer_t *transfer )
|
||||
{
|
||||
int cnt;
|
||||
const char *etag = NULL;
|
||||
|
||||
if( ! transfer ) return 0;
|
||||
|
||||
/* Loop over all parts and do a assertion that there is only one etag. */
|
||||
for( cnt = 0; cnt < transfer->block_cnt; cnt++ ) {
|
||||
int block_id = (cnt + transfer->start_id) % transfer->block_cnt;
|
||||
hbf_block_t *block = transfer->block_arr[block_id];
|
||||
if( block->etag ) {
|
||||
if( etag && strcmp(etag, block->etag) != 0 ) {
|
||||
/* multiple etags in the transfer, not equal. */
|
||||
DEBUG_HBF( "WARN: etags are not equal in blocks of one single transfer." );
|
||||
}
|
||||
etag = block->etag;
|
||||
}
|
||||
}
|
||||
return etag;
|
||||
}
|
||||
|
||||
const char *hbf_transfer_file_id( hbf_transfer_t *transfer )
|
||||
{
|
||||
const char *re = NULL;
|
||||
if(transfer) {
|
||||
re = transfer->file_id;
|
||||
}
|
||||
return re;
|
||||
}
|
||||
|
||||
const char *hbf_error_string(hbf_transfer_t *transfer, Hbf_State state)
|
||||
{
|
||||
const char *re;
|
||||
int cnt;
|
||||
switch( state ) {
|
||||
case HBF_SUCCESS:
|
||||
re = "Ok.";
|
||||
break;
|
||||
case HBF_NOT_TRANSFERED: /* never tried to transfer */
|
||||
re = "Block was not yet tried to transfer.";
|
||||
break;
|
||||
case HBF_TRANSFER: /* transfer currently running */
|
||||
re = "Block is currently transferred.";
|
||||
break;
|
||||
case HBF_TRANSFER_FAILED: /* transfer tried but failed */
|
||||
re = "Block transfer failed.";
|
||||
break;
|
||||
case HBF_TRANSFER_SUCCESS: /* transfer succeeded. */
|
||||
re = "Block transfer successful.";
|
||||
break;
|
||||
case HBF_SPLITLIST_FAIL: /* the file could not be split */
|
||||
re = "Splitlist could not be computed.";
|
||||
break;
|
||||
case HBF_SESSION_FAIL:
|
||||
re = "No valid session in transfer.";
|
||||
break;
|
||||
case HBF_FILESTAT_FAIL:
|
||||
re = "Source file could not be stat'ed.";
|
||||
break;
|
||||
case HBF_PARAM_FAIL:
|
||||
re = "Parameter fail.";
|
||||
break;
|
||||
case HBF_AUTH_FAIL:
|
||||
re = "Authentication fail.";
|
||||
break;
|
||||
case HBF_PROXY_AUTH_FAIL:
|
||||
re = "Proxy Authentication fail.";
|
||||
break;
|
||||
case HBF_CONNECT_FAIL:
|
||||
re = "Connection could not be established.";
|
||||
break;
|
||||
case HBF_TIMEOUT_FAIL:
|
||||
re = "Network timeout.";
|
||||
break;
|
||||
case HBF_MEMORY_FAIL:
|
||||
re = "Out of memory.";
|
||||
break;
|
||||
case HBF_STAT_FAIL:
|
||||
re = "Filesystem stat on file failed.";
|
||||
break;
|
||||
case HBF_SOURCE_FILE_CHANGE:
|
||||
re = "Source file changed too often during upload.";
|
||||
break;
|
||||
case HBF_USER_ABORTED:
|
||||
re = "Transmission aborted by user.";
|
||||
break;
|
||||
case HBF_TRANSFER_NOT_ACKED:
|
||||
re = "The server did not provide an Etag.";
|
||||
break;
|
||||
case HBF_FAIL:
|
||||
default:
|
||||
for( cnt = 0; cnt < transfer->block_cnt; cnt++ ) {
|
||||
int block_id = (cnt + transfer->start_id) % transfer->block_cnt;
|
||||
hbf_block_t *block = transfer->block_arr[block_id];
|
||||
|
||||
if( block->state != HBF_NOT_TRANSFERED && block->state != HBF_TRANSFER_SUCCESS
|
||||
&& block->http_error_msg != NULL) {
|
||||
return block->http_error_msg;
|
||||
}
|
||||
}
|
||||
re = "Unknown error.";
|
||||
}
|
||||
return re;
|
||||
}
|
||||
|
||||
void hbf_set_abort_callback( hbf_transfer_t *transfer, hbf_abort_callback cb)
|
||||
{
|
||||
if( transfer ) {
|
||||
transfer->abort_cb = cb;
|
||||
}
|
||||
}
|
||||
|
||||
void hbf_set_log_callback(hbf_transfer_t* transfer, hbf_log_callback cb)
|
||||
{
|
||||
if( transfer ) {
|
||||
transfer->log_cb = cb;
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
/**
|
||||
* http big file functions
|
||||
*
|
||||
* Copyright (c) 2012 by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _HBF_SEND_H
|
||||
#define _HBF_SEND_H
|
||||
|
||||
#include "config_csync.h"
|
||||
#ifdef NEON_WITH_LFS /* Switch on LFS in libneon. Never remove the NE_LFS! */
|
||||
#define NE_LFS
|
||||
#endif
|
||||
|
||||
#include <neon/ne_session.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum hbf_state_e {
|
||||
HBF_SUCCESS,
|
||||
HBF_NOT_TRANSFERED, /* never tried to transfer */
|
||||
HBF_TRANSFER, /* transfer currently running */
|
||||
HBF_TRANSFER_FAILED, /* transfer tried but failed */
|
||||
HBF_TRANSFER_SUCCESS, /* block transfer succeeded. */
|
||||
HBF_SPLITLIST_FAIL, /* the file could not be split */
|
||||
HBF_SESSION_FAIL,
|
||||
HBF_FILESTAT_FAIL,
|
||||
HBF_PARAM_FAIL,
|
||||
HBF_AUTH_FAIL,
|
||||
HBF_PROXY_AUTH_FAIL,
|
||||
HBF_CONNECT_FAIL,
|
||||
HBF_TIMEOUT_FAIL,
|
||||
HBF_MEMORY_FAIL,
|
||||
HBF_STAT_FAIL,
|
||||
HBF_SOURCE_FILE_CHANGE,
|
||||
HBF_USER_ABORTED,
|
||||
HBF_TRANSFER_NOT_ACKED,
|
||||
HBF_FAIL
|
||||
};
|
||||
|
||||
typedef enum hbf_state_e Hbf_State;
|
||||
|
||||
typedef struct hbf_block_s hbf_block_t;
|
||||
|
||||
struct hbf_block_s {
|
||||
int seq_number;
|
||||
|
||||
int64_t start;
|
||||
int64_t size;
|
||||
|
||||
Hbf_State state;
|
||||
int http_result_code;
|
||||
char *http_error_msg;
|
||||
char *etag;
|
||||
|
||||
int tries;
|
||||
};
|
||||
|
||||
typedef struct hbf_transfer_s hbf_transfer_t;
|
||||
|
||||
/* Callback for to check on abort */
|
||||
typedef int (*hbf_abort_callback) (void *);
|
||||
typedef void (*hbf_log_callback) (const char *, const char *, void*);
|
||||
typedef void (*hbf_chunk_finished_callback) (hbf_transfer_t*,int, void*);
|
||||
|
||||
struct hbf_transfer_s {
|
||||
hbf_block_t **block_arr;
|
||||
int block_cnt;
|
||||
int fd;
|
||||
int transfer_id;
|
||||
char *url;
|
||||
int start_id;
|
||||
|
||||
int status_code;
|
||||
char *error_string;
|
||||
|
||||
int64_t stat_size;
|
||||
time_t modtime;
|
||||
time_t oc_header_modtime;
|
||||
int64_t block_size;
|
||||
int64_t threshold;
|
||||
|
||||
void *user_data;
|
||||
hbf_abort_callback abort_cb;
|
||||
hbf_log_callback log_cb;
|
||||
hbf_chunk_finished_callback chunk_finished_cb;
|
||||
int modtime_accepted;
|
||||
const char *previous_etag; /* etag send as the If-Match http header */
|
||||
char *file_id;
|
||||
|
||||
#ifndef NDEBUG
|
||||
int64_t calc_size;
|
||||
#endif
|
||||
};
|
||||
|
||||
hbf_transfer_t *hbf_init_transfer( const char *dest_uri );
|
||||
|
||||
Hbf_State hbf_transfer( ne_session *session, hbf_transfer_t *transfer, const char *verb );
|
||||
|
||||
Hbf_State hbf_splitlist( hbf_transfer_t *transfer, int fd );
|
||||
|
||||
void hbf_free_transfer( hbf_transfer_t *transfer );
|
||||
|
||||
const char *hbf_error_string(hbf_transfer_t* transfer, Hbf_State state);
|
||||
|
||||
const char *hbf_transfer_etag( hbf_transfer_t *transfer );
|
||||
|
||||
const char *hbf_transfer_file_id( hbf_transfer_t *transfer );
|
||||
|
||||
void hbf_set_abort_callback( hbf_transfer_t *transfer, hbf_abort_callback cb);
|
||||
void hbf_set_log_callback( hbf_transfer_t *transfer, hbf_log_callback cb);
|
||||
|
||||
/* returns an http (error) code of the transmission. If the transmission
|
||||
* succeeded, the code is 200. If it failed, its the error code of the
|
||||
* first part transmission that failed.
|
||||
*/
|
||||
int hbf_fail_http_code( hbf_transfer_t *transfer );
|
||||
|
||||
Hbf_State hbf_validate_source_file( hbf_transfer_t *transfer );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,18 +0,0 @@
|
||||
project(hbf_test C )
|
||||
|
||||
add_definitions(-DUNIT_TESTING=1)
|
||||
|
||||
find_package(CMocka REQUIRED)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMOCKA_INCLUDE_DIRS}
|
||||
${NEON_INCLUDE_DIRS}
|
||||
${HTTPBF_PUBLIC_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
add_executable(send_test hbf_send_test.c)
|
||||
target_link_libraries(send_test ${CMOCKA_LIBRARIES} ${NEON_LIBRARIES} ${HBF_LIBRARY} )
|
||||
|
||||
|
||||
|
Antes Largura: | Altura: | Tamanho: 1.2 MiB |
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
* httpbf - send big files via http
|
||||
*
|
||||
* Copyright (c) 2012 Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE /* See feature_test_macros(7) */
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <cmocka.h>
|
||||
|
||||
#include "config_csync.h"
|
||||
|
||||
#include <httpbf.h>
|
||||
|
||||
|
||||
// A test case that does nothing and succeeds.
|
||||
static void null_test_success(void **state) {
|
||||
(void) state;
|
||||
}
|
||||
|
||||
|
||||
static char* test_file( const char* name ) {
|
||||
if( ! name ) return 0;
|
||||
|
||||
char path[260];
|
||||
strcpy( path, TESTFILEDIR);
|
||||
if(path[strlen(TESTFILEDIR)-1] != '/')
|
||||
strcat( path, "/");
|
||||
strcat( path, name );
|
||||
|
||||
return strdup(path);
|
||||
}
|
||||
|
||||
static void test_get_transfer_url( void **state ) {
|
||||
const char *url = "http://example.org/owncloud";
|
||||
const char *turl = NULL;
|
||||
char res[256];
|
||||
int i;
|
||||
Hbf_State hbf_state;
|
||||
|
||||
hbf_transfer_t *list = NULL;
|
||||
list = hbf_init_transfer( url );
|
||||
assert_non_null( list );
|
||||
|
||||
/* open a file */
|
||||
int fd = open( test_file("church.jpg"), O_RDONLY );
|
||||
assert_true(fd >= 0);
|
||||
|
||||
hbf_state = hbf_splitlist(list, fd);
|
||||
assert_true( hbf_state == HBF_SUCCESS);
|
||||
|
||||
for( i=0; i < list->block_cnt; i++ ) {
|
||||
turl = get_transfer_url( list, i );
|
||||
|
||||
sprintf(res, "%s-chunking-%d-%d-%d", url, list->transfer_id,
|
||||
list->block_cnt, i );
|
||||
printf( "XX: %s\n", res );
|
||||
assert_string_equal( turl, res );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void test_hbf_init_transfer( void **state ) {
|
||||
hbf_transfer_t *list = NULL;
|
||||
const char *url = "http://example.org/owncloud";
|
||||
|
||||
list = hbf_init_transfer( url );
|
||||
assert_non_null( list );
|
||||
assert_string_equal( url, list->url );
|
||||
}
|
||||
|
||||
/* test with a file size that is not a multiply of the slize size. */
|
||||
static void test_hbf_splitlist_odd( void **state ){
|
||||
|
||||
hbf_transfer_t *list = NULL;
|
||||
const char *dest_url = "http://localhost/ocm/remote.php/webdav/big/church.jpg";
|
||||
|
||||
/* open a file */
|
||||
int fd = open(test_file("church.jpg"), O_RDONLY);
|
||||
assert_true(fd >= 0);
|
||||
|
||||
int prev_id = 0;
|
||||
int i;
|
||||
|
||||
Hbf_State hbf_state;
|
||||
|
||||
/* do a smoke test for uniqueness */
|
||||
for( i=0; i < 10000; i++) {
|
||||
list = hbf_init_transfer(dest_url);
|
||||
assert_non_null(list);
|
||||
usleep(1);
|
||||
hbf_state = hbf_splitlist(list, fd);
|
||||
|
||||
assert_int_not_equal(list->transfer_id, prev_id);
|
||||
prev_id = list->transfer_id;
|
||||
hbf_free_transfer(list);
|
||||
}
|
||||
|
||||
list = hbf_init_transfer(dest_url);
|
||||
assert_non_null(list);
|
||||
|
||||
hbf_state = hbf_splitlist(list, fd);
|
||||
assert_non_null(list);
|
||||
assert_int_equal(list->calc_size, list->stat_size);
|
||||
assert_int_not_equal(list->block_cnt, 0);
|
||||
assert_true( hbf_state == HBF_SUCCESS);
|
||||
|
||||
/* checks on the block list */
|
||||
int seen_zero_seq = 0;
|
||||
int prev_seq = -1;
|
||||
int64_t prev_block_end = -1;
|
||||
|
||||
for( i=0; i < list->block_cnt; i++) {
|
||||
hbf_block_t *blk = list->block_arr[i];
|
||||
assert_non_null(blk);
|
||||
if( blk->seq_number == 0 ) seen_zero_seq++;
|
||||
|
||||
assert_int_equal(prev_seq, blk->seq_number -1 );
|
||||
prev_seq = blk->seq_number;
|
||||
|
||||
assert_true((prev_block_end+1) == (blk->start));
|
||||
prev_block_end = blk->start + blk->size;
|
||||
}
|
||||
/* Make sure we exactly saw blk->seq_number == 0 exactly one times */
|
||||
assert_int_equal( seen_zero_seq, 1 );
|
||||
|
||||
hbf_free_transfer( list );
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
const UnitTest tests[] = {
|
||||
unit_test(null_test_success),
|
||||
unit_test(test_hbf_splitlist_odd),
|
||||
unit_test(test_hbf_init_transfer),
|
||||
unit_test(test_get_transfer_url)
|
||||
};
|
||||
return run_tests(tests);
|
||||
}
|
||||
@@ -393,8 +393,8 @@ int c_parse_uri(const char *uri,
|
||||
|
||||
/*
|
||||
* This function takes a path and converts it to a UNC representation of the
|
||||
* string. That means that it prepends a \\?\ and convertes all slashes to
|
||||
* backslashes.
|
||||
* string. That means that it prepends a \\?\ (unless already UNC) and converts
|
||||
* all slashes to backslashes.
|
||||
*
|
||||
* Note the following:
|
||||
* - The string must be absolute.
|
||||
@@ -408,27 +408,28 @@ int c_parse_uri(const char *uri,
|
||||
{
|
||||
int len = 0;
|
||||
char *longStr = NULL;
|
||||
int i = 4; // index where to start changing "/"=>"\"
|
||||
|
||||
len = strlen(str);
|
||||
longStr = c_malloc(len+5);
|
||||
*longStr = '\0';
|
||||
|
||||
// prepend \\?\ and convert '/' => '\' to support long names
|
||||
if( str[0] == '/' ) {
|
||||
strncpy( longStr, "\\\\?", 4);
|
||||
i=3;
|
||||
if( str[0] == '/' || str[0] == '\\' ) {
|
||||
// Don't prepend if already UNC
|
||||
if( !(len > 1 && (str[1] == '/' || str[1] == '\\')) ) {
|
||||
strcpy( longStr, "\\\\?");
|
||||
}
|
||||
} else {
|
||||
strncpy( longStr, "\\\\?\\", 5); // prepend string by this four magic chars.
|
||||
strcpy( longStr, "\\\\?\\"); // prepend string by this four magic chars.
|
||||
}
|
||||
strncat( longStr, str, len );
|
||||
|
||||
/* replace all occurences of / with the windows native \ */
|
||||
while(longStr[i] != '\0') {
|
||||
if(longStr[i] == '/') {
|
||||
longStr[i] = '\\';
|
||||
char *c = longStr;
|
||||
for (; *c; ++c) {
|
||||
if(*c == '/') {
|
||||
*c = '\\';
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return longStr;
|
||||
}
|
||||
|
||||
@@ -215,6 +215,25 @@ int c_strlist_add(c_strlist_t *strlist, const char *string) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int c_strlist_add_grow(c_strlist_t **strlist, const char *string) {
|
||||
if (*strlist == NULL) {
|
||||
*strlist = c_strlist_new(32);
|
||||
if (*strlist == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((*strlist)->count == (*strlist)->size) {
|
||||
c_strlist_t *list = c_strlist_expand(*strlist, 2 * (*strlist)->size);
|
||||
if (list == NULL) {
|
||||
return -1;
|
||||
}
|
||||
*strlist = list;
|
||||
}
|
||||
|
||||
return c_strlist_add(*strlist, string);
|
||||
}
|
||||
|
||||
void c_strlist_clear(c_strlist_t *strlist) {
|
||||
size_t i = 0;
|
||||
|
||||
|
||||
@@ -112,6 +112,19 @@ c_strlist_t *c_strlist_expand(c_strlist_t *strlist, size_t size);
|
||||
*/
|
||||
int c_strlist_add(c_strlist_t *strlist, const char *string);
|
||||
|
||||
/**
|
||||
* @brief Add a string to the stringlist, growing it if necessary
|
||||
*
|
||||
* Duplicates the string and stores it in the stringlist.
|
||||
* It also initializes the stringlist if it starts out as null.
|
||||
*
|
||||
* @param strlist Stringlist to add the string.
|
||||
* @param string String to add.
|
||||
*
|
||||
* @return 0 on success, less than 0 and errno set if an error occured.
|
||||
*/
|
||||
int c_strlist_add_grow(c_strlist_t **strlist, const char *string);
|
||||
|
||||
/**
|
||||
* @brief Removes all strings from the list.
|
||||
*
|
||||
|
||||
@@ -36,9 +36,6 @@
|
||||
#define CSYNC_LOG_CATEGORY_NAME "csync.vio.main"
|
||||
|
||||
#include "csync_log.h"
|
||||
#if USE_NEON
|
||||
#include "csync_owncloud.h"
|
||||
#endif
|
||||
|
||||
csync_vio_handle_t *csync_vio_opendir(CSYNC *ctx, const char *name) {
|
||||
switch(ctx->replica) {
|
||||
@@ -132,8 +129,5 @@ char *csync_vio_get_status_string(CSYNC *ctx) {
|
||||
if(ctx->error_string) {
|
||||
return ctx->error_string;
|
||||
}
|
||||
#ifdef USE_NEON
|
||||
return owncloud_error_string(ctx);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -157,13 +157,6 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf->name = c_basename(uri);
|
||||
|
||||
if (buf->name == NULL) {
|
||||
csync_vio_file_stat_destroy(buf);
|
||||
c_free_locale_string(wuri);
|
||||
return -1;
|
||||
}
|
||||
buf->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
|
||||
|
||||
switch(sb.st_mode & S_IFMT) {
|
||||
@@ -210,9 +203,6 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
#endif
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_FLAGS;
|
||||
|
||||
buf->device = sb.st_dev;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_DEVICE;
|
||||
|
||||
buf->inode = sb.st_ino;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_INODE;
|
||||
|
||||
|
||||
@@ -74,6 +74,12 @@ csync_vio_handle_t *csync_vio_local_opendir(const char *name) {
|
||||
}
|
||||
|
||||
if (!dirname || handle->hFind == INVALID_HANDLE_VALUE) {
|
||||
int retcode = GetLastError();
|
||||
if( retcode == ERROR_FILE_NOT_FOUND ) {
|
||||
errno = ENOENT;
|
||||
} else {
|
||||
errno = EACCES;
|
||||
}
|
||||
SAFE_FREE(handle);
|
||||
return NULL;
|
||||
}
|
||||
@@ -99,6 +105,9 @@ int csync_vio_local_closedir(csync_vio_handle_t *dhandle) {
|
||||
// FindClose returns non-zero on success
|
||||
if( FindClose(handle->hFind) != 0 ) {
|
||||
rc = 0;
|
||||
} else {
|
||||
// error case, set errno
|
||||
errno = EBADF;
|
||||
}
|
||||
|
||||
SAFE_FREE(handle->path);
|
||||
@@ -107,17 +116,39 @@ int csync_vio_local_closedir(csync_vio_handle_t *dhandle) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static time_t FileTimeToUnixTime(FILETIME *filetime, DWORD *remainder)
|
||||
{
|
||||
long long int t = filetime->dwHighDateTime;
|
||||
t <<= 32;
|
||||
t += (UINT32)filetime->dwLowDateTime;
|
||||
t -= 116444736000000000LL;
|
||||
if (t < 0)
|
||||
{
|
||||
if (remainder) *remainder = 9999999 - (-t - 1) % 10000000;
|
||||
return -1 - ((-t - 1) / 10000000);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (remainder) *remainder = t % 10000000;
|
||||
return t / 10000000;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
errno = 0;
|
||||
file_stat = csync_vio_file_stat_new();
|
||||
if (file_stat == NULL) {
|
||||
goto err;
|
||||
errno = ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
file_stat->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
|
||||
|
||||
@@ -138,13 +169,43 @@ 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_DIRECTORY) {
|
||||
file_stat->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
|
||||
} else {
|
||||
file_stat->type = CSYNC_VIO_FILE_TYPE_REGULAR;
|
||||
}
|
||||
if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT
|
||||
&& handle->ffd.dwReserved0 & IO_REPARSE_TAG_SYMLINK) {
|
||||
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
|
||||
|| handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE
|
||||
|| handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) {
|
||||
file_stat->type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
|
||||
} else if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
file_stat->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
|
||||
} else {
|
||||
file_stat->type = CSYNC_VIO_FILE_TYPE_REGULAR;
|
||||
}
|
||||
|
||||
return file_stat;
|
||||
file_stat->flags = CSYNC_VIO_FILE_FLAGS_NONE;
|
||||
/* Check for the hidden flag */
|
||||
if( handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ) {
|
||||
file_stat->flags |= CSYNC_VIO_FILE_FLAGS_HIDDEN;
|
||||
}
|
||||
|
||||
file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_FLAGS;
|
||||
file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
|
||||
|
||||
file_stat->size = (handle->ffd.nFileSizeHigh * ((int64_t)(MAXDWORD)+1)) + handle->ffd.nFileSizeLow;
|
||||
file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
|
||||
|
||||
file_stat->atime = FileTimeToUnixTime(&handle->ffd.ftLastAccessTime, &rem);
|
||||
file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ATIME;
|
||||
|
||||
file_stat->mtime = FileTimeToUnixTime(&handle->ffd.ftLastWriteTime, &rem);
|
||||
/* CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Local File MTime: %llu", (unsigned long long) buf->mtime ); */
|
||||
file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;
|
||||
|
||||
file_stat->ctime = FileTimeToUnixTime(&handle->ffd.ftCreationTime, &rem);
|
||||
file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_CTIME;
|
||||
|
||||
return file_stat;
|
||||
|
||||
err:
|
||||
SAFE_FREE(file_stat);
|
||||
@@ -152,34 +213,21 @@ err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static time_t FileTimeToUnixTime(FILETIME *filetime, DWORD *remainder)
|
||||
{
|
||||
long long int t = filetime->dwHighDateTime;
|
||||
t <<= 32;
|
||||
t += (UINT32)filetime->dwLowDateTime;
|
||||
t -= 116444736000000000LL;
|
||||
if (t < 0)
|
||||
{
|
||||
if (remainder) *remainder = 9999999 - (-t - 1) % 10000000;
|
||||
return -1 - ((-t - 1) / 10000000);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (remainder) *remainder = t % 10000000;
|
||||
return t / 10000000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
HANDLE h, hFind;
|
||||
FILETIME ftCreate, ftAccess, ftWrite;
|
||||
/* Almost nothing to do since csync_vio_local_readdir already filled up most of the information
|
||||
But we still need to fetch the file ID.
|
||||
Possible optimisation: only fetch the file id when we need it (for new files)
|
||||
*/
|
||||
|
||||
HANDLE h;
|
||||
BY_HANDLE_FILE_INFORMATION fileInfo;
|
||||
WIN32_FIND_DATAW FindFileData;
|
||||
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, NULL );
|
||||
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();
|
||||
@@ -195,47 +243,6 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf->flags = CSYNC_VIO_FILE_FLAGS_NONE;
|
||||
do {
|
||||
// Check first if it is a symlink (code from c_islink)
|
||||
if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
|
||||
hFind = FindFirstFileW(wuri, &FindFileData );
|
||||
if (hFind != INVALID_HANDLE_VALUE) {
|
||||
if( (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
|
||||
(FindFileData.dwReserved0 & IO_REPARSE_TAG_SYMLINK) ) {
|
||||
buf->flags = CSYNC_VIO_FILE_FLAGS_SYMLINK;
|
||||
buf->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
FindClose(hFind);
|
||||
}
|
||||
if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DEVICE
|
||||
|| fileInfo.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE
|
||||
|| fileInfo.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) {
|
||||
buf->type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
buf->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
|
||||
break;
|
||||
}
|
||||
// fallthrough:
|
||||
buf->type = CSYNC_VIO_FILE_TYPE_REGULAR;
|
||||
break;
|
||||
} while (0);
|
||||
|
||||
/* Check for the hidden flag */
|
||||
if( fileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ) {
|
||||
buf->flags |= CSYNC_VIO_FILE_FLAGS_HIDDEN;
|
||||
}
|
||||
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_FLAGS;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
|
||||
|
||||
buf->device = fileInfo.dwVolumeSerialNumber;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_DEVICE;
|
||||
|
||||
/* Get the Windows file id as an inode replacement. */
|
||||
FileIndex.HighPart = fileInfo.nFileIndexHigh;
|
||||
FileIndex.LowPart = fileInfo.nFileIndexLow;
|
||||
@@ -243,28 +250,7 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
/* printf("Index: %I64i\n", FileIndex.QuadPart); */
|
||||
buf->inode = FileIndex.QuadPart;
|
||||
|
||||
buf->size = (fileInfo.nFileSizeHigh * ((int64_t)(MAXDWORD)+1)) + fileInfo.nFileSizeLow;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
|
||||
|
||||
/* Get the file time with a win32 call rather than through stat. See
|
||||
* http://www.codeproject.com/Articles/1144/Beating-the-Daylight-Savings-Time-bug-and-getting
|
||||
* for deeper explanation.
|
||||
*/
|
||||
if( GetFileTime(h, &ftCreate, &ftAccess, &ftWrite) ) {
|
||||
DWORD rem;
|
||||
buf->atime = FileTimeToUnixTime(&ftAccess, &rem);
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ATIME;
|
||||
|
||||
buf->mtime = FileTimeToUnixTime(&ftWrite, &rem);
|
||||
/* CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Local File MTime: %llu", (unsigned long long) buf->mtime ); */
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;
|
||||
|
||||
buf->ctime = FileTimeToUnixTime(&ftCreate, &rem);
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_CTIME;
|
||||
}
|
||||
|
||||
c_free_locale_string(wuri);
|
||||
CloseHandle(h);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ include_directories(
|
||||
${CSTDLIB_PUBLIC_INCLUDE_DIRS}
|
||||
${CMAKE_BINARY_DIR}
|
||||
${CMOCKA_INCLUDE_DIR}
|
||||
${HTTPBF_PUBLIC_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
include_directories(${CHECK_INCLUDE_DIRS})
|
||||
@@ -54,10 +53,6 @@ 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})
|
||||
|
||||
# httpbf
|
||||
set(TEST_HTTPBF_LIBRARIES ${TEST_TARGET_LIBRARIES} ${NEON_LIBRARIES})
|
||||
add_cmocka_test(check_httpbf httpbf_tests/hbf_send_test.c ${TEST_HTTPBF_LIBRARIES} )
|
||||
|
||||
if(UNIT_TESTING)
|
||||
INSTALL( FILES "${CMOCKA_LIBRARIES}" DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif(UNIT_TESTING)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
#include "config_csync.h"
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
@@ -47,6 +48,12 @@ static void setup_init(void **state) {
|
||||
rc = csync_exclude_load(EXCLUDE_LIST_FILE, &(csync->excludes));
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
/* and add some unicode stuff */
|
||||
rc = _csync_exclude_add(&(csync->excludes), "*.💩");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = _csync_exclude_add(&(csync->excludes), "пятницы.*");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = csync;
|
||||
}
|
||||
|
||||
@@ -80,7 +87,7 @@ static void check_csync_exclude_load(void **state)
|
||||
rc = csync_exclude_load(EXCLUDE_LIST_FILE, &(csync->excludes) );
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
assert_string_equal(csync->excludes->vector[0], "*.filepart");
|
||||
assert_string_equal(csync->excludes->vector[0], "*~");
|
||||
assert_int_not_equal(csync->excludes->count, 0);
|
||||
}
|
||||
|
||||
@@ -89,6 +96,11 @@ static void check_csync_excluded(void **state)
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
|
||||
rc = csync_excluded(csync, "", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
rc = csync_excluded(csync, "/", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
|
||||
rc = csync_excluded(csync, "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);
|
||||
@@ -139,6 +151,66 @@ static void check_csync_excluded(void **state)
|
||||
rc = csync_excluded(csync, ".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);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
/* excluded */
|
||||
rc = csync_excluded(csync, "unicode/пятницы.txt", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
rc = csync_excluded(csync, "unicode/中文.💩", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void check_csync_excluded_traversal(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
|
||||
_csync_exclude_add( &(csync->excludes), "/exclude" );
|
||||
|
||||
/* Check toplevel dir, the pattern only works for toplevel dir. */
|
||||
rc = csync_excluded_traversal(csync->excludes, "/exclude", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded_traversal(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_traversal(csync->excludes, "/exclude", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded_traversal(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_traversal(csync->excludes, "/excl", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded_traversal(csync->excludes, "meep/excl", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded_traversal(csync->excludes, "meep/excl/file", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED); // because leading dirs aren't checked!
|
||||
|
||||
rc = csync_excluded_traversal(csync->excludes, "/excl", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
|
||||
_csync_exclude_add(&csync->excludes, "/excludepath/withsubdir");
|
||||
|
||||
rc = csync_excluded_traversal(csync->excludes, "/excludepath/withsubdir", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded_traversal(csync->excludes, "/excludepath/withsubdir", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded_traversal(csync->excludes, "/excludepath/withsubdir2", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
|
||||
rc = csync_excluded_traversal(csync->excludes, "/excludepath/withsubdir/foo", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED); // because leading dirs aren't checked!
|
||||
}
|
||||
|
||||
static void check_csync_pathes(void **state)
|
||||
@@ -170,8 +242,25 @@ static void check_csync_pathes(void **state)
|
||||
rc = csync_excluded(csync, "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);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded(csync, "/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);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded(csync, "/excludepath/withsubdir", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
|
||||
rc = csync_excluded(csync, "/excludepath/withsubdir2", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||
|
||||
rc = csync_excluded(csync, "/excludepath/withsubdir/foo", CSYNC_FTW_TYPE_DIR);
|
||||
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
|
||||
}
|
||||
|
||||
static void check_csync_is_windows_reserved_word() {
|
||||
@@ -190,7 +279,51 @@ static void check_csync_is_windows_reserved_word() {
|
||||
assert_true(csync_is_windows_reserved_word("Z:"));
|
||||
assert_true(csync_is_windows_reserved_word("M:"));
|
||||
assert_true(csync_is_windows_reserved_word("m:"));
|
||||
}
|
||||
|
||||
static void check_csync_excluded_performance(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
|
||||
const int N = 10000;
|
||||
int totalRc = 0;
|
||||
|
||||
// Being able to use QElapsedTimer for measurement would be nice...
|
||||
{
|
||||
struct timeval before, after;
|
||||
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);
|
||||
}
|
||||
assert_int_equal(totalRc, CSYNC_NOT_EXCLUDED); // mainly to avoid optimization
|
||||
|
||||
gettimeofday(&after, 0);
|
||||
|
||||
const double total = (after.tv_sec - before.tv_sec)
|
||||
+ (after.tv_usec - before.tv_usec) / 1.0e6;
|
||||
const double perCallMs = total / 2 / N * 1000;
|
||||
printf("csync_excluded: %f ms per call\n", perCallMs);
|
||||
}
|
||||
|
||||
{
|
||||
struct timeval before, after;
|
||||
gettimeofday(&before, 0);
|
||||
|
||||
for (int i = 0; i < N; ++i) {
|
||||
totalRc += csync_excluded_traversal(csync->excludes, "/this/is/quite/a/long/path/with/many/components", CSYNC_FTW_TYPE_DIR);
|
||||
totalRc += csync_excluded_traversal(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
|
||||
|
||||
gettimeofday(&after, 0);
|
||||
|
||||
const double total = (after.tv_sec - before.tv_sec)
|
||||
+ (after.tv_usec - before.tv_usec) / 1.0e6;
|
||||
const double perCallMs = total / 2 / N * 1000;
|
||||
printf("csync_excluded_traversal: %f ms per call\n", perCallMs);
|
||||
}
|
||||
}
|
||||
|
||||
int torture_run_tests(void)
|
||||
@@ -199,8 +332,10 @@ int torture_run_tests(void)
|
||||
unit_test_setup_teardown(check_csync_exclude_add, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_exclude_load, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_excluded, setup_init, teardown),
|
||||
unit_test_setup_teardown(check_csync_excluded_traversal, setup_init, teardown),
|
||||
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),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
|
||||
@@ -201,7 +201,6 @@ static csync_vio_file_stat_t* create_fstat(const char *name,
|
||||
}
|
||||
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_INODE;
|
||||
|
||||
fs->device = 0;
|
||||
|
||||
fs->size = 157459;
|
||||
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
|
||||
|
||||
@@ -146,13 +146,47 @@ static void check_to_multibyte(void **state)
|
||||
|
||||
static void check_long_win_path(void **state)
|
||||
{
|
||||
const char *path = "C://DATA/FILES/MUSIC/MY_MUSIC.mp3"; // check a short path
|
||||
const char *exp_path = "\\\\?\\C:\\\\DATA\\FILES\\MUSIC\\MY_MUSIC.mp3";
|
||||
const char *new_short = c_path_to_UNC(path);
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
assert_string_equal(new_short, exp_path);
|
||||
{
|
||||
const char *path = "C://DATA/FILES/MUSIC/MY_MUSIC.mp3"; // check a short path
|
||||
const char *exp_path = "\\\\?\\C:\\\\DATA\\FILES\\MUSIC\\MY_MUSIC.mp3";
|
||||
const char *new_short = c_path_to_UNC(path);
|
||||
assert_string_equal(new_short, exp_path);
|
||||
SAFE_FREE(new_short);
|
||||
}
|
||||
|
||||
{
|
||||
const char *path = "\\\\foo\\bar/MY_MUSIC.mp3";
|
||||
const char *exp_path = "\\\\foo\\bar\\MY_MUSIC.mp3";
|
||||
const char *new_short = c_path_to_UNC(path);
|
||||
assert_string_equal(new_short, exp_path);
|
||||
SAFE_FREE(new_short);
|
||||
}
|
||||
|
||||
{
|
||||
const char *path = "//foo\\bar/MY_MUSIC.mp3";
|
||||
const char *exp_path = "\\\\foo\\bar\\MY_MUSIC.mp3";
|
||||
const char *new_short = c_path_to_UNC(path);
|
||||
assert_string_equal(new_short, exp_path);
|
||||
SAFE_FREE(new_short);
|
||||
}
|
||||
|
||||
{
|
||||
const char *path = "\\foo\\bar";
|
||||
const char *exp_path = "\\\\?\\foo\\bar";
|
||||
const char *new_short = c_path_to_UNC(path);
|
||||
assert_string_equal(new_short, exp_path);
|
||||
SAFE_FREE(new_short);
|
||||
}
|
||||
|
||||
{
|
||||
const char *path = "/foo/bar";
|
||||
const char *exp_path = "\\\\?\\foo\\bar";
|
||||
const char *new_short = c_path_to_UNC(path);
|
||||
assert_string_equal(new_short, exp_path);
|
||||
SAFE_FREE(new_short);
|
||||
}
|
||||
|
||||
const char *longPath = "D://alonglonglonglong/blonglonglonglong/clonglonglonglong/dlonglonglonglong/"
|
||||
"elonglonglonglong/flonglonglonglong/glonglonglonglong/hlonglonglonglong/ilonglonglonglong/"
|
||||
@@ -170,7 +204,7 @@ static void check_long_win_path(void **state)
|
||||
|
||||
// printf( "YYYYYYYYYYYY %ld\n", strlen(new_long));
|
||||
assert_int_equal( strlen(new_long), 286);
|
||||
|
||||
SAFE_FREE(new_long);
|
||||
}
|
||||
|
||||
int torture_run_tests(void)
|
||||
|
||||
@@ -1,241 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2013 by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cmocka.h>
|
||||
|
||||
#include "config_test.h"
|
||||
|
||||
#if USE_NEON
|
||||
#include "httpbf.c"
|
||||
#endif
|
||||
|
||||
// A test case that does nothing and succeeds.
|
||||
static void null_test_success(void **state) {
|
||||
(void) state;
|
||||
}
|
||||
|
||||
#if USE_NEON
|
||||
|
||||
static char* test_file( const char* name ) {
|
||||
char path[260];
|
||||
|
||||
if( ! name ) return 0;
|
||||
|
||||
strcpy( path, TESTFILES_DIR);
|
||||
if(path[strlen(TESTFILES_DIR)-1] != '/')
|
||||
strcat( path, "/");
|
||||
strcat( path, name );
|
||||
|
||||
return strdup(path);
|
||||
}
|
||||
|
||||
static void test_get_transfer_url( void **state ) {
|
||||
const char *url = "http://example.org/owncloud";
|
||||
const char *turl = NULL;
|
||||
int fd;
|
||||
Hbf_State hbf_state;
|
||||
|
||||
hbf_transfer_t *list = NULL;
|
||||
|
||||
(void) state;
|
||||
list = hbf_init_transfer( url );
|
||||
assert_non_null( list );
|
||||
|
||||
/* open a file */
|
||||
fd = open( test_file("church.jpg"), O_RDONLY );
|
||||
assert_true(fd >= 0);
|
||||
|
||||
hbf_state = hbf_splitlist(list, fd);
|
||||
assert_true( hbf_state == HBF_SUCCESS);
|
||||
assert_true( list->block_cnt == 1);
|
||||
|
||||
turl = get_transfer_url( list, 0 );
|
||||
assert_non_null( turl );
|
||||
assert_string_equal( url, turl );
|
||||
|
||||
hbf_free_transfer( list );
|
||||
}
|
||||
|
||||
|
||||
static void test_get_transfer_url_bigfile( void **state ) {
|
||||
const char *url = "http://example.org/big_file";
|
||||
const char *turl = NULL;
|
||||
char res[256];
|
||||
int i, fd;
|
||||
Hbf_State hbf_state;
|
||||
hbf_transfer_t *list = NULL;
|
||||
|
||||
(void) state;
|
||||
|
||||
list = hbf_init_transfer( url );
|
||||
assert_non_null( list );
|
||||
|
||||
list->threshold = list->block_size = (1024*1024); /* block size 1 MB */
|
||||
|
||||
/* open a file */
|
||||
fd = open( test_file("church.jpg"), O_RDONLY );
|
||||
assert_true(fd >= 0);
|
||||
|
||||
hbf_state = hbf_splitlist(list, fd);
|
||||
assert_true( hbf_state == HBF_SUCCESS);
|
||||
assert_true( list->block_cnt == 2 );
|
||||
|
||||
for( i=0; i < list->block_cnt; i++ ) {
|
||||
turl = get_transfer_url( list, i );
|
||||
assert_non_null(turl);
|
||||
|
||||
sprintf(res, "%s-chunking-%u-%u-%u", url, list->transfer_id,
|
||||
list->block_cnt, i );
|
||||
/* printf( "XX: %s\n", res ); */
|
||||
assert_string_equal( turl, res );
|
||||
}
|
||||
hbf_free_transfer(list);
|
||||
}
|
||||
|
||||
static void test_hbf_init_transfer( void **state ) {
|
||||
hbf_transfer_t *list = NULL;
|
||||
const char *url = "http://example.org/owncloud";
|
||||
|
||||
(void) state;
|
||||
|
||||
list = hbf_init_transfer( url );
|
||||
assert_non_null( list );
|
||||
assert_string_equal( url, list->url );
|
||||
}
|
||||
|
||||
/* test with a file size that is not a multiply of the slize size. */
|
||||
static void test_hbf_splitlist_odd( void **state ){
|
||||
|
||||
hbf_transfer_t *list = NULL;
|
||||
const char *dest_url = "http://localhost/ocm/remote.php/webdav/big/church.jpg";
|
||||
int prev_id = 0;
|
||||
int i, fd;
|
||||
Hbf_State hbf_state;
|
||||
|
||||
(void) state;
|
||||
|
||||
/* open a file */
|
||||
fd = open(test_file("church.jpg"), O_RDONLY);
|
||||
assert_true(fd >= 0);
|
||||
|
||||
/* do a smoke test for uniqueness */
|
||||
for( i=0; i < 10000; i++) {
|
||||
list = hbf_init_transfer(dest_url);
|
||||
assert_non_null(list);
|
||||
usleep(1);
|
||||
hbf_state = hbf_splitlist(list, fd);
|
||||
|
||||
assert_int_not_equal(list->transfer_id, prev_id);
|
||||
prev_id = list->transfer_id;
|
||||
hbf_free_transfer(list);
|
||||
}
|
||||
|
||||
list = hbf_init_transfer(dest_url);
|
||||
assert_non_null(list);
|
||||
|
||||
hbf_state = hbf_splitlist(list, fd);
|
||||
assert_non_null(list);
|
||||
#ifndef NDEBUG
|
||||
assert_int_equal(list->calc_size, list->stat_size);
|
||||
#endif
|
||||
assert_int_not_equal(list->block_cnt, 0);
|
||||
assert_true( hbf_state == HBF_SUCCESS);
|
||||
|
||||
/* checks on the block list */
|
||||
if( 1 ) {
|
||||
int seen_zero_seq = 0;
|
||||
int prev_seq = -1;
|
||||
int64_t prev_block_end = -1;
|
||||
|
||||
for( i=0; i < list->block_cnt; i++) {
|
||||
hbf_block_t *blk = list->block_arr[i];
|
||||
assert_non_null(blk);
|
||||
if( blk->seq_number == 0 ) seen_zero_seq++;
|
||||
|
||||
assert_int_equal(prev_seq, blk->seq_number -1 );
|
||||
prev_seq = blk->seq_number;
|
||||
|
||||
assert_true((prev_block_end+1) == (blk->start));
|
||||
prev_block_end = blk->start + blk->size;
|
||||
}
|
||||
/* Make sure we exactly saw blk->seq_number == 0 exactly one times */
|
||||
assert_int_equal( seen_zero_seq, 1 );
|
||||
}
|
||||
hbf_free_transfer( list );
|
||||
}
|
||||
|
||||
/* test with a file size that is not a multiply of the slize size. */
|
||||
static void test_hbf_splitlist_zero( void **state ){
|
||||
|
||||
hbf_transfer_t *list = NULL;
|
||||
const char *dest_url = "http://localhost/ocm/remote.php/webdav/big/zerofile.txt";
|
||||
int fd;
|
||||
Hbf_State hbf_state;
|
||||
|
||||
(void) state;
|
||||
|
||||
/* open a file */
|
||||
fd = open(test_file("zerofile.txt"), O_RDONLY);
|
||||
assert_true(fd >= 0);
|
||||
|
||||
list = hbf_init_transfer(dest_url);
|
||||
assert_non_null(list);
|
||||
|
||||
hbf_state = hbf_splitlist(list, fd);
|
||||
assert_non_null(list);
|
||||
assert_int_equal(list->stat_size, 0);
|
||||
#ifndef NDEBUG
|
||||
assert_int_equal(list->calc_size, list->stat_size);
|
||||
#endif
|
||||
assert_int_equal(list->block_cnt, 1);
|
||||
|
||||
assert_true( hbf_state == HBF_SUCCESS);
|
||||
|
||||
hbf_free_transfer( list );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int main(void) {
|
||||
const UnitTest tests[] = {
|
||||
unit_test(null_test_success),
|
||||
#if USE_NEON
|
||||
unit_test(test_hbf_splitlist_odd),
|
||||
unit_test(test_hbf_splitlist_zero),
|
||||
unit_test(test_hbf_init_transfer),
|
||||
unit_test(test_get_transfer_url),
|
||||
unit_test(test_get_transfer_url_bigfile)
|
||||
#endif
|
||||
};
|
||||
return run_tests(tests);
|
||||
}
|
||||
|
||||
@@ -73,15 +73,6 @@ static void setup_dir(void **state) {
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void setup_file(void **state) {
|
||||
int rc;
|
||||
|
||||
setup_dir(state);
|
||||
|
||||
rc = system("echo \"This is a test\" > /tmp/csync_test/file.txt");
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void teardown(void **state) {
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
@@ -164,46 +155,6 @@ static void check_csync_vio_readdir(void **state)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Test for general functions (stat, chmod, chown, ...)
|
||||
*/
|
||||
|
||||
static void check_csync_vio_stat_dir(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
csync_vio_file_stat_t *fs;
|
||||
int rc;
|
||||
|
||||
fs = csync_vio_file_stat_new();
|
||||
assert_non_null(fs);
|
||||
|
||||
rc = csync_vio_stat(csync, CSYNC_TEST_DIR, fs);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
assert_string_equal(fs->name, "csync_test");
|
||||
assert_int_equal(fs->type, CSYNC_VIO_FILE_TYPE_DIRECTORY);
|
||||
|
||||
csync_vio_file_stat_destroy(fs);
|
||||
}
|
||||
|
||||
static void check_csync_vio_stat_file(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
csync_vio_file_stat_t *fs;
|
||||
int rc;
|
||||
|
||||
fs = csync_vio_file_stat_new();
|
||||
assert_non_null(fs);
|
||||
|
||||
rc = csync_vio_stat(csync, CSYNC_TEST_FILE, fs);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
assert_string_equal(fs->name, "file.txt");
|
||||
assert_int_equal(fs->type, CSYNC_VIO_FILE_TYPE_REGULAR);
|
||||
|
||||
csync_vio_file_stat_destroy(fs);
|
||||
}
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
@@ -211,9 +162,6 @@ int torture_run_tests(void)
|
||||
unit_test_setup_teardown(check_csync_vio_opendir_perm, setup, teardown),
|
||||
unit_test(check_csync_vio_closedir_null),
|
||||
unit_test_setup_teardown(check_csync_vio_readdir, setup_dir, teardown),
|
||||
|
||||
unit_test_setup_teardown(check_csync_vio_stat_dir, setup_dir, teardown),
|
||||
unit_test_setup_teardown(check_csync_vio_stat_file, setup_file, teardown),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
|
||||
@@ -47,7 +47,7 @@ Synchronization by Time versus ETag
|
||||
.. index:: time stamps, file times, etag, unique id
|
||||
|
||||
Until the release of ownCloud 4.5 and ownCloud Client 1.1, the ownCloud
|
||||
synchronization process employed a single file property -- the file modificatin
|
||||
synchronization process employed a single file property -- the file modification
|
||||
time -- to decide which file was newer and needed to be synchronized to the
|
||||
other repository.
|
||||
|
||||
@@ -76,7 +76,7 @@ a synchronization process.
|
||||
not support using the file ID functionality.
|
||||
|
||||
Before the 1.3.0 release of the Desktop Client, the synchronization process
|
||||
might create faux conflict files if time deviates. Original and changed files
|
||||
might create false conflict files if time deviates. Original and changed files
|
||||
conflict only in their timestamp, but not in their content. This behaviour was
|
||||
changed to employ a binary check if files differ.
|
||||
|
||||
@@ -104,11 +104,11 @@ depending on server/client combination:
|
||||
+--------------------+-------------------+----------------------------+
|
||||
|
||||
We strongly recommend using ownCloud Server release 4.5 or later when using
|
||||
ownCloud Client 1.1 or later. Using incompatible time stamp-based
|
||||
ownCloud Client 1.1 or later. Using an incompatible time stamp-based
|
||||
synchronization mechanism can lead to data loss in rare cases, especially when
|
||||
multiple clients are involved and one utilizes a non-synchronized NTP time.
|
||||
|
||||
.. _`NTP time synchronisation`: http://en.wikipedia.org/wiki/Network_Time_Protocol
|
||||
.. _`NTP time synchronization`: http://en.wikipedia.org/wiki/Network_Time_Protocol
|
||||
.. _Etag: http://en.wikipedia.org/wiki/HTTP_ETag
|
||||
|
||||
Comparison and Conflict Cases
|
||||
@@ -120,7 +120,7 @@ traverses the file tree and compares the modification time of each file with an
|
||||
expected value stored in its database. If the value is not the same, the client
|
||||
determines that the file has been modified in the local repository.
|
||||
|
||||
.. note:: On the local side, the modification time a good attribute to use for
|
||||
.. note:: On the local side, the modification time is a good attribute to use for
|
||||
detecting changes, because
|
||||
the value does not depend on time shifts and such.
|
||||
|
||||
@@ -131,8 +131,8 @@ changed and no synchronization occurs.
|
||||
|
||||
In the event a file has changed on both the local and the remote repository
|
||||
since the last sync run, it can not easily be decided which version of the file
|
||||
is the one that should be used. However, changes to any side be lost. Instead,
|
||||
a *conflict case* is created. The client resolves this conflic by creating a
|
||||
is the one that should be used. However, changes to any side will not be lost. Instead,
|
||||
a *conflict case* is created. The client resolves this conflict by creating a
|
||||
conflict file of the older of the two files and saving the newer file under the
|
||||
original file name. Conflict files are always created on the client and never
|
||||
on the server. The conflict file uses the same name as the original file, but
|
||||
@@ -156,18 +156,18 @@ By default, the ownCloud Client ignores the following files:
|
||||
* Files starting with ``.csync_journal.db``, as these files are reserved for journalling.
|
||||
|
||||
If a pattern selected using a checkbox in the `ignoredFilesEditor-label` (or if
|
||||
a line in the exclude file starts with the character `]` directly followed by
|
||||
a line in the exclude file starts with the character ``]`` directly followed by
|
||||
the file pattern), files matching the pattern are considered *fleeting meta
|
||||
data*. These files are ingored and *removed* by the client if found in the
|
||||
data*. These files are ignored and *removed* by the client if found in the
|
||||
synchronized folder. This is suitable for meta files created by some
|
||||
applications that have no sustainable meaning.
|
||||
|
||||
If a pattern ends with the backslash (`/`) character, only directories are
|
||||
If a pattern ends with the forwardslash (``/``) character, only directories are
|
||||
matched. The pattern is only applied for directory components of filenames
|
||||
selected using the checkbox.
|
||||
|
||||
To match filenames against the exclude patterns, the unix standard C library
|
||||
function fnmatch is used. This procesx checks the filename against the
|
||||
function fnmatch is used. This process checks the filename against the
|
||||
specified pattern using standard shell wildcard pattern matching. For more
|
||||
information, please refer to `The opengroup website
|
||||
<http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_13_01>`_.
|
||||
|
||||
@@ -11,8 +11,8 @@ the Updater will check for updates and notify you when a new version is
|
||||
available.
|
||||
|
||||
.. note:: Because of various technical issues, desktop sync clients older than
|
||||
1.7 will not be allowed to connect and sync with the ownCloud 8.1 server. It is
|
||||
highly recommended to keep your client updated.
|
||||
1.7 will not be allowed to connect and sync with the ownCloud 8.1+ server. It
|
||||
is highly recommended to keep your client updated.
|
||||
|
||||
Basic Workflow
|
||||
--------------
|
||||
@@ -73,8 +73,8 @@ To prevent automatic updates, but allow manual overrides:
|
||||
|
||||
1. Edit these Registry keys:
|
||||
|
||||
a. (32-bit) ``HKEY_LOCAL_MACHINE\Software\ownCloud\ownCloud``
|
||||
b. (64-bit) ``HKEY_LOCAL_MACHINE\Software\Wow6432Node\ownCloud\ownCloud``
|
||||
a. (32-bit-Windows) ``HKEY_LOCAL_MACHINE\Software\ownCloud\ownCloud``
|
||||
b. (64-bit-Windows) ``HKEY_LOCAL_MACHINE\Software\Wow6432Node\ownCloud\ownCloud``
|
||||
|
||||
2. Add the key ``skipUpdateCheck`` (of type DWORD).
|
||||
|
||||
@@ -87,9 +87,9 @@ To prevent automatic updates and disallow manual overrides:
|
||||
.. note::This is the preferred method of controlling the updater behavior using
|
||||
Group Policies.
|
||||
|
||||
1. Migrate to the following directory::
|
||||
1. Edit this Registry key:
|
||||
|
||||
HKEY_LOCAL_MACHINE\Software\Policies\ownCloud\ownCloud
|
||||
``HKEY_LOCAL_MACHINE\Software\Policies\ownCloud\ownCloud``
|
||||
|
||||
2. Add the key ``skipUpdateCheck`` (of type DWORD).
|
||||
|
||||
@@ -106,7 +106,7 @@ using the system-wide ``.plist`` file. To access this file:
|
||||
|
||||
/Library/Preferences/
|
||||
|
||||
2. Locate and open the following file::
|
||||
2. Locate and open the following file::
|
||||
|
||||
com.owncloud.desktopclient.plist
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
.. _building-label:
|
||||
|
||||
===============================
|
||||
Appendix A: Building the Client
|
||||
===============================
|
||||
|
||||
@@ -7,7 +8,7 @@ This section explains how to build the ownCloud Client from source for all
|
||||
major platforms. You should read this section if you want to develop for the
|
||||
desktop client.
|
||||
|
||||
.. note:: Building instruction are subject to change as development proceeds.
|
||||
.. 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.
|
||||
@@ -23,7 +24,7 @@ Linux
|
||||
* openSUSE: ``zypper ref; zypper si -d owncloud-client``
|
||||
* Fedora/CentOS: ``yum install yum-utils; yum-builddep owncloud-client``
|
||||
|
||||
3. Follow the `generic build instructions`_.
|
||||
3. Follow the :ref:`generic-build-instructions`.
|
||||
|
||||
4. (Optional) Call ``make install`` to install the client to the ``/usr/local/bin`` directory.
|
||||
|
||||
@@ -43,7 +44,7 @@ The tested and preferred way to develop in this environment is through the use
|
||||
of HomeBrew_. The ownCloud team has its own repository containing non-standard
|
||||
recipes.
|
||||
|
||||
To set up your build enviroment for development using HomeBrew_:
|
||||
To set up your build environment for development using HomeBrew_:
|
||||
|
||||
1. Add the ownCloud repository using the following command::
|
||||
|
||||
@@ -60,7 +61,7 @@ To set up your build enviroment for development using HomeBrew_:
|
||||
Where ``x.z`` is the current version of Qt 5 that brew has installed
|
||||
on your machine.
|
||||
|
||||
5. For compilation of the client, follow the `generic build instructions`_.
|
||||
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>
|
||||
<install_dir>``. If you have a developer signing certificate, you can specify
|
||||
@@ -118,14 +119,14 @@ follow `Windows Installer Build (Cross-Compile)`_ instead.
|
||||
cmake -G "MinGW Makefiles" ../client
|
||||
mingw32-make
|
||||
|
||||
.. note:: You can try using ninja to build parallelly using
|
||||
.. note:: You can try using ninja to build in parallel using
|
||||
``cmake -G Ninja ../client`` and ``ninja`` instead.
|
||||
.. note:: Refer to the `generic build instructions`_ section for additional options.
|
||||
.. 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.
|
||||
@@ -134,58 +135,38 @@ have it installed already.
|
||||
|
||||
To cross-compile:
|
||||
|
||||
1. Add the following repositories using YaST or ``zypper ar`` (adjust when using another openSUSE version)::
|
||||
1. Add the following repository using YaST or ``zypper ar`` (adjust when using another openSUSE version)::
|
||||
|
||||
zypper ar http://download.opensuse.org/repositories/windows:/mingw/openSUSE_13.2/windows:mingw.repo
|
||||
zypper ar http://download.opensuse.org/repositories/windows:/mingw:/win32/openSUSE_13.2/windows:mingw:win32.repo
|
||||
zypper ar https://build.opensuse.org/project/show/isv:ownCloud:toolchains:mingw:win32:stable
|
||||
|
||||
2. Install the cross-compiler packages and the cross-compiled dependencies::
|
||||
|
||||
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-cross-libqt5-qmake mingw32-cross-libqt5-qttools mingw32-libqt5* \
|
||||
mingw32-cross-nsis
|
||||
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*
|
||||
|
||||
3. For the installer, install the NSIS installer package::
|
||||
|
||||
zypper install mingw32-cross-nsis
|
||||
zypper install mingw32-cross-nsis mingw32-cross-nsis-plugin-uac mingw32-cross-nsis-plugin-nsprocess
|
||||
|
||||
4. Install the following plugin::
|
||||
|
||||
mingw32-cross-nsis-plugin-processes mingw32-cross-nsis-plugin-uac
|
||||
|
||||
.. note:: This plugin is typically required. However, due to a current bug
|
||||
in ``mingw``, the plugins do not currently build properly from source.
|
||||
|
||||
5. Manually download and install the following files using ``rpm -ivh <package>``:
|
||||
|
||||
.. note:: These files also work for more recent openSUSE versions!
|
||||
|
||||
::
|
||||
# RPM depends on curl for installs from HTTP
|
||||
zypper install curl
|
||||
|
||||
rpm -ivh http://download.tomahawk-player.org/packman/mingw:32/openSUSE_12.1/x86_64/mingw32-cross-nsis-plugin-processes-0-1.1.x86_64.rpm
|
||||
rpm -ivh http://download.tomahawk-player.org/packman/mingw:32/openSUSE_12.1/x86_64/mingw32-cross-nsis-plugin-uac-0-3.1.x86_64.rpm
|
||||
|
||||
6. Follow the `generic build instructions`_
|
||||
4. Follow the :ref:`generic-build-instructions`
|
||||
|
||||
.. 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``.
|
||||
|
||||
7. Build by running ``make``.
|
||||
5. Build by running ``make``.
|
||||
|
||||
.. note:: Using ``make package`` produces an NSIS-based installer, provided
|
||||
the NSIS mingw32 packages are installed.
|
||||
|
||||
8. If you want to sign the installer, acquire a `Microsoft Authenticode`_ Certificate and install ``osslsigncode`` to sign the installer::
|
||||
6. If you want to sign the installer, acquire a `Microsoft Authenticode`_ Certificate and install ``osslsigncode`` to sign the installer::
|
||||
|
||||
zypper install osslsigncode
|
||||
|
||||
9. Sign the package::
|
||||
7. Sign the package::
|
||||
|
||||
osslsigncode -pkcs12 $HOME/.codesign/packages.pfx -h sha1 \
|
||||
-pass yourpass \
|
||||
@@ -195,11 +176,12 @@ To cross-compile:
|
||||
-in ${unsigned_file} \
|
||||
-out ${installer_file}
|
||||
|
||||
for ``-in``, use URL to the time stamping server provided by your CA along with the Authenticode certificate. Alternatively,
|
||||
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.
|
||||
|
||||
|
||||
.. _`generic build instructions`:
|
||||
.. _generic-build-instructions:
|
||||
|
||||
Generic Build Instructions
|
||||
--------------------------
|
||||
|
||||
|
||||
@@ -48,9 +48,9 @@ copyright = u'2013, The ownCloud developers'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '@VERSION_MAJOR@.@VERSION_MINOR@'
|
||||
version = '@MIRALL_VERSION_MAJOR@.@MIRALL_VERSION_MINOR@'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '@VERSION@'
|
||||
release = '@MIRALL_VERSION@'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@@ -189,7 +189,7 @@ latex_documents = [
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
latex_logo = '@LATEX_LOGO@'
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
The ownCloud Client reads a configuration file. You can locate this configuration files as follows:
|
||||
The ownCloud Client reads a configuration file. You can locate this configuration file as follows:
|
||||
|
||||
On Linux distributions:
|
||||
``$HOME/.local/share/data/ownCloud/owncloud.cfg``
|
||||
|
||||
@@ -9,9 +9,9 @@ Some files are continuously uploaded to the server, even when they are not modif
|
||||
|
||||
It is possible that another program is changing the modification date of the file.
|
||||
|
||||
If the file is uses the ``.eml`` extention, Windows automatically and
|
||||
If the file is uses the ``.eml`` extension, Windows automatically and
|
||||
continually changes all files, unless you remove
|
||||
``\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\PropertySystem\PropertyHandlers`
|
||||
``\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\PropertySystem\PropertyHandlers``
|
||||
from the windows registry.
|
||||
|
||||
See http://petersteier.wordpress.com/2011/10/22/windows-indexer-changes-modification-dates-of-eml-files/ for more information.
|
||||
|
||||
|
Depois Largura: | Altura: | Tamanho: 34 KiB |
|
Depois Largura: | Altura: | Tamanho: 41 KiB |
|
Depois Largura: | Altura: | Tamanho: 67 KiB |
|
Depois Largura: | Altura: | Tamanho: 63 KiB |
|
Depois Largura: | Altura: | Tamanho: 5.5 KiB |
|
Antes Largura: | Altura: | Tamanho: 44 KiB |
|
Antes Largura: | Altura: | Tamanho: 39 KiB |