mirror of
https://github.com/chylex/Nextcloud-Desktop.git
synced 2026-04-13 08:30:35 +02:00
Compare commits
278 Commits
v1.7.0beta
...
v1.7.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17a4299f74 | ||
|
|
776f4dc316 | ||
|
|
5db55d9e29 | ||
|
|
5c9564ac08 | ||
|
|
5c5a89c1a4 | ||
|
|
176413d312 | ||
|
|
b70ecc3dd3 | ||
|
|
174e1acbc7 | ||
|
|
1f09a24a72 | ||
|
|
eed91ddf46 | ||
|
|
6eec896282 | ||
|
|
a78bb252de | ||
|
|
0ba07f19f7 | ||
|
|
a49a6bfd88 | ||
|
|
b87931c0a9 | ||
|
|
9b640d586b | ||
|
|
7440ffc0e6 | ||
|
|
63e901cd0b | ||
|
|
af4e9c30f5 | ||
|
|
5805ffebec | ||
|
|
39bfacf1d5 | ||
|
|
8d30fc2718 | ||
|
|
19daff36b0 | ||
|
|
c34c8ff358 | ||
|
|
af68cb6029 | ||
|
|
6b6b212643 | ||
|
|
dd2a71fa8f | ||
|
|
cd72d133a3 | ||
|
|
d3662d0e34 | ||
|
|
cf6219bb6f | ||
|
|
45eeb5065f | ||
|
|
f563eb1f63 | ||
|
|
1029f9521c | ||
|
|
825eca078d | ||
|
|
1eccfb798f | ||
|
|
7810da51a8 | ||
|
|
a470138450 | ||
|
|
7bad731ad2 | ||
|
|
eeb54290b3 | ||
|
|
782463589e | ||
|
|
ff570c4a6b | ||
|
|
105ff694f2 | ||
|
|
26ff6be63c | ||
|
|
47e3da9ebf | ||
|
|
b7ce5ba82a | ||
|
|
5723abe6eb | ||
|
|
95a9b0427c | ||
|
|
0692fea9d8 | ||
|
|
b0882a5cd2 | ||
|
|
4c1a0005e6 | ||
|
|
05ceed926c | ||
|
|
b691521662 | ||
|
|
ce300d88ee | ||
|
|
05c0249672 | ||
|
|
2498c13078 | ||
|
|
ab5dae741a | ||
|
|
cddad94e45 | ||
|
|
2f0a40c1c8 | ||
|
|
3b1ff5bf41 | ||
|
|
1bd1c61c3c | ||
|
|
9cd81d87b2 | ||
|
|
59efea1b0e | ||
|
|
d0b40bab47 | ||
|
|
d76192cce1 | ||
|
|
0e828d802e | ||
|
|
9505d7cc51 | ||
|
|
1c4072e231 | ||
|
|
86e13ea06f | ||
|
|
c12d3870cd | ||
|
|
fce76a13cb | ||
|
|
82b14370fc | ||
|
|
a9d8e9dcd8 | ||
|
|
542e989046 | ||
|
|
f5c199740d | ||
|
|
f37b81c8b7 | ||
|
|
c0ea69ee24 | ||
|
|
5640cbf653 | ||
|
|
6d81e5c87a | ||
|
|
3c7ff97ed4 | ||
|
|
2120ff8037 | ||
|
|
92c35c6aa6 | ||
|
|
149b16aefd | ||
|
|
114c38c1ff | ||
|
|
e5269a4151 | ||
|
|
81584c6d51 | ||
|
|
0d9ae241c9 | ||
|
|
e726e7aad8 | ||
|
|
c7c05ea869 | ||
|
|
83880aed52 | ||
|
|
de56b753d1 | ||
|
|
dab01e3f3f | ||
|
|
e46ab72718 | ||
|
|
9f6d7eb587 | ||
|
|
bbd9098e44 | ||
|
|
47ad4e3fe8 | ||
|
|
9330d2e1e8 | ||
|
|
020e19f770 | ||
|
|
3be5600caf | ||
|
|
22dd275b15 | ||
|
|
6342e76e19 | ||
|
|
55dd149a03 | ||
|
|
39a0f28753 | ||
|
|
dd45b448d9 | ||
|
|
7740150576 | ||
|
|
4f367faf4d | ||
|
|
3840186dd8 | ||
|
|
d77fcea365 | ||
|
|
ed51a45187 | ||
|
|
ba86988101 | ||
|
|
6073e3f345 | ||
|
|
d31ccacf57 | ||
|
|
de48e65091 | ||
|
|
3243365210 | ||
|
|
8dc3f2146a | ||
|
|
a993496ab4 | ||
|
|
61e72ef50b | ||
|
|
d7ac878efd | ||
|
|
e5a0db8782 | ||
|
|
24d4840c93 | ||
|
|
fa70798fb5 | ||
|
|
1af480ea3b | ||
|
|
a76fc0ee5a | ||
|
|
80e86d6c1b | ||
|
|
dc13e39bb1 | ||
|
|
98c5871d38 | ||
|
|
5a109d9293 | ||
|
|
56316bc980 | ||
|
|
21c8e65d13 | ||
|
|
86d8079739 | ||
|
|
d2be45bce1 | ||
|
|
5d048c18bc | ||
|
|
0fb779d363 | ||
|
|
d0ed82a686 | ||
|
|
d33b68ccc9 | ||
|
|
26f068bcab | ||
|
|
f0dc3725e8 | ||
|
|
2de22b408b | ||
|
|
04b62b139d | ||
|
|
2f20f3c65d | ||
|
|
53b3e5af1b | ||
|
|
7dbb98c2e5 | ||
|
|
8b35cda4c6 | ||
|
|
cb36a37779 | ||
|
|
704c5f2de7 | ||
|
|
3fcb0d2d6b | ||
|
|
2dfe0ed42e | ||
|
|
ac48fbae9c | ||
|
|
6048a7143a | ||
|
|
7c24db07c2 | ||
|
|
271cdac474 | ||
|
|
79e2c132cc | ||
|
|
b5736fb5a7 | ||
|
|
7822a6b000 | ||
|
|
306b63599c | ||
|
|
3021fb546e | ||
|
|
a5bd437d48 | ||
|
|
08156186fa | ||
|
|
f1006ca8b0 | ||
|
|
93c85711d1 | ||
|
|
e5ef5f2410 | ||
|
|
52a5729298 | ||
|
|
b9849580f8 | ||
|
|
4525161e7c | ||
|
|
dee6d18d69 | ||
|
|
d44179142f | ||
|
|
c66c01245b | ||
|
|
681c43631b | ||
|
|
2f740fe471 | ||
|
|
b1c10c8454 | ||
|
|
1d5b3aadea | ||
|
|
2d420cd72c | ||
|
|
707d6880a8 | ||
|
|
dbad1a8d45 | ||
|
|
36eaff92e5 | ||
|
|
e51c299937 | ||
|
|
8c7953a47c | ||
|
|
4527784905 | ||
|
|
ee8a93ae9a | ||
|
|
6096362052 | ||
|
|
89c51e7649 | ||
|
|
6c92076ec3 | ||
|
|
2bba4134fb | ||
|
|
10175c8d57 | ||
|
|
7804bf0a9a | ||
|
|
336c95ce5b | ||
|
|
babe891242 | ||
|
|
bb37e93f52 | ||
|
|
aa0f2c64ff | ||
|
|
e66ca267f4 | ||
|
|
eeb5ca42e0 | ||
|
|
74ec90c725 | ||
|
|
03ee742981 | ||
|
|
b4c86bcf40 | ||
|
|
0094c1ecf5 | ||
|
|
6b5fcf53eb | ||
|
|
4b001a77b3 | ||
|
|
357c08c5b3 | ||
|
|
e7d9ec50dc | ||
|
|
09b0ba31ef | ||
|
|
8231bc931b | ||
|
|
26ffa078ef | ||
|
|
eb60aca34f | ||
|
|
4d3020421a | ||
|
|
f1ce0a1cf3 | ||
|
|
dd28a645a1 | ||
|
|
561e3c780d | ||
|
|
8371e34d87 | ||
|
|
46fd79604d | ||
|
|
d08c2de619 | ||
|
|
a452a05e52 | ||
|
|
0a96aa3aaf | ||
|
|
07bcaaebf9 | ||
|
|
0cde7c8ac1 | ||
|
|
b285e98988 | ||
|
|
ab40ba2f75 | ||
|
|
bbcb8ba3e7 | ||
|
|
ef48de34f7 | ||
|
|
7e898cf60c | ||
|
|
2f5cea0e73 | ||
|
|
282abdd804 | ||
|
|
9b178c5bb2 | ||
|
|
d491663143 | ||
|
|
8eaeba6486 | ||
|
|
631e67949e | ||
|
|
77d2cba155 | ||
|
|
2149092c7a | ||
|
|
100d1361b6 | ||
|
|
76f5266fa1 | ||
|
|
3ebe3b1196 | ||
|
|
c4f96c2fba | ||
|
|
d880f2ffbc | ||
|
|
f8f5a7ceaa | ||
|
|
b01839e9a4 | ||
|
|
75dbf12ae6 | ||
|
|
9bb89dced5 | ||
|
|
661fe5df66 | ||
|
|
8a93437e55 | ||
|
|
b20752f13e | ||
|
|
61967f6e1b | ||
|
|
f0fef4f232 | ||
|
|
7eb10a08b8 | ||
|
|
4c83653d5d | ||
|
|
3149cd03be | ||
|
|
5314765410 | ||
|
|
621a37be15 | ||
|
|
6de104a03a | ||
|
|
97560509ea | ||
|
|
32aaecd832 | ||
|
|
dfba8fbe5e | ||
|
|
32fea6523f | ||
|
|
d1c1a18226 | ||
|
|
04558beabe | ||
|
|
425d0d77c5 | ||
|
|
edf7cd29dd | ||
|
|
27318dded6 | ||
|
|
11fe0c5b4b | ||
|
|
886f9d82f2 | ||
|
|
4f2fb4af5d | ||
|
|
6c8eab734e | ||
|
|
9d5d6aff38 | ||
|
|
705cd571a5 | ||
|
|
48d3c75745 | ||
|
|
6fbd28d228 | ||
|
|
285cb78962 | ||
|
|
708655d9b2 | ||
|
|
9bd7ffe952 | ||
|
|
51109ea485 | ||
|
|
1579c23ff1 | ||
|
|
961df010cb | ||
|
|
103986b320 | ||
|
|
764c0cdb03 | ||
|
|
12b09fab67 | ||
|
|
ed5a8ab090 | ||
|
|
41fa562dce | ||
|
|
6c2ce06fea | ||
|
|
ef019cdbfa | ||
|
|
1b02a1a6f3 | ||
|
|
b6d97cfffb |
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -3,7 +3,7 @@
|
|||||||
url = https://github.com/owncloud/documentation
|
url = https://github.com/owncloud/documentation
|
||||||
[submodule "src/3rdparty/qtmacgoodies"]
|
[submodule "src/3rdparty/qtmacgoodies"]
|
||||||
path = src/3rdparty/qtmacgoodies
|
path = src/3rdparty/qtmacgoodies
|
||||||
url = git://github.com/guruz/qtmacgoodies.git
|
url = git://github.com/shadone/qtmacgoodies.git
|
||||||
[submodule "binary"]
|
[submodule "binary"]
|
||||||
path = binary
|
path = binary
|
||||||
url = git://github.com/owncloud/owncloud-client-binary.git
|
url = git://github.com/owncloud/owncloud-client-binary.git
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ if (${GIT_SHA1} STREQUAL "GITDIR-NOTFOUND")
|
|||||||
set (GIT_SHA1 "${sha1_candidate}")
|
set (GIT_SHA1 "${sha1_candidate}")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
message(STATUS "GIT_SHA1 ${GIT_SHA1}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
|
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
|
||||||
@@ -123,6 +124,12 @@ find_package(Sphinx)
|
|||||||
find_package(PdfLatex)
|
find_package(PdfLatex)
|
||||||
|
|
||||||
|
|
||||||
|
find_package(SQLite3 3.8.0 REQUIRED)
|
||||||
|
# On some OS, we want to use our own, not the system sqlite
|
||||||
|
if (USE_OUR_OWN_SQLITE3)
|
||||||
|
include_directories(BEFORE ${SQLITE3_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
configure_file(config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
configure_file(config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
|
|
||||||
|
|||||||
54
ChangeLog
54
ChangeLog
@@ -1,5 +1,59 @@
|
|||||||
ChangeLog
|
ChangeLog
|
||||||
=========
|
=========
|
||||||
|
version 1.7.0 (release 2014-10-xx)
|
||||||
|
|
||||||
|
* oC7 Sharing: Handle new sharing options of ownCloud 7 correctly.
|
||||||
|
* Added Selective sync: Ability to unselect server folders which are
|
||||||
|
excluded from syncing, plus GUI and setup GUI
|
||||||
|
* Added overlay icons for Windows Explorer, Mac OS Finder and GNOME Nautilus.
|
||||||
|
Information is provided by the client via a local socket / named pipe API
|
||||||
|
which provides information about the sync status of files.
|
||||||
|
* Improved local change detection: consider file size, detect files
|
||||||
|
with ongoing changes and do not upload immediately
|
||||||
|
* Improved HTTP request timeout handler: all successful requests reset
|
||||||
|
the timeout counter
|
||||||
|
* Improvements for syncing command line tool: netrc support, improved
|
||||||
|
SSL support, non interactive mode
|
||||||
|
* Permission system: ownCloud 7 delivers file and folder permissions,
|
||||||
|
added ability to deal with it for shared folders and more.
|
||||||
|
* Ignore handling: Do not recurse into ignored or excluded directories
|
||||||
|
* Major sync journal database improvements for more stability and performance
|
||||||
|
* New library interface to sqlite3
|
||||||
|
* Improve "resync handling" if errors occur
|
||||||
|
* Blacklist improvements
|
||||||
|
* Improved logging: more useful meta info, removed noise
|
||||||
|
* Updated to latest Qt5 versions on Windows and OS X
|
||||||
|
* Fixed data loss when renaming a download temporary fails and there was
|
||||||
|
a conflict at the same time.
|
||||||
|
* Fixed missing warnings about reusing a sync folder when the back button
|
||||||
|
was used in the advanced folder setup wizard.
|
||||||
|
* The 'Retry Sync' button now also restarts all downloads.
|
||||||
|
* Clean up temporary downloads and some extra database files when wiping a
|
||||||
|
folder.
|
||||||
|
* OS X: Sparkle update to provide pkg format properly
|
||||||
|
* OS X: Change distribution format from dmg to pkg with new installer.
|
||||||
|
* Windows: Fix handling of filenames with trailing dot or space
|
||||||
|
* Windows: Don't use the wrong way to get file mtimes in the legacy propagator.
|
||||||
|
|
||||||
|
version 1.6.4 (release 2014-10-22)
|
||||||
|
* Fix startup logic, fixes bug #1989
|
||||||
|
* Fix raise dialog on X11
|
||||||
|
* Win32: fix overflow when computing the size of file > 4GiB
|
||||||
|
* Use a fixed function to get files modification time, the
|
||||||
|
original one was broken for certain timezone issues, see
|
||||||
|
core bug #9781 for details
|
||||||
|
* Added some missing copyright headers
|
||||||
|
* Avoid data corruption due to wrong error handling, bug #2280
|
||||||
|
* Do improved request timeout handling to reduce the number of
|
||||||
|
timed out jobs, bug #2155
|
||||||
|
version 1.6.3 (release 2014-09-03)
|
||||||
|
* Fixed updater on OS X
|
||||||
|
* Fixed memory leak in SSL button that could lead to quick memory draining
|
||||||
|
* Fixed upload problem with files >4 GB
|
||||||
|
* MacOSX, Linux: Bring Settings window to front properly
|
||||||
|
* Branded clients: If no configuration is detected, try to import the data
|
||||||
|
from a previously configured community edition.
|
||||||
|
|
||||||
version 1.6.2 (release 2014-07-28 )
|
version 1.6.2 (release 2014-07-28 )
|
||||||
* Limit the HTTP buffer size when downloading to limit memory consumption.
|
* Limit the HTTP buffer size when downloading to limit memory consumption.
|
||||||
* Another small mem leak fixed in HTTP Credentials.
|
* Another small mem leak fixed in HTTP Credentials.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ set( MIRALL_VERSION_PATCH 0 )
|
|||||||
set( MIRALL_SOVERSION 0 )
|
set( MIRALL_SOVERSION 0 )
|
||||||
|
|
||||||
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||||
set( MIRALL_VERSION_SUFFIX "beta2") #e.g. beta1, beta2, rc1
|
set( MIRALL_VERSION_SUFFIX "") #e.g. beta1, beta2, rc1
|
||||||
endif( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
endif( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||||
|
|
||||||
if( NOT DEFINED MIRALL_VERSION_BUILD )
|
if( NOT DEFINED MIRALL_VERSION_BUILD )
|
||||||
|
|||||||
BIN
admin/osx/installer-background.png
Normal file
BIN
admin/osx/installer-background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
51
admin/osx/installer-background.svg
Normal file
51
admin/osx/installer-background.svg
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
enable-background="new 0 0 595.275 311.111"
|
||||||
|
xml:space="preserve"
|
||||||
|
height="200"
|
||||||
|
width="320"
|
||||||
|
version="1.1"
|
||||||
|
y="0px"
|
||||||
|
x="0px"
|
||||||
|
viewBox="0 0 35 0"
|
||||||
|
id="svg2"
|
||||||
|
inkscape:version="0.48.4 r9939"
|
||||||
|
sodipodi:docname="installer-background.svg"><metadata
|
||||||
|
id="metadata12"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs10" /><sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1002"
|
||||||
|
id="namedview8"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="0.734375"
|
||||||
|
inkscape:cx="-49.141255"
|
||||||
|
inkscape:cy="236.17459"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="34"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg2"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0" /><path
|
||||||
|
style="text-indent:0;text-transform:none;block-progression:tb;color:#000000;fill:#ffffff;fill-opacity:1;enable-background:accumulate"
|
||||||
|
d="m 75.63384,28.421489 c -29.36582,0 -53.09172,23.724901 -53.09172,53.091701 0,12.1047 4.03087,23.2455 10.82647,32.1667 14.74225,-17.0631 36.50138,-27.8988 60.79508,-27.8988 11.88546,0 23.15644,2.6467 33.31219,7.2871 0.82221,-3.7185 1.24924,-7.5856 1.24924,-11.555 0,-29.3658 -23.72491,-53.091701 -53.09172,-53.091701 z M 6.30358,52.98809 c -15.29297,0 -27.58645,12.3977 -27.58645,27.6906 0,4.9515 1.27738,9.6301 3.53933,13.6373 9.22826,-5.206 19.89756,-8.2239 31.23002,-8.2239 1.09366,0 2.14708,0.039 3.22713,0.1052 -0.12231,-1.5502 -0.20806,-3.103 -0.20806,-4.6844 0,-8.5178 1.85002,-16.6223 5.10106,-23.9429 -4.37708,-2.9351 -9.62115,-4.5803 -15.30284,-4.5803 z m 130.95716,19.0502 c -1.12983,0 -2.21885,0.1381 -3.33122,0.2078 0.48121,3.0338 0.83274,6.097 0.83274,9.2651 0,4.9298 -0.62692,9.6869 -1.7697,14.2616 13.39754,7.4144 24.52385,18.5084 31.8547,31.9586 7.60342,-3.9586 16.08566,-6.4754 25.08804,-7.0787 -2.32015,-27.2093 -24.86184,-48.6137 -52.67416,-48.6137 z m -43.09675,19.7789 c -41.09117,0 -74.32775,33.2333 -74.32775,74.3278 0,41.0911 33.23329,74.3277 74.32775,74.3277 41.09447,0 74.32775,-33.2366 74.32775,-74.3277 0,-41.0945 -33.23657,-74.3278 -74.32775,-74.3278 z m -80.67652,0.3117 c -31.87937,0 -57.67166,25.792 -57.67166,57.6717 0,18.7668 8.94156,35.3802 22.79774,45.9078 5.84147,-11.2667 17.57406,-18.9461 31.1258,-18.9461 1.63789,0 3.21,0.1986 4.78871,0.4169 -0.49554,-3.6054 -0.72871,-7.2937 -0.72871,-11.0346 0,-17.8847 5.82174,-34.4234 15.71907,-47.7819 -5.92466,-7.4133 -10.1643,-16.321 -11.97162,-26.025 -1.33935,-0.092 -2.69673,-0.2078 -4.05979,-0.2078 z m 180.71831,34.3544 c -9.68,0 -18.74781,2.4714 -26.75364,6.6625 4.54607,10.0696 7.07867,21.2422 7.07867,32.9998 0,22.0146 -8.85114,42.0052 -23.21431,56.5275 10.5516,11.7145 25.861,19.0503 42.88961,19.0503 31.87937,0 57.67165,-25.7916 57.67165,-57.6717 0,-31.8793 -25.79195,-57.5664 -57.67165,-57.5664 z m -244.00885,7.5998 c -29.3701,0 -53.19693,23.6164 -53.19693,52.9832 0,29.3669 23.82815,53.1937 53.19364,53.1937 11.17727,0 21.53161,-3.4825 30.08487,-9.369 -3.5344,-5.492 -5.62151,-12.0581 -5.62151,-19.0503 0,-3.6291 0.53552,-7.1158 1.56148,-10.4099 -16.01267,-11.5721 -26.44131,-30.4034 -26.44131,-51.6319 0,-5.394 0.71083,-10.6098 1.97792,-15.6152 -0.52591,-0.013 -1.03171,-0.1052 -1.56152,-0.1052 z m 312.19495,45.5955 c -1.56661,0 -3.08252,0.1789 -4.58026,0.4169 0.0829,1.3242 0.1039,2.6108 0.1039,3.9559 0,16.9326 -6.68118,32.3015 -17.4889,43.7214 5.31706,6.1831 13.12695,10.0976 21.96526,10.0976 16.09849,0 29.14785,-12.9451 29.14785,-29.0439 0,-16.0985 -13.04936,-29.1479 -29.14785,-29.1479 z m -252.64924,3.1229 c -16.09783,0 -29.04395,12.9461 -29.04395,29.044 0,16.0978 12.94612,29.1478 29.04395,29.1478 12.33919,0 22.81287,-7.6994 27.06599,-18.5298 -10.378,-10.57 -17.83675,-24.0544 -21.13213,-39.0363 -1.92854,-0.3985 -3.88588,-0.6247 -5.93386,-0.6247 z"
|
||||||
|
id="path6"
|
||||||
|
inkscape:connector-curvature="0" /></svg>
|
||||||
|
After Width: | Height: | Size: 4.6 KiB |
BIN
admin/osx/installer-background_2x.png
Normal file
BIN
admin/osx/installer-background_2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@@ -23,7 +23,7 @@ import sys
|
|||||||
from glob import glob
|
from glob import glob
|
||||||
|
|
||||||
def QueryQMake(attrib):
|
def QueryQMake(attrib):
|
||||||
return subprocess.check_output(['qmake', '-query', attrib]).rstrip('\n')
|
return subprocess.check_output([qmake_path, '-query', attrib]).rstrip('\n')
|
||||||
|
|
||||||
FRAMEWORK_SEARCH_PATH=[
|
FRAMEWORK_SEARCH_PATH=[
|
||||||
'/Library/Frameworks',
|
'/Library/Frameworks',
|
||||||
@@ -68,14 +68,18 @@ class CouldNotFindQtPluginError(Error):
|
|||||||
class CouldNotFindScriptPluginError(Error):
|
class CouldNotFindScriptPluginError(Error):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if len(sys.argv) < 2:
|
class CouldNotFindFrameworkError(Error):
|
||||||
print 'Usage: %s <bundle.app>' % sys.argv[0]
|
pass
|
||||||
|
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
print 'Usage: %s <bundle.app> <path-to-qmake>' % sys.argv[0]
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
def is_exe(fpath):
|
def is_exe(fpath):
|
||||||
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
|
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
|
||||||
|
|
||||||
bundle_dir = sys.argv[1]
|
bundle_dir = sys.argv[1]
|
||||||
|
qmake_path = sys.argv[2]
|
||||||
|
|
||||||
bundle_name = os.path.basename(bundle_dir).split('.')[0]
|
bundle_name = os.path.basename(bundle_dir).split('.')[0]
|
||||||
|
|
||||||
@@ -246,8 +250,10 @@ def CopyFramework(path):
|
|||||||
parts = path.split(os.sep)
|
parts = path.split(os.sep)
|
||||||
print "CopyFramework:", path
|
print "CopyFramework:", path
|
||||||
for i, part in enumerate(parts):
|
for i, part in enumerate(parts):
|
||||||
if re.match(r'\w+\.framework', part):
|
matchObj = re.match(r'(\w+\.framework)', part)
|
||||||
|
if matchObj:
|
||||||
full_path = os.path.join(frameworks_dir, *parts[i:-1])
|
full_path = os.path.join(frameworks_dir, *parts[i:-1])
|
||||||
|
framework = matchObj.group(1)
|
||||||
break
|
break
|
||||||
args = ['mkdir', '-p', full_path]
|
args = ['mkdir', '-p', full_path]
|
||||||
commands.append(args)
|
commands.append(args)
|
||||||
@@ -255,12 +261,13 @@ def CopyFramework(path):
|
|||||||
commands.append(args)
|
commands.append(args)
|
||||||
args = ['chmod', 'u+w', os.path.join(full_path, parts[-1])]
|
args = ['chmod', 'u+w', os.path.join(full_path, parts[-1])]
|
||||||
commands.append(args)
|
commands.append(args)
|
||||||
|
args = ['chmod', 'u+w', os.path.join(frameworks_dir, framework, "Resources")]
|
||||||
|
commands.append(args)
|
||||||
|
|
||||||
info_plist = os.path.join(os.path.split(path)[0], '..', '..', 'Contents', 'Info.plist')
|
info_plist = os.path.join(os.path.split(path)[0], '..', '..', 'Contents', 'Info.plist')
|
||||||
if os.path.exists(info_plist):
|
if os.path.exists(info_plist):
|
||||||
args = ['cp', '-r', info_plist, resources_dir]
|
args = ['cp', '-r', info_plist, os.path.join(frameworks_dir, framework, "Resources")]
|
||||||
commands.append(args)
|
commands.append(args)
|
||||||
|
|
||||||
return os.path.join(full_path, parts[-1])
|
return os.path.join(full_path, parts[-1])
|
||||||
|
|
||||||
def FixId(path, library_name):
|
def FixId(path, library_name):
|
||||||
|
|||||||
@@ -491,7 +491,7 @@
|
|||||||
<key>OVERWRITE_PERMISSIONS</key>
|
<key>OVERWRITE_PERMISSIONS</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>VERSION</key>
|
<key>VERSION</key>
|
||||||
<string>1.6.2</string>
|
<string>@MIRALL_VERSION_FULL@</string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>UUID</key>
|
<key>UUID</key>
|
||||||
<string>7D7219B7-1897-48C3-8533-842BDEC46F71</string>
|
<string>7D7219B7-1897-48C3-8533-842BDEC46F71</string>
|
||||||
@@ -793,7 +793,7 @@
|
|||||||
<key>GID</key>
|
<key>GID</key>
|
||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
<key>PATH</key>
|
<key>PATH</key>
|
||||||
<string>Library/ScriptingAdditions/OwnCloudFinder.osax/Contents</string>
|
<string>Library/ScriptingAdditions/SyncStateFinder.osax/Contents</string>
|
||||||
<key>PATH_TYPE</key>
|
<key>PATH_TYPE</key>
|
||||||
<integer>3</integer>
|
<integer>3</integer>
|
||||||
<key>PERMISSIONS</key>
|
<key>PERMISSIONS</key>
|
||||||
@@ -807,7 +807,7 @@
|
|||||||
<key>GID</key>
|
<key>GID</key>
|
||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
<key>PATH</key>
|
<key>PATH</key>
|
||||||
<string>OwnCloudFinder.osax</string>
|
<string>SyncStateFinder.osax</string>
|
||||||
<key>PATH_TYPE</key>
|
<key>PATH_TYPE</key>
|
||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
<key>PERMISSIONS</key>
|
<key>PERMISSIONS</key>
|
||||||
@@ -1019,7 +1019,7 @@
|
|||||||
<key>OVERWRITE_PERMISSIONS</key>
|
<key>OVERWRITE_PERMISSIONS</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>VERSION</key>
|
<key>VERSION</key>
|
||||||
<string>1.6.2</string>
|
<string>@MIRALL_VERSION_FULL@</string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>TYPE</key>
|
<key>TYPE</key>
|
||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
@@ -1041,7 +1041,7 @@
|
|||||||
ZW50LVN0eWxlLVR5cGUiIGNvbnRlbnQ9InRleHQvY3NzIj4KPHRp
|
ZW50LVN0eWxlLVR5cGUiIGNvbnRlbnQ9InRleHQvY3NzIj4KPHRp
|
||||||
dGxlPjwvdGl0bGU+CjxtZXRhIG5hbWU9IkdlbmVyYXRvciIgY29u
|
dGxlPjwvdGl0bGU+CjxtZXRhIG5hbWU9IkdlbmVyYXRvciIgY29u
|
||||||
dGVudD0iQ29jb2EgSFRNTCBXcml0ZXIiPgo8bWV0YSBuYW1lPSJD
|
dGVudD0iQ29jb2EgSFRNTCBXcml0ZXIiPgo8bWV0YSBuYW1lPSJD
|
||||||
b2NvYVZlcnNpb24iIGNvbnRlbnQ9IjExMzguNTEiPgo8c3R5bGUg
|
b2NvYVZlcnNpb24iIGNvbnRlbnQ9IjEzNDMuMTQiPgo8c3R5bGUg
|
||||||
dHlwZT0idGV4dC9jc3MiPgo8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5
|
dHlwZT0idGV4dC9jc3MiPgo8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5
|
||||||
Pgo8L2JvZHk+CjwvaHRtbD4K
|
Pgo8L2JvZHk+CjwvaHRtbD4K
|
||||||
</data>
|
</data>
|
||||||
@@ -1054,10 +1054,10 @@
|
|||||||
<integer>6</integer>
|
<integer>6</integer>
|
||||||
<key>BACKGROUND_PATH</key>
|
<key>BACKGROUND_PATH</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>PATH</key>
|
<key>PATH</key>
|
||||||
<string>./@APPLICATION_EXECUTABLE@.app/Contents/Resources/owncloud_logo_blue.png</string>
|
<string>@CMAKE_SOURCE_DIR@/admin/osx/installer-background.png</string>
|
||||||
<key>PATH_TYPE</key>
|
<key>PATH_TYPE</key>
|
||||||
<integer>3</integer>
|
<integer>0</integer>
|
||||||
</dict>
|
</dict>
|
||||||
<key>CUSTOM</key>
|
<key>CUSTOM</key>
|
||||||
<integer>1</integer>
|
<integer>1</integer>
|
||||||
@@ -1415,7 +1415,7 @@
|
|||||||
<key>NAME</key>
|
<key>NAME</key>
|
||||||
<string>ownCloud Installer</string>
|
<string>ownCloud Installer</string>
|
||||||
<key>REFERENCE_FOLDER_PATH</key>
|
<key>REFERENCE_FOLDER_PATH</key>
|
||||||
<string>/Users/mackie/install</string>
|
<string>@CMAKE_INSTALL_DIR@</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>TYPE</key>
|
<key>TYPE</key>
|
||||||
|
|||||||
2
binary
2
binary
Submodule binary updated: 82d72bc62d...151fc83a05
@@ -14,7 +14,8 @@ if (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
|
|||||||
|
|
||||||
# add -Wconversion ?
|
# add -Wconversion ?
|
||||||
# cannot be pedantic with sqlite3 directly linked
|
# cannot be pedantic with sqlite3 directly linked
|
||||||
if (NOT CSYNC_STATIC_COMPILE_DIR)
|
# FIXME Can we somehow not use those flags for sqlite3.* but use them for the rest of csync?
|
||||||
|
if (NOT USE_OUR_OWN_SQLITE3)
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -pedantic-errors")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -pedantic-errors")
|
||||||
endif()
|
endif()
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes")
|
||||||
|
|||||||
@@ -50,8 +50,18 @@ if (SQLite3_FIND_VERSION AND _SQLITE3_VERSION)
|
|||||||
set(SQLite3_VERSION _SQLITE3_VERSION)
|
set(SQLite3_VERSION _SQLITE3_VERSION)
|
||||||
endif (SQLite3_FIND_VERSION AND _SQLITE3_VERSION)
|
endif (SQLite3_FIND_VERSION AND _SQLITE3_VERSION)
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
if (APPLE OR WIN32)
|
||||||
find_package_handle_standard_args(SQLite3 DEFAULT_MSG SQLITE3_LIBRARIES SQLITE3_INCLUDE_DIRS)
|
set(USE_OUR_OWN_SQLITE3 TRUE)
|
||||||
|
set(SQLITE3_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/src/3rdparty/sqlite3)
|
||||||
|
set(SQLITE3_LIBRARIES "")
|
||||||
|
set(SQLITE3_SOURCE ${SQLITE3_INCLUDE_DIR}/sqlite3.c)
|
||||||
|
MESSAGE(STATUS "Using own sqlite3 from " ${SQLITE3_INCLUDE_DIR})
|
||||||
|
else()
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(SQLite3 DEFAULT_MSG SQLITE3_LIBRARIES SQLITE3_INCLUDE_DIRS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# show the SQLITE3_INCLUDE_DIRS and SQLITE3_LIBRARIES variables only in the advanced view
|
# show the SQLITE3_INCLUDE_DIRS and SQLITE3_LIBRARIES variables only in the advanced view
|
||||||
mark_as_advanced(SQLITE3_INCLUDE_DIRS SQLITE3_LIBRARIES)
|
mark_as_advanced(SQLITE3_INCLUDE_DIRS SQLITE3_LIBRARIES)
|
||||||
|
|||||||
@@ -391,6 +391,7 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
|
|||||||
; Make sure only to copy qt, not qt_help, etc
|
; Make sure only to copy qt, not qt_help, etc
|
||||||
File "${MING_SHARE}\qt5\translations\qt_??.qm"
|
File "${MING_SHARE}\qt5\translations\qt_??.qm"
|
||||||
File "${MING_SHARE}\qt5\translations\qt_??_??.qm"
|
File "${MING_SHARE}\qt5\translations\qt_??_??.qm"
|
||||||
|
File "${MING_SHARE}\qt5\translations\qtbase_*.qm"
|
||||||
File "${MING_SHARE}\qt5\translations\qtkeychain_*.qm"
|
File "${MING_SHARE}\qt5\translations\qtkeychain_*.qm"
|
||||||
|
|
||||||
SetOutPath "$INSTDIR\platforms"
|
SetOutPath "$INSTDIR\platforms"
|
||||||
|
|||||||
@@ -153,7 +153,18 @@ if(NOT Qt5Core_FOUND)
|
|||||||
include( ${QT_USE_FILE} )
|
include( ${QT_USE_FILE} )
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
add_definitions("-DQ_DECL_OVERRIDE=override")
|
if (CMAKE_COMPILER_IS_GNUCC)
|
||||||
|
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
|
||||||
|
OUTPUT_VARIABLE GCC_VERSION)
|
||||||
|
if (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)
|
||||||
|
add_definitions("-DQ_DECL_OVERRIDE=override")
|
||||||
|
else()
|
||||||
|
add_definitions("-DQ_DECL_OVERRIDE=")
|
||||||
|
endif()
|
||||||
|
else() #clang or others
|
||||||
|
add_definitions("-DQ_DECL_OVERRIDE=override")
|
||||||
|
endif()
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if( Qt5Core_DIR )
|
if( Qt5Core_DIR )
|
||||||
|
|||||||
@@ -4,13 +4,6 @@ add_subdirectory(std)
|
|||||||
add_subdirectory(httpbf)
|
add_subdirectory(httpbf)
|
||||||
|
|
||||||
# Statically include sqlite
|
# Statically include sqlite
|
||||||
if (CSYNC_STATIC_COMPILE_DIR)
|
|
||||||
set(SQLITE3_INCLUDE_DIRS "")
|
|
||||||
set(SQLITE3_LIBRARIES "")
|
|
||||||
include_directories(${CSYNC_STATIC_COMPILE_DIR})
|
|
||||||
else (CSYNC_STATIC_COMPILE_DIR)
|
|
||||||
find_package(SQLite3 3.3.9 REQUIRED)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CSYNC_PUBLIC_INCLUDE_DIRS
|
set(CSYNC_PUBLIC_INCLUDE_DIRS
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
@@ -86,8 +79,8 @@ set(csync_HDRS
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Statically include sqlite
|
# Statically include sqlite
|
||||||
if (CSYNC_STATIC_COMPILE_DIR)
|
if (USE_OUR_OWN_SQLITE3)
|
||||||
list(APPEND csync_SRCS ${CSYNC_STATIC_COMPILE_DIR}/dictionary.c ${CSYNC_STATIC_COMPILE_DIR}/sqlite3.c)
|
list(APPEND csync_SRCS ${SQLITE3_SOURCE})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
|
|||||||
@@ -228,9 +228,10 @@ int csync_update(CSYNC *ctx) {
|
|||||||
|
|
||||||
rc = csync_ftw(ctx, ctx->local.uri, csync_walker, MAX_DEPTH);
|
rc = csync_ftw(ctx, ctx->local.uri, csync_walker, MAX_DEPTH);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
if(ctx->status_code == CSYNC_STATUS_OK)
|
if(ctx->status_code == CSYNC_STATUS_OK) {
|
||||||
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_UPDATE_ERROR);
|
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_UPDATE_ERROR);
|
||||||
return -1;
|
}
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
csync_gettime(&finish);
|
csync_gettime(&finish);
|
||||||
@@ -247,9 +248,10 @@ int csync_update(CSYNC *ctx) {
|
|||||||
|
|
||||||
rc = csync_ftw(ctx, ctx->remote.uri, csync_walker, MAX_DEPTH);
|
rc = csync_ftw(ctx, ctx->remote.uri, csync_walker, MAX_DEPTH);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
if(ctx->status_code == CSYNC_STATUS_OK)
|
if(ctx->status_code == CSYNC_STATUS_OK) {
|
||||||
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_UPDATE_ERROR);
|
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_UPDATE_ERROR);
|
||||||
return -1;
|
}
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
csync_gettime(&finish);
|
csync_gettime(&finish);
|
||||||
@@ -262,7 +264,11 @@ int csync_update(CSYNC *ctx) {
|
|||||||
|
|
||||||
ctx->status |= CSYNC_STATUS_UPDATE;
|
ctx->status |= CSYNC_STATUS_UPDATE;
|
||||||
|
|
||||||
return 0;
|
rc = 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
csync_statedb_close(ctx);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int csync_reconcile(CSYNC *ctx) {
|
int csync_reconcile(CSYNC *ctx) {
|
||||||
@@ -278,6 +284,12 @@ int csync_reconcile(CSYNC *ctx) {
|
|||||||
/* Reconciliation for local replica */
|
/* Reconciliation for local replica */
|
||||||
csync_gettime(&start);
|
csync_gettime(&start);
|
||||||
|
|
||||||
|
if (csync_statedb_load(ctx, ctx->statedb.file, &ctx->statedb.db) < 0) {
|
||||||
|
ctx->status_code = CSYNC_STATUS_STATEDB_LOAD_ERROR;
|
||||||
|
rc = -1;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->current = LOCAL_REPLICA;
|
ctx->current = LOCAL_REPLICA;
|
||||||
ctx->replica = ctx->local.type;
|
ctx->replica = ctx->local.type;
|
||||||
|
|
||||||
@@ -293,7 +305,7 @@ int csync_reconcile(CSYNC *ctx) {
|
|||||||
if (!CSYNC_STATUS_IS_OK(ctx->status_code)) {
|
if (!CSYNC_STATUS_IS_OK(ctx->status_code)) {
|
||||||
ctx->status_code = csync_errno_to_status( errno, CSYNC_STATUS_RECONCILE_ERROR );
|
ctx->status_code = csync_errno_to_status( errno, CSYNC_STATUS_RECONCILE_ERROR );
|
||||||
}
|
}
|
||||||
return -1;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reconciliation for remote replica */
|
/* Reconciliation for remote replica */
|
||||||
@@ -314,11 +326,15 @@ int csync_reconcile(CSYNC *ctx) {
|
|||||||
if (!CSYNC_STATUS_IS_OK(ctx->status_code)) {
|
if (!CSYNC_STATUS_IS_OK(ctx->status_code)) {
|
||||||
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_RECONCILE_ERROR );
|
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_RECONCILE_ERROR );
|
||||||
}
|
}
|
||||||
return -1;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->status |= CSYNC_STATUS_RECONCILE;
|
ctx->status |= CSYNC_STATUS_RECONCILE;
|
||||||
|
|
||||||
|
rc = 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
csync_statedb_close(ctx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -156,6 +156,40 @@ CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype) {
|
|||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See http://support.microsoft.com/kb/74496
|
||||||
|
static const char *win_reserved_words[] = {"CON","PRN","AUX", "NUL",
|
||||||
|
"COM1", "COM2", "COM3", "COM4",
|
||||||
|
"LPT1", "LPT2", "LPT3", "CLOCK$" };
|
||||||
|
|
||||||
|
|
||||||
|
bool csync_is_windows_reserved_word(const char* filename) {
|
||||||
|
|
||||||
|
size_t win_reserve_words_len = sizeof(win_reserved_words) / sizeof(char*);
|
||||||
|
size_t j;
|
||||||
|
|
||||||
|
for (j = 0; j < win_reserve_words_len; j++) {
|
||||||
|
int len_reserved_word = strlen(win_reserved_words[j]);
|
||||||
|
int len_filename = strlen(filename);
|
||||||
|
if (len_filename == 2 && filename[1] == ':') {
|
||||||
|
if (filename[0] >= 'a' && filename[0] <= 'z') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (filename[0] >= 'A' && filename[0] <= 'Z') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c_strncasecmp(filename, win_reserved_words[j], len_reserved_word) == 0) {
|
||||||
|
if (len_filename == len_reserved_word) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((len_filename > len_reserved_word) && (filename[len_reserved_word] == '.')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype) {
|
CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
const char *p = NULL;
|
const char *p = NULL;
|
||||||
@@ -214,6 +248,13 @@ CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path
|
|||||||
SAFE_FREE(dname);
|
SAFE_FREE(dname);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (csync_is_windows_reserved_word(bname)) {
|
||||||
|
match = CSYNC_FILE_EXCLUDE_INVALID_CHAR;
|
||||||
|
SAFE_FREE(bname);
|
||||||
|
SAFE_FREE(dname);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rc = csync_fnmatch(".owncloudsync.log*", bname, 0);
|
rc = csync_fnmatch(".owncloudsync.log*", bname, 0);
|
||||||
|
|||||||
@@ -80,4 +80,12 @@ CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype);
|
|||||||
CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype);
|
CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype);
|
||||||
#endif /* _CSYNC_EXCLUDE_H */
|
#endif /* _CSYNC_EXCLUDE_H */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if filename is considered reserved by Windows
|
||||||
|
* @param file_name filename
|
||||||
|
* @return true if file is reserved, false otherwise
|
||||||
|
*/
|
||||||
|
bool csync_is_windows_reserved_word(const char *file_name);
|
||||||
|
|
||||||
|
|
||||||
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */
|
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ static int ssl_callback_by_neon(void *userdata, int failures,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
DEBUG_WEBDAV("## VERIFY_SSL CERT: %d", ret );
|
DEBUG_WEBDAV("## VERIFY_SSL CERT: %d", ret );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -761,6 +761,7 @@ int owncloud_commit(CSYNC* ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx->owncloud_context->is_first_propfind = true;
|
ctx->owncloud_context->is_first_propfind = true;
|
||||||
|
ctx->owncloud_context->dav_session.no_recursive_propfind = true;
|
||||||
/* DEBUG_WEBDAV( "********** vio_module_shutdown" ); */
|
/* DEBUG_WEBDAV( "********** vio_module_shutdown" ); */
|
||||||
|
|
||||||
ctx->owncloud_context->dav_session.ctx = 0;
|
ctx->owncloud_context->dav_session.ctx = 0;
|
||||||
|
|||||||
@@ -100,6 +100,8 @@ struct csync_s {
|
|||||||
sqlite3_stmt* by_hash_stmt;
|
sqlite3_stmt* by_hash_stmt;
|
||||||
sqlite3_stmt* by_fileid_stmt;
|
sqlite3_stmt* by_fileid_stmt;
|
||||||
sqlite3_stmt* by_inode_stmt;
|
sqlite3_stmt* by_inode_stmt;
|
||||||
|
|
||||||
|
int lastReturnValue;
|
||||||
} statedb;
|
} statedb;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -146,8 +148,8 @@ struct csync_s {
|
|||||||
struct csync_owncloud_ctx_s *owncloud_context;
|
struct csync_owncloud_ctx_s *owncloud_context;
|
||||||
|
|
||||||
/* hooks for checking the white list */
|
/* hooks for checking the white list */
|
||||||
void *checkBlackListData;
|
void *checkSelectiveSyncBlackListData;
|
||||||
int (*checkBlackListHook)(void*, const char*);
|
int (*checkSelectiveSyncBlackListHook)(void*, const char*);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -138,6 +138,11 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) {
|
|||||||
/* Do not remove a directory that has ignored files */
|
/* Do not remove a directory that has ignored files */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (cur->child_modified) {
|
||||||
|
/* re-create directory that has modified contents */
|
||||||
|
cur->instruction = CSYNC_INSTRUCTION_NEW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
cur->instruction = CSYNC_INSTRUCTION_REMOVE;
|
cur->instruction = CSYNC_INSTRUCTION_REMOVE;
|
||||||
break;
|
break;
|
||||||
case CSYNC_INSTRUCTION_EVAL_RENAME:
|
case CSYNC_INSTRUCTION_EVAL_RENAME:
|
||||||
|
|||||||
@@ -50,6 +50,22 @@
|
|||||||
|
|
||||||
#define BUF_SIZE 16
|
#define BUF_SIZE 16
|
||||||
|
|
||||||
|
#define sqlite_open(A, B) sqlite3_open_v2(A,B, SQLITE_OPEN_READONLY+SQLITE_OPEN_NOMUTEX, NULL)
|
||||||
|
|
||||||
|
#define SQLTM_TIME 150000
|
||||||
|
#define SQLTM_COUNT 10
|
||||||
|
|
||||||
|
#define SQLITE_BUSY_HANDLED(F) if(1) { \
|
||||||
|
int n = 0; \
|
||||||
|
do { rc = F ; \
|
||||||
|
if( (rc == SQLITE_BUSY) || (rc == SQLITE_LOCKED) ) { \
|
||||||
|
n++; \
|
||||||
|
usleep(SQLTM_TIME); \
|
||||||
|
} \
|
||||||
|
}while( (n < SQLTM_COUNT) && ((rc == SQLITE_BUSY) || (rc == SQLITE_LOCKED))); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void csync_set_statedb_exists(CSYNC *ctx, int val) {
|
void csync_set_statedb_exists(CSYNC *ctx, int val) {
|
||||||
ctx->statedb.exists = val;
|
ctx->statedb.exists = val;
|
||||||
}
|
}
|
||||||
@@ -73,85 +89,12 @@ static int _csync_check_db_integrity(sqlite3 *db) {
|
|||||||
c_strlist_destroy(result);
|
c_strlist_destroy(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
if( sqlite3_threadsafe() == 0 ) {
|
||||||
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "* WARNING: SQLite module is not threadsafe!");
|
||||||
}
|
rc = -1;
|
||||||
|
|
||||||
static int _csync_statedb_check(const char *statedb) {
|
|
||||||
int fd = -1, rc;
|
|
||||||
ssize_t r;
|
|
||||||
char buf[BUF_SIZE] = {0};
|
|
||||||
sqlite3 *db = NULL;
|
|
||||||
csync_stat_t sb;
|
|
||||||
|
|
||||||
mbchar_t *wstatedb = c_utf8_to_locale(statedb);
|
|
||||||
|
|
||||||
if (wstatedb == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check db version */
|
|
||||||
#ifdef _WIN32
|
|
||||||
_fmode = _O_BINARY;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fd = _topen(wstatedb, O_RDONLY);
|
|
||||||
|
|
||||||
if (fd >= 0) {
|
|
||||||
/* Check size. Size of zero is a valid database actually. */
|
|
||||||
rc = _tfstat(fd, &sb);
|
|
||||||
|
|
||||||
if (rc == 0) {
|
|
||||||
if (sb.st_size == 0) {
|
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Database size is zero byte!");
|
|
||||||
close(fd);
|
|
||||||
} else {
|
|
||||||
r = read(fd, (void *) buf, sizeof(buf) - 1);
|
|
||||||
close(fd);
|
|
||||||
if (r >= 0) {
|
|
||||||
buf[BUF_SIZE - 1] = '\0';
|
|
||||||
if (c_streq(buf, "SQLite format 3")) {
|
|
||||||
if (sqlite3_open(statedb, &db ) == SQLITE_OK) {
|
|
||||||
rc = _csync_check_db_integrity(db);
|
|
||||||
if( sqlite3_close(db) != 0 ) {
|
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "WARN: sqlite3_close error!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if( rc >= 0 ) {
|
|
||||||
/* everything is fine */
|
|
||||||
c_free_locale_string(wstatedb);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Integrity check failed!");
|
|
||||||
} else {
|
|
||||||
/* resources need to be freed even when open failed */
|
|
||||||
sqlite3_close(db);
|
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "database corrupted, removing!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "sqlite version mismatch");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
/* if it comes here, the database is broken and should be recreated. */
|
|
||||||
_tunlink(wstatedb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c_free_locale_string(wstatedb);
|
return rc;
|
||||||
|
|
||||||
/* create database */
|
|
||||||
rc = sqlite3_open(statedb, &db);
|
|
||||||
if (rc == SQLITE_OK) {
|
|
||||||
sqlite3_close(db);
|
|
||||||
csync_win32_set_file_hidden(statedb, true);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
sqlite3_close(db);
|
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "sqlite3_open failed: %s %s", sqlite3_errmsg(db), statedb);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _csync_statedb_is_empty(sqlite3 *db) {
|
static int _csync_statedb_is_empty(sqlite3 *db) {
|
||||||
@@ -179,7 +122,6 @@ static void sqlite_profile( void *x, const char* sql, sqlite3_uint64 time)
|
|||||||
|
|
||||||
int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb) {
|
int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb) {
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
int check_rc = -1;
|
|
||||||
c_strlist_t *result = NULL;
|
c_strlist_t *result = NULL;
|
||||||
sqlite3 *db = NULL;
|
sqlite3 *db = NULL;
|
||||||
|
|
||||||
@@ -187,19 +129,15 @@ int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* csync_statedb_check tries to open the statedb and creates it in case
|
if (ctx->statedb.db) {
|
||||||
* its not there.
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "ERR: DB already open");
|
||||||
*/
|
return -1;
|
||||||
check_rc = _csync_statedb_check(statedb);
|
|
||||||
if (check_rc < 0) {
|
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "ERR: checking csync database failed - bail out.");
|
|
||||||
|
|
||||||
rc = -1;
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open or create the temporary database */
|
ctx->statedb.lastReturnValue = SQLITE_OK;
|
||||||
if (sqlite3_open(statedb, &db) != SQLITE_OK) {
|
|
||||||
|
/* Openthe database */
|
||||||
|
if (sqlite_open(statedb, &db) != SQLITE_OK) {
|
||||||
const char *errmsg= sqlite3_errmsg(ctx->statedb.db);
|
const char *errmsg= sqlite3_errmsg(ctx->statedb.db);
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "ERR: Failed to sqlite3 open statedb - bail out: %s.",
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "ERR: Failed to sqlite3 open statedb - bail out: %s.",
|
||||||
errmsg ? errmsg : "<no sqlite3 errormsg>");
|
errmsg ? errmsg : "<no sqlite3 errormsg>");
|
||||||
@@ -208,16 +146,31 @@ int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb) {
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If check_rc == 1 the database is new and empty as a result. */
|
if (_csync_check_db_integrity(db) != 0) {
|
||||||
if ((check_rc == 1) || _csync_statedb_is_empty(db)) {
|
const char *errmsg= sqlite3_errmsg(db);
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "statedb doesn't exist");
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "ERR: sqlite3 integrity check failed - bail out: %s.",
|
||||||
|
errmsg ? errmsg : "<no sqlite3 errormsg>");
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_csync_statedb_is_empty(db)) {
|
||||||
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "statedb contents doesn't exist");
|
||||||
csync_set_statedb_exists(ctx, 0);
|
csync_set_statedb_exists(ctx, 0);
|
||||||
} else {
|
} else {
|
||||||
csync_set_statedb_exists(ctx, 1);
|
csync_set_statedb_exists(ctx, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Print out the version */
|
||||||
|
//
|
||||||
|
result = csync_statedb_query(db, "SELECT sqlite_version();");
|
||||||
|
if (result && result->count >= 1) {
|
||||||
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "sqlite3 version \"%s\"", *result->vector);
|
||||||
|
}
|
||||||
|
c_strlist_destroy(result);
|
||||||
|
|
||||||
/* optimization for speeding up SQLite */
|
/* optimization for speeding up SQLite */
|
||||||
result = csync_statedb_query(db, "PRAGMA synchronous = FULL;");
|
result = csync_statedb_query(db, "PRAGMA synchronous = NORMAL;");
|
||||||
c_strlist_destroy(result);
|
c_strlist_destroy(result);
|
||||||
result = csync_statedb_query(db, "PRAGMA case_sensitive_like = ON;");
|
result = csync_statedb_query(db, "PRAGMA case_sensitive_like = ON;");
|
||||||
c_strlist_destroy(result);
|
c_strlist_destroy(result);
|
||||||
@@ -230,6 +183,8 @@ int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb) {
|
|||||||
#endif
|
#endif
|
||||||
*pdb = db;
|
*pdb = db;
|
||||||
|
|
||||||
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "Success");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
out:
|
out:
|
||||||
sqlite3_close(db);
|
sqlite3_close(db);
|
||||||
@@ -244,22 +199,25 @@ int csync_statedb_close(CSYNC *ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* deallocate query resources */
|
/* deallocate query resources */
|
||||||
if( ctx->statedb.by_hash_stmt ) {
|
|
||||||
rc = sqlite3_finalize(ctx->statedb.by_hash_stmt);
|
|
||||||
ctx->statedb.by_hash_stmt = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ctx->statedb.by_fileid_stmt ) {
|
if( ctx->statedb.by_fileid_stmt ) {
|
||||||
rc = sqlite3_finalize(ctx->statedb.by_fileid_stmt);
|
sqlite3_finalize(ctx->statedb.by_fileid_stmt);
|
||||||
ctx->statedb.by_fileid_stmt = NULL;
|
ctx->statedb.by_fileid_stmt = NULL;
|
||||||
}
|
}
|
||||||
|
if( ctx->statedb.by_hash_stmt ) {
|
||||||
if( ctx->statedb.by_inode_stmt ) {
|
sqlite3_finalize(ctx->statedb.by_hash_stmt);
|
||||||
rc = sqlite3_finalize(ctx->statedb.by_inode_stmt);
|
ctx->statedb.by_hash_stmt = NULL;
|
||||||
|
}
|
||||||
|
if( ctx->statedb.by_inode_stmt) {
|
||||||
|
sqlite3_finalize(ctx->statedb.by_inode_stmt);
|
||||||
ctx->statedb.by_inode_stmt = NULL;
|
ctx->statedb.by_inode_stmt = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3_close(ctx->statedb.db);
|
ctx->statedb.lastReturnValue = SQLITE_OK;
|
||||||
|
|
||||||
|
int sr = sqlite3_close(ctx->statedb.db);
|
||||||
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "sqlite3_close=%d", sr);
|
||||||
|
|
||||||
|
ctx->statedb.db = 0;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -281,7 +239,7 @@ static int _csync_file_stat_from_metadata_table( csync_file_stat_t **st, sqlite3
|
|||||||
|
|
||||||
column_count = sqlite3_column_count(stmt);
|
column_count = sqlite3_column_count(stmt);
|
||||||
|
|
||||||
rc = sqlite3_step(stmt);
|
SQLITE_BUSY_HANDLED( sqlite3_step(stmt) );
|
||||||
|
|
||||||
if( rc == SQLITE_ROW ) {
|
if( rc == SQLITE_ROW ) {
|
||||||
if(column_count > 7) {
|
if(column_count > 7) {
|
||||||
@@ -344,7 +302,8 @@ csync_file_stat_t *csync_statedb_get_stat_by_hash(CSYNC *ctx,
|
|||||||
if( ctx->statedb.by_hash_stmt == NULL ) {
|
if( ctx->statedb.by_hash_stmt == NULL ) {
|
||||||
const char *hash_query = "SELECT * FROM metadata WHERE phash=?1";
|
const char *hash_query = "SELECT * FROM metadata WHERE phash=?1";
|
||||||
|
|
||||||
rc = sqlite3_prepare_v2(ctx->statedb.db, hash_query, strlen(hash_query), &ctx->statedb.by_hash_stmt, NULL);
|
SQLITE_BUSY_HANDLED(sqlite3_prepare_v2(ctx->statedb.db, hash_query, strlen(hash_query), &ctx->statedb.by_hash_stmt, NULL));
|
||||||
|
ctx->statedb.lastReturnValue = rc;
|
||||||
if( rc != SQLITE_OK ) {
|
if( rc != SQLITE_OK ) {
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for hash query.");
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for hash query.");
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -358,6 +317,7 @@ csync_file_stat_t *csync_statedb_get_stat_by_hash(CSYNC *ctx,
|
|||||||
sqlite3_bind_int64(ctx->statedb.by_hash_stmt, 1, (long long signed int)phash);
|
sqlite3_bind_int64(ctx->statedb.by_hash_stmt, 1, (long long signed int)phash);
|
||||||
|
|
||||||
rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_hash_stmt);
|
rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_hash_stmt);
|
||||||
|
ctx->statedb.lastReturnValue = rc;
|
||||||
if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) ) {
|
if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) ) {
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata: %d!", rc);
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata: %d!", rc);
|
||||||
}
|
}
|
||||||
@@ -385,7 +345,8 @@ csync_file_stat_t *csync_statedb_get_stat_by_file_id(CSYNC *ctx,
|
|||||||
if( ctx->statedb.by_fileid_stmt == NULL ) {
|
if( ctx->statedb.by_fileid_stmt == NULL ) {
|
||||||
const char *query = "SELECT * FROM metadata WHERE fileid=?1";
|
const char *query = "SELECT * FROM metadata WHERE fileid=?1";
|
||||||
|
|
||||||
rc = sqlite3_prepare_v2(ctx->statedb.db, query, strlen(query), &ctx->statedb.by_fileid_stmt, NULL);
|
SQLITE_BUSY_HANDLED(sqlite3_prepare_v2(ctx->statedb.db, query, strlen(query), &ctx->statedb.by_fileid_stmt, NULL));
|
||||||
|
ctx->statedb.lastReturnValue = rc;
|
||||||
if( rc != SQLITE_OK ) {
|
if( rc != SQLITE_OK ) {
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for file id query.");
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for file id query.");
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -396,6 +357,7 @@ csync_file_stat_t *csync_statedb_get_stat_by_file_id(CSYNC *ctx,
|
|||||||
sqlite3_bind_text(ctx->statedb.by_fileid_stmt, 1, file_id, -1, SQLITE_STATIC);
|
sqlite3_bind_text(ctx->statedb.by_fileid_stmt, 1, file_id, -1, SQLITE_STATIC);
|
||||||
|
|
||||||
rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_fileid_stmt);
|
rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_fileid_stmt);
|
||||||
|
ctx->statedb.lastReturnValue = rc;
|
||||||
if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) ) {
|
if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) ) {
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata: %d!", rc);
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata: %d!", rc);
|
||||||
}
|
}
|
||||||
@@ -423,7 +385,8 @@ csync_file_stat_t *csync_statedb_get_stat_by_inode(CSYNC *ctx,
|
|||||||
if( ctx->statedb.by_inode_stmt == NULL ) {
|
if( ctx->statedb.by_inode_stmt == NULL ) {
|
||||||
const char *inode_query = "SELECT * FROM metadata WHERE inode=?1";
|
const char *inode_query = "SELECT * FROM metadata WHERE inode=?1";
|
||||||
|
|
||||||
rc = sqlite3_prepare_v2(ctx->statedb.db, inode_query, strlen(inode_query), &ctx->statedb.by_inode_stmt, NULL);
|
SQLITE_BUSY_HANDLED(sqlite3_prepare_v2(ctx->statedb.db, inode_query, strlen(inode_query), &ctx->statedb.by_inode_stmt, NULL));
|
||||||
|
ctx->statedb.lastReturnValue = rc;
|
||||||
if( rc != SQLITE_OK ) {
|
if( rc != SQLITE_OK ) {
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for inode query.");
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for inode query.");
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -437,6 +400,7 @@ csync_file_stat_t *csync_statedb_get_stat_by_inode(CSYNC *ctx,
|
|||||||
sqlite3_bind_int64(ctx->statedb.by_inode_stmt, 1, (long long signed int)inode);
|
sqlite3_bind_int64(ctx->statedb.by_inode_stmt, 1, (long long signed int)inode);
|
||||||
|
|
||||||
rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_inode_stmt);
|
rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_inode_stmt);
|
||||||
|
ctx->statedb.lastReturnValue = rc;
|
||||||
if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) ) {
|
if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) ) {
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata by inode: %d!", rc);
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata by inode: %d!", rc);
|
||||||
}
|
}
|
||||||
@@ -485,7 +449,8 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sqlite3_prepare_v2(ctx->statedb.db, BELOW_PATH_QUERY, -1, &stmt, NULL);
|
SQLITE_BUSY_HANDLED(sqlite3_prepare_v2(ctx->statedb.db, BELOW_PATH_QUERY, -1, &stmt, NULL));
|
||||||
|
ctx->statedb.lastReturnValue = rc;
|
||||||
if( rc != SQLITE_OK ) {
|
if( rc != SQLITE_OK ) {
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for below path query.");
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for below path query.");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -507,6 +472,7 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
|||||||
|
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
|
|
||||||
|
ctx->statedb.lastReturnValue = rc;
|
||||||
do {
|
do {
|
||||||
csync_file_stat_t *st = NULL;
|
csync_file_stat_t *st = NULL;
|
||||||
|
|
||||||
@@ -522,6 +488,7 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
|||||||
}
|
}
|
||||||
} while( rc == SQLITE_ROW );
|
} while( rc == SQLITE_ROW );
|
||||||
|
|
||||||
|
ctx->statedb.lastReturnValue = rc;
|
||||||
if( rc != SQLITE_DONE ) {
|
if( rc != SQLITE_DONE ) {
|
||||||
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
|
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -98,27 +98,6 @@ int csync_statedb_get_below_path(CSYNC *ctx, const char *path);
|
|||||||
*/
|
*/
|
||||||
c_strlist_t *csync_statedb_query(sqlite3 *db, const char *statement);
|
c_strlist_t *csync_statedb_query(sqlite3 *db, const char *statement);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Insert function for the statedb.
|
|
||||||
*
|
|
||||||
* @param ctx The csync context.
|
|
||||||
* @param statement The SQL statement to insert into the statedb.
|
|
||||||
*
|
|
||||||
* @return The rowid of the most recent INSERT on success, 0 if the query
|
|
||||||
* wasn't successful.
|
|
||||||
*/
|
|
||||||
typedef struct csync_progressinfo_s {
|
|
||||||
struct csync_progressinfo_s *next;
|
|
||||||
uint64_t phash;
|
|
||||||
uint64_t modtime;
|
|
||||||
char *md5;
|
|
||||||
int error;
|
|
||||||
int chunk;
|
|
||||||
int transferId;
|
|
||||||
char *tmpfile;
|
|
||||||
char *error_string;
|
|
||||||
} csync_progressinfo_t;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -100,6 +100,10 @@ static bool _csync_sameextension(const char *p1, const char *p2) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool _last_db_return_error(CSYNC* ctx) {
|
||||||
|
return ctx->statedb.lastReturnValue != SQLITE_OK && ctx->statedb.lastReturnValue != SQLITE_DONE && ctx->statedb.lastReturnValue != SQLITE_ROW;
|
||||||
|
}
|
||||||
|
|
||||||
static int _csync_detect_update(CSYNC *ctx, const char *file,
|
static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||||
const csync_vio_file_stat_t *fs, const int type) {
|
const csync_vio_file_stat_t *fs, const int type) {
|
||||||
uint64_t h = 0;
|
uint64_t h = 0;
|
||||||
@@ -157,8 +161,8 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->current == REMOTE_REPLICA && ctx->checkBlackListHook) {
|
if (ctx->current == REMOTE_REPLICA && ctx->checkSelectiveSyncBlackListHook) {
|
||||||
if (ctx->checkBlackListHook(ctx->checkBlackListData, path)) {
|
if (ctx->checkSelectiveSyncBlackListHook(ctx->checkSelectiveSyncBlackListData, path)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,8 +194,15 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fs->mtime == 0) {
|
if (fs->mtime == 0) {
|
||||||
tmp = csync_statedb_get_stat_by_hash(ctx, h);
|
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s - mtime is zero!", path);
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s - mtime is zero!", path);
|
||||||
|
|
||||||
|
tmp = csync_statedb_get_stat_by_hash(ctx, h);
|
||||||
|
if(_last_db_return_error(ctx)) {
|
||||||
|
SAFE_FREE(st);
|
||||||
|
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s - not found in db, IGNORE!", path);
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s - not found in db, IGNORE!", path);
|
||||||
st->instruction = CSYNC_INSTRUCTION_IGNORE;
|
st->instruction = CSYNC_INSTRUCTION_IGNORE;
|
||||||
@@ -228,10 +239,20 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
|||||||
if (csync_get_statedb_exists(ctx)) {
|
if (csync_get_statedb_exists(ctx)) {
|
||||||
tmp = csync_statedb_get_stat_by_hash(ctx, h);
|
tmp = csync_statedb_get_stat_by_hash(ctx, h);
|
||||||
|
|
||||||
|
if(_last_db_return_error(ctx)) {
|
||||||
|
SAFE_FREE(st);
|
||||||
|
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if(tmp && tmp->phash == h ) { /* there is an entry in the database */
|
if(tmp && tmp->phash == h ) { /* there is an entry in the database */
|
||||||
/* we have an update! */
|
/* we have an update! */
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Database entry found, compare: %" PRId64 " <-> %" PRId64 ", etag: %s <-> %s, inode: %" PRId64 " <-> %" PRId64 ", size: %" PRId64 " <-> %" PRId64,
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Database entry found, compare: %" PRId64 " <-> %" PRId64
|
||||||
((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);
|
", etag: %s <-> %s, inode: %" PRId64 " <-> %" PRId64
|
||||||
|
", size: %" PRId64 " <-> %" PRId64 ", perms: %s <-> %s",
|
||||||
|
((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 );
|
||||||
if( !fs->etag) {
|
if( !fs->etag) {
|
||||||
st->instruction = CSYNC_INSTRUCTION_EVAL;
|
st->instruction = CSYNC_INSTRUCTION_EVAL;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -289,6 +310,12 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
|||||||
|
|
||||||
tmp = csync_statedb_get_stat_by_inode(ctx, fs->inode);
|
tmp = csync_statedb_get_stat_by_inode(ctx, fs->inode);
|
||||||
|
|
||||||
|
if(_last_db_return_error(ctx)) {
|
||||||
|
SAFE_FREE(st);
|
||||||
|
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* translate the file type between the two stat types csync has. */
|
/* translate the file type between the two stat types csync has. */
|
||||||
if( tmp && tmp->type == 0 ) {
|
if( tmp && tmp->type == 0 ) {
|
||||||
tmp_vio_type = CSYNC_VIO_FILE_TYPE_REGULAR;
|
tmp_vio_type = CSYNC_VIO_FILE_TYPE_REGULAR;
|
||||||
@@ -319,6 +346,12 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
|||||||
} else {
|
} else {
|
||||||
/* Remote Replica Rename check */
|
/* Remote Replica Rename check */
|
||||||
tmp = csync_statedb_get_stat_by_file_id(ctx, fs->file_id);
|
tmp = csync_statedb_get_stat_by_file_id(ctx, fs->file_id);
|
||||||
|
|
||||||
|
if(_last_db_return_error(ctx)) {
|
||||||
|
SAFE_FREE(st);
|
||||||
|
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if(tmp ) { /* tmp existing at all */
|
if(tmp ) { /* tmp existing at all */
|
||||||
if ((tmp->type == CSYNC_FTW_TYPE_DIR && fs->type != CSYNC_VIO_FILE_TYPE_DIRECTORY) ||
|
if ((tmp->type == CSYNC_FTW_TYPE_DIR && fs->type != CSYNC_VIO_FILE_TYPE_DIRECTORY) ||
|
||||||
(tmp->type == CSYNC_FTW_TYPE_FILE && fs->type != CSYNC_VIO_FILE_TYPE_REGULAR)) {
|
(tmp->type == CSYNC_FTW_TYPE_FILE && fs->type != CSYNC_VIO_FILE_TYPE_REGULAR)) {
|
||||||
@@ -346,8 +379,9 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Unable to open statedb, setting inst to NEW" );
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Unable to open statedb" );
|
||||||
st->instruction = CSYNC_INSTRUCTION_NEW;
|
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@@ -547,6 +581,17 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
|||||||
if (asp < 0) {
|
if (asp < 0) {
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "asprintf failed!");
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "asprintf failed!");
|
||||||
}
|
}
|
||||||
|
} else if(errno == ERRNO_SERVICE_UNAVAILABLE) {
|
||||||
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Service was not available!");
|
||||||
|
if (ctx->current_fs) {
|
||||||
|
ctx->current_fs->instruction = CSYNC_INSTRUCTION_IGNORE;
|
||||||
|
ctx->current_fs->error_status = CSYNC_STATUS_SERVICE_UNAVAILABLE;
|
||||||
|
/* 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 {
|
} else {
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "opendir failed for %s - errno %d", uri, errno);
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "opendir failed for %s - errno %d", uri, errno);
|
||||||
}
|
}
|
||||||
@@ -603,10 +648,13 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
|||||||
path = filename + ulen;
|
path = filename + ulen;
|
||||||
|
|
||||||
/* skip ".csync_journal.db" and ".csync_journal.db.ctmp" */
|
/* skip ".csync_journal.db" and ".csync_journal.db.ctmp" */
|
||||||
|
/* Isn't this done via csync_exclude already? */
|
||||||
if (c_streq(path, ".csync_journal.db")
|
if (c_streq(path, ".csync_journal.db")
|
||||||
|| c_streq(path, ".csync_journal.db.ctmp")
|
|| c_streq(path, ".csync_journal.db.ctmp")
|
||||||
|| c_streq(path, ".csync_journal.db.ctmp-journal")
|
|| c_streq(path, ".csync_journal.db.ctmp-journal")
|
||||||
|| c_streq(path, ".csync-progressdatabase")) {
|
|| c_streq(path, ".csync-progressdatabase")
|
||||||
|
|| c_streq(path, ".csync_journal.db-shm")
|
||||||
|
|| c_streq(path, ".csync_journal.db-wal")) {
|
||||||
csync_vio_file_stat_destroy(dirent);
|
csync_vio_file_stat_destroy(dirent);
|
||||||
dirent = NULL;
|
dirent = NULL;
|
||||||
SAFE_FREE(filename);
|
SAFE_FREE(filename);
|
||||||
@@ -652,6 +700,11 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
|||||||
uint64_t h = c_jhash64((uint8_t *) path, len, 0);
|
uint64_t h = c_jhash64((uint8_t *) path, len, 0);
|
||||||
etag = csync_statedb_get_etag( ctx, h );
|
etag = csync_statedb_get_etag( ctx, h );
|
||||||
|
|
||||||
|
if(_last_db_return_error(ctx)) {
|
||||||
|
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
if( etag ) {
|
if( etag ) {
|
||||||
SAFE_FREE(fs->etag);
|
SAFE_FREE(fs->etag);
|
||||||
fs->etag = etag;
|
fs->etag = etag;
|
||||||
@@ -671,11 +724,6 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
|||||||
rc = fn(ctx, filename, fs, flag);
|
rc = fn(ctx, filename, fs, flag);
|
||||||
/* this function may update ctx->current and ctx->read_from_db */
|
/* this function may update ctx->current and ctx->read_from_db */
|
||||||
|
|
||||||
if (ctx->current_fs && previous_fs && ctx->current_fs->child_modified) {
|
|
||||||
/* If a directory has modified files, put the flag on the parent directory as well */
|
|
||||||
previous_fs->child_modified = ctx->current_fs->child_modified;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Only for the local replica we have to destroy stat(), for the remote one it is a pointer to dirent */
|
/* 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) {
|
if (ctx->replica == LOCAL_REPLICA) {
|
||||||
csync_vio_file_stat_destroy(fs);
|
csync_vio_file_stat_destroy(fs);
|
||||||
@@ -710,6 +758,11 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctx->current_fs && previous_fs && ctx->current_fs->child_modified) {
|
||||||
|
/* If a directory has modified files, put the flag on the parent directory as well */
|
||||||
|
previous_fs->child_modified = ctx->current_fs->child_modified;
|
||||||
|
}
|
||||||
|
|
||||||
if (flag == CSYNC_FTW_FLAG_DIR && ctx->current_fs
|
if (flag == CSYNC_FTW_FLAG_DIR && ctx->current_fs
|
||||||
&& (ctx->current_fs->instruction == CSYNC_INSTRUCTION_EVAL ||
|
&& (ctx->current_fs->instruction == CSYNC_INSTRUCTION_EVAL ||
|
||||||
ctx->current_fs->instruction == CSYNC_INSTRUCTION_NEW)) {
|
ctx->current_fs->instruction == CSYNC_INSTRUCTION_NEW)) {
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ hbf_transfer_t *hbf_init_transfer( const char *dest_uri ) {
|
|||||||
transfer->block_size = DEFAULT_BLOCK_SIZE;
|
transfer->block_size = DEFAULT_BLOCK_SIZE;
|
||||||
transfer->threshold = transfer->block_size;
|
transfer->threshold = transfer->block_size;
|
||||||
transfer->modtime_accepted = 0;
|
transfer->modtime_accepted = 0;
|
||||||
|
transfer->oc_header_modtime = 0;
|
||||||
|
|
||||||
return transfer;
|
return transfer;
|
||||||
}
|
}
|
||||||
@@ -491,8 +492,8 @@ Hbf_State hbf_transfer( ne_session *session, hbf_transfer_t *transfer, const cha
|
|||||||
|
|
||||||
snprintf(buf, sizeof(buf), "%"PRId64, transfer->stat_size);
|
snprintf(buf, sizeof(buf), "%"PRId64, transfer->stat_size);
|
||||||
ne_add_request_header(req, "OC-Total-Length", buf);
|
ne_add_request_header(req, "OC-Total-Length", buf);
|
||||||
if( transfer->modtime > 0 ) {
|
if( transfer->oc_header_modtime > 0 ) {
|
||||||
snprintf(buf, sizeof(buf), "%"PRId64, transfer->modtime);
|
snprintf(buf, sizeof(buf), "%"PRId64, transfer->oc_header_modtime);
|
||||||
ne_add_request_header(req, "X-OC-Mtime", buf);
|
ne_add_request_header(req, "X-OC-Mtime", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ struct hbf_transfer_s {
|
|||||||
|
|
||||||
int64_t stat_size;
|
int64_t stat_size;
|
||||||
time_t modtime;
|
time_t modtime;
|
||||||
|
time_t oc_header_modtime;
|
||||||
int64_t block_size;
|
int64_t block_size;
|
||||||
int64_t threshold;
|
int64_t threshold;
|
||||||
|
|
||||||
|
|||||||
@@ -134,6 +134,14 @@ static char *c_iconv(const char* str, enum iconv_direction dir)
|
|||||||
}
|
}
|
||||||
#endif /* defined(HAVE_ICONV) && defined(WITH_ICONV) */
|
#endif /* defined(HAVE_ICONV) && defined(WITH_ICONV) */
|
||||||
|
|
||||||
|
int c_strncasecmp(const char *a, const char *b, size_t n) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
return _strnicmp(a, b, n);
|
||||||
|
#else
|
||||||
|
return strncasecmp(a, b, n);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int c_streq(const char *a, const char *b) {
|
int c_streq(const char *a, const char *b) {
|
||||||
register const char *s1 = a;
|
register const char *s1 = a;
|
||||||
register const char *s2 = b;
|
register const char *s2 = b;
|
||||||
|
|||||||
@@ -59,6 +59,17 @@ struct c_strlist_s {
|
|||||||
size_t size;
|
size_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compare to strings case insensitively.
|
||||||
|
*
|
||||||
|
* @param a First string to compare.
|
||||||
|
* @param b Second string to compare.
|
||||||
|
* @param n Max comparison length.
|
||||||
|
*
|
||||||
|
* @return see strncasecmp
|
||||||
|
*/
|
||||||
|
int c_strncasecmp(const char *a, const char *b, size_t n);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Compare to strings if they are equal.
|
* @brief Compare to strings if they are equal.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -174,6 +174,25 @@ static void check_csync_pathes(void **state)
|
|||||||
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void check_csync_is_windows_reserved_word() {
|
||||||
|
assert_true(csync_is_windows_reserved_word("CON"));
|
||||||
|
assert_true(csync_is_windows_reserved_word("con"));
|
||||||
|
assert_true(csync_is_windows_reserved_word("CON."));
|
||||||
|
assert_true(csync_is_windows_reserved_word("con."));
|
||||||
|
assert_true(csync_is_windows_reserved_word("CON.ference"));
|
||||||
|
assert_false(csync_is_windows_reserved_word("CONference"));
|
||||||
|
assert_false(csync_is_windows_reserved_word("conference"));
|
||||||
|
assert_false(csync_is_windows_reserved_word("conf.erence"));
|
||||||
|
assert_false(csync_is_windows_reserved_word("co"));
|
||||||
|
assert_true(csync_is_windows_reserved_word("A:"));
|
||||||
|
assert_true(csync_is_windows_reserved_word("a:"));
|
||||||
|
assert_true(csync_is_windows_reserved_word("z:"));
|
||||||
|
assert_true(csync_is_windows_reserved_word("Z:"));
|
||||||
|
assert_true(csync_is_windows_reserved_word("M:"));
|
||||||
|
assert_true(csync_is_windows_reserved_word("m:"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int torture_run_tests(void)
|
int torture_run_tests(void)
|
||||||
{
|
{
|
||||||
const UnitTest tests[] = {
|
const UnitTest tests[] = {
|
||||||
@@ -181,6 +200,7 @@ int torture_run_tests(void)
|
|||||||
unit_test_setup_teardown(check_csync_exclude_load, 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, setup_init, teardown),
|
||||||
unit_test_setup_teardown(check_csync_pathes, 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),
|
||||||
};
|
};
|
||||||
|
|
||||||
return run_tests(tests);
|
return run_tests(tests);
|
||||||
|
|||||||
@@ -42,6 +42,13 @@ static void setup(void **state) {
|
|||||||
|
|
||||||
csync->statedb.file = c_strdup( TESTDB );
|
csync->statedb.file = c_strdup( TESTDB );
|
||||||
*state = csync;
|
*state = csync;
|
||||||
|
|
||||||
|
sqlite3 *db = NULL;
|
||||||
|
rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
|
||||||
|
assert_int_equal(rc, SQLITE_OK);
|
||||||
|
|
||||||
|
rc = sqlite3_close(db);
|
||||||
|
assert_int_equal(rc, SQLITE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void teardown(void **state) {
|
static void teardown(void **state) {
|
||||||
@@ -57,37 +64,6 @@ static void teardown(void **state) {
|
|||||||
*state = NULL;
|
*state = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_csync_statedb_check(void **state)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
(void) state; /* unused */
|
|
||||||
|
|
||||||
rc = system("mkdir -p /tmp/check_csync1");
|
|
||||||
|
|
||||||
/* old db */
|
|
||||||
rc = system("echo \"SQLite format 2\" > /tmp/check_csync1/test.db");
|
|
||||||
assert_int_equal(rc, 0);
|
|
||||||
rc = _csync_statedb_check(TESTDB);
|
|
||||||
assert_int_equal(rc, 1);
|
|
||||||
|
|
||||||
/* db already exists */
|
|
||||||
rc = _csync_statedb_check(TESTDB);
|
|
||||||
assert_int_equal(rc, 1);
|
|
||||||
|
|
||||||
/* no db exists */
|
|
||||||
rc = system("rm -f /tmp/check_csync1/test.db");
|
|
||||||
assert_int_equal(rc, 0);
|
|
||||||
rc = _csync_statedb_check(TESTDB);
|
|
||||||
assert_int_equal(rc, 1);
|
|
||||||
|
|
||||||
rc = _csync_statedb_check("/tmp/check_csync1/");
|
|
||||||
assert_int_equal(rc, -1);
|
|
||||||
|
|
||||||
rc = system("rm -rf /tmp/check_csync1");
|
|
||||||
assert_int_equal(rc, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void check_csync_statedb_load(void **state)
|
static void check_csync_statedb_load(void **state)
|
||||||
{
|
{
|
||||||
CSYNC *csync = *state;
|
CSYNC *csync = *state;
|
||||||
@@ -143,7 +119,6 @@ static void check_csync_statedb_close(void **state)
|
|||||||
int torture_run_tests(void)
|
int torture_run_tests(void)
|
||||||
{
|
{
|
||||||
const UnitTest tests[] = {
|
const UnitTest tests[] = {
|
||||||
unit_test_setup_teardown(check_csync_statedb_check, setup, teardown),
|
|
||||||
unit_test_setup_teardown(check_csync_statedb_load, setup, teardown),
|
unit_test_setup_teardown(check_csync_statedb_load, setup, teardown),
|
||||||
unit_test_setup_teardown(check_csync_statedb_close, setup, teardown),
|
unit_test_setup_teardown(check_csync_statedb_close, setup, teardown),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -47,6 +47,12 @@ static void setup(void **state)
|
|||||||
rc = csync_init(csync);
|
rc = csync_init(csync);
|
||||||
assert_int_equal(rc, 0);
|
assert_int_equal(rc, 0);
|
||||||
|
|
||||||
|
sqlite3 *db = NULL;
|
||||||
|
rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
|
||||||
|
assert_int_equal(rc, SQLITE_OK);
|
||||||
|
rc = sqlite3_close(db);
|
||||||
|
assert_int_equal(rc, SQLITE_OK);
|
||||||
|
|
||||||
rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
|
rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
|
||||||
assert_int_equal(rc, 0);
|
assert_int_equal(rc, 0);
|
||||||
|
|
||||||
@@ -55,19 +61,11 @@ static void setup(void **state)
|
|||||||
|
|
||||||
static void setup_db(void **state)
|
static void setup_db(void **state)
|
||||||
{
|
{
|
||||||
CSYNC *csync;
|
char *errmsg;
|
||||||
char *stmt = NULL;
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
c_strlist_t *result = NULL;
|
sqlite3 *db = NULL;
|
||||||
|
|
||||||
setup(state);
|
const char *sql = "CREATE TABLE IF NOT EXISTS metadata ("
|
||||||
csync = *state;
|
|
||||||
|
|
||||||
// rc = csync_statedb_create_tables(csync->statedb.db);
|
|
||||||
assert_int_equal(rc, 0);
|
|
||||||
|
|
||||||
result = csync_statedb_query(csync->statedb.db,
|
|
||||||
"CREATE TABLE IF NOT EXISTS metadata ("
|
|
||||||
"phash INTEGER(8),"
|
"phash INTEGER(8),"
|
||||||
"pathlen INTEGER,"
|
"pathlen INTEGER,"
|
||||||
"path VARCHAR(4096),"
|
"path VARCHAR(4096),"
|
||||||
@@ -79,29 +77,25 @@ static void setup_db(void **state)
|
|||||||
"type INTEGER,"
|
"type INTEGER,"
|
||||||
"md5 VARCHAR(32),"
|
"md5 VARCHAR(32),"
|
||||||
"PRIMARY KEY(phash)"
|
"PRIMARY KEY(phash)"
|
||||||
");"
|
");";
|
||||||
);
|
|
||||||
|
|
||||||
assert_non_null(result);
|
const char *sql2 = "INSERT INTO metadata"
|
||||||
c_strlist_destroy(result);
|
|
||||||
|
|
||||||
|
|
||||||
stmt = sqlite3_mprintf("INSERT INTO metadata"
|
|
||||||
"(phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5) VALUES"
|
"(phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5) VALUES"
|
||||||
"(%lu, %d, '%q', %d, %d, %d, %d, %lu, %d, %lu);",
|
"(42, 42, 'Its funny stuff', 23, 42, 43, 55, 66, 2, 54);";
|
||||||
42,
|
|
||||||
42,
|
|
||||||
"It's a rainy day",
|
setup(state);
|
||||||
23,
|
rc = sqlite3_open( TESTDB, &db);
|
||||||
42,
|
assert_int_equal(rc, SQLITE_OK);
|
||||||
42,
|
|
||||||
42,
|
rc = sqlite3_exec( db, sql, NULL, NULL, &errmsg );
|
||||||
42,
|
assert_int_equal(rc, SQLITE_OK);
|
||||||
2,
|
|
||||||
43);
|
rc = sqlite3_exec( db, sql2, NULL, NULL, &errmsg );
|
||||||
|
assert_int_equal(rc, SQLITE_OK);
|
||||||
|
|
||||||
|
sqlite3_close(db);
|
||||||
|
|
||||||
// rc = csync_statedb_insert(csync->statedb.db, stmt);
|
|
||||||
sqlite3_free(stmt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void teardown(void **state) {
|
static void teardown(void **state) {
|
||||||
@@ -139,41 +133,6 @@ static void check_csync_statedb_query_statement(void **state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_csync_statedb_create_error(void **state)
|
|
||||||
{
|
|
||||||
CSYNC *csync = *state;
|
|
||||||
c_strlist_t *result;
|
|
||||||
|
|
||||||
result = csync_statedb_query(csync->statedb.db, "CREATE TABLE test(phash INTEGER, text VARCHAR(10));");
|
|
||||||
assert_non_null(result);
|
|
||||||
c_strlist_destroy(result);
|
|
||||||
|
|
||||||
result = csync_statedb_query(csync->statedb.db, "CREATE TABLE test(phash INTEGER, text VARCHAR(10));");
|
|
||||||
assert_null(result);
|
|
||||||
|
|
||||||
c_strlist_destroy(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void check_csync_statedb_insert_statement(void **state)
|
|
||||||
{
|
|
||||||
CSYNC *csync = *state;
|
|
||||||
c_strlist_t *result;
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
result = csync_statedb_query(csync->statedb.db, "CREATE TABLE test(phash INTEGER, text VARCHAR(10));");
|
|
||||||
assert_non_null(result);
|
|
||||||
c_strlist_destroy(result);
|
|
||||||
|
|
||||||
// rc = csync_statedb_insert(csync->statedb.db, "INSERT;");
|
|
||||||
assert_int_equal(rc, 0);
|
|
||||||
// rc = csync_statedb_insert(csync->statedb.db, "INSERT");
|
|
||||||
assert_int_equal(rc, 0);
|
|
||||||
// rc = csync_statedb_insert(csync->statedb.db, "");
|
|
||||||
assert_int_equal(rc, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void check_csync_statedb_drop_tables(void **state)
|
static void check_csync_statedb_drop_tables(void **state)
|
||||||
{
|
{
|
||||||
// CSYNC *csync = *state;
|
// CSYNC *csync = *state;
|
||||||
@@ -255,8 +214,6 @@ int torture_run_tests(void)
|
|||||||
{
|
{
|
||||||
const UnitTest tests[] = {
|
const UnitTest tests[] = {
|
||||||
unit_test_setup_teardown(check_csync_statedb_query_statement, setup, teardown),
|
unit_test_setup_teardown(check_csync_statedb_query_statement, setup, teardown),
|
||||||
unit_test_setup_teardown(check_csync_statedb_create_error, setup, teardown),
|
|
||||||
unit_test_setup_teardown(check_csync_statedb_insert_statement, setup, teardown),
|
|
||||||
unit_test_setup_teardown(check_csync_statedb_drop_tables, setup, teardown),
|
unit_test_setup_teardown(check_csync_statedb_drop_tables, setup, teardown),
|
||||||
unit_test_setup_teardown(check_csync_statedb_insert_metadata, setup, teardown),
|
unit_test_setup_teardown(check_csync_statedb_insert_metadata, setup, teardown),
|
||||||
unit_test_setup_teardown(check_csync_statedb_write, setup, teardown),
|
unit_test_setup_teardown(check_csync_statedb_write, setup, teardown),
|
||||||
|
|||||||
@@ -23,11 +23,64 @@
|
|||||||
|
|
||||||
#define TESTDB "/tmp/check_csync/journal.db"
|
#define TESTDB "/tmp/check_csync/journal.db"
|
||||||
|
|
||||||
|
static int firstrun = 1;
|
||||||
|
|
||||||
|
static void statedb_create_metadata_table(sqlite3 *db)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if( db ) {
|
||||||
|
const char *sql = "CREATE TABLE IF NOT EXISTS metadata("
|
||||||
|
"phash INTEGER(8),"
|
||||||
|
"pathlen INTEGER,"
|
||||||
|
"path VARCHAR(4096),"
|
||||||
|
"inode INTEGER,"
|
||||||
|
"uid INTEGER,"
|
||||||
|
"gid INTEGER,"
|
||||||
|
"mode INTEGER,"
|
||||||
|
"modtime INTEGER(8),"
|
||||||
|
"type INTEGER,"
|
||||||
|
"md5 VARCHAR(32),"
|
||||||
|
"PRIMARY KEY(phash));";
|
||||||
|
|
||||||
|
rc = sqlite3_exec(db, sql, NULL, NULL, NULL);
|
||||||
|
const char *msg = sqlite3_errmsg(db);
|
||||||
|
assert_int_equal( rc, SQLITE_OK );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void statedb_insert_metadata(sqlite3 *db)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if( db ) {
|
||||||
|
char *stmt = sqlite3_mprintf("INSERT INTO metadata"
|
||||||
|
"(phash, pathlen, path, inode, uid, gid, mode, modtime,type,md5) VALUES"
|
||||||
|
"(%lld, %d, '%q', %d, %d, %d, %d, %lld, %d, '%q');",
|
||||||
|
(long long signed int)42,
|
||||||
|
42,
|
||||||
|
"I_was_wurst_before_I_became_wurstsalat",
|
||||||
|
619070,
|
||||||
|
42,
|
||||||
|
42,
|
||||||
|
42,
|
||||||
|
(long long signed int)42,
|
||||||
|
0,
|
||||||
|
"4711");
|
||||||
|
|
||||||
|
char *errmsg;
|
||||||
|
rc = sqlite3_exec(db, stmt, NULL, NULL, &errmsg);
|
||||||
|
sqlite3_free(stmt);
|
||||||
|
assert_int_equal( rc, SQLITE_OK );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void setup(void **state)
|
static void setup(void **state)
|
||||||
{
|
{
|
||||||
CSYNC *csync;
|
CSYNC *csync;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
unlink(TESTDB);
|
||||||
rc = system("mkdir -p /tmp/check_csync");
|
rc = system("mkdir -p /tmp/check_csync");
|
||||||
assert_int_equal(rc, 0);
|
assert_int_equal(rc, 0);
|
||||||
rc = system("mkdir -p /tmp/check_csync1");
|
rc = system("mkdir -p /tmp/check_csync1");
|
||||||
@@ -38,10 +91,21 @@ static void setup(void **state)
|
|||||||
assert_int_equal(rc, 0);
|
assert_int_equal(rc, 0);
|
||||||
rc = csync_init(csync);
|
rc = csync_init(csync);
|
||||||
assert_int_equal(rc, 0);
|
assert_int_equal(rc, 0);
|
||||||
|
|
||||||
|
/* Create a new db with metadata */
|
||||||
|
sqlite3 *db;
|
||||||
|
csync->statedb.file = c_strdup(TESTDB);
|
||||||
|
rc = sqlite3_open(csync->statedb.file, &db);
|
||||||
|
statedb_create_metadata_table(db);
|
||||||
|
if( firstrun ) {
|
||||||
|
statedb_insert_metadata(db);
|
||||||
|
firstrun = 0;
|
||||||
|
}
|
||||||
|
sqlite3_close(db);
|
||||||
|
|
||||||
rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
|
rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
|
||||||
assert_int_equal(rc, 0);
|
assert_int_equal(rc, 0);
|
||||||
|
|
||||||
|
|
||||||
*state = csync;
|
*state = csync;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,9 +124,18 @@ static void setup_ftw(void **state)
|
|||||||
assert_int_equal(rc, 0);
|
assert_int_equal(rc, 0);
|
||||||
rc = csync_init(csync);
|
rc = csync_init(csync);
|
||||||
assert_int_equal(rc, 0);
|
assert_int_equal(rc, 0);
|
||||||
|
|
||||||
|
sqlite3 *db = NULL;
|
||||||
|
rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
|
||||||
|
assert_int_equal(rc, SQLITE_OK);
|
||||||
|
statedb_create_metadata_table(db);
|
||||||
|
rc = sqlite3_close(db);
|
||||||
|
assert_int_equal(rc, SQLITE_OK);
|
||||||
|
|
||||||
rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
|
rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
|
||||||
assert_int_equal(rc, 0);
|
assert_int_equal(rc, 0);
|
||||||
|
|
||||||
|
csync->statedb.file = c_strdup( TESTDB );
|
||||||
*state = csync;
|
*state = csync;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,6 +144,7 @@ static void teardown(void **state)
|
|||||||
CSYNC *csync = *state;
|
CSYNC *csync = *state;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
unlink( csync->statedb.file);
|
||||||
rc = csync_destroy(csync);
|
rc = csync_destroy(csync);
|
||||||
assert_int_equal(rc, 0);
|
assert_int_equal(rc, 0);
|
||||||
|
|
||||||
@@ -249,6 +323,7 @@ static void check_csync_detect_update_db_eval(void **state)
|
|||||||
csync_vio_file_stat_destroy(fs);
|
csync_vio_file_stat_destroy(fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void check_csync_detect_update_db_rename(void **state)
|
static void check_csync_detect_update_db_rename(void **state)
|
||||||
{
|
{
|
||||||
CSYNC *csync = *state;
|
CSYNC *csync = *state;
|
||||||
@@ -256,27 +331,6 @@ static void check_csync_detect_update_db_rename(void **state)
|
|||||||
|
|
||||||
csync_vio_file_stat_t *fs;
|
csync_vio_file_stat_t *fs;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
char *stmt = NULL;
|
|
||||||
|
|
||||||
// rc = csync_statedb_create_tables(csync->statedb.db);
|
|
||||||
|
|
||||||
assert_int_equal(rc, 0);
|
|
||||||
stmt = sqlite3_mprintf("INSERT INTO metadata"
|
|
||||||
"(phash, pathlen, path, inode, uid, gid, mode, modtime,type,md5) VALUES"
|
|
||||||
"(%lld, %d, '%q', %d, %d, %d, %d, %lld, %d, '%q');",
|
|
||||||
(long long signed int)42,
|
|
||||||
42,
|
|
||||||
"I_was_wurst_before_I_became_wurstsalat",
|
|
||||||
619070,
|
|
||||||
42,
|
|
||||||
42,
|
|
||||||
42,
|
|
||||||
(long long signed int)42,
|
|
||||||
0,
|
|
||||||
"4711");
|
|
||||||
|
|
||||||
// rc = csync_statedb_insert(csync->statedb.db, stmt);
|
|
||||||
sqlite3_free(stmt);
|
|
||||||
|
|
||||||
fs = create_fstat("wurst.txt", 0, 1, 42);
|
fs = create_fstat("wurst.txt", 0, 1, 42);
|
||||||
assert_non_null(fs);
|
assert_non_null(fs);
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ our %config;
|
|||||||
|
|
||||||
@ISA = qw(Exporter);
|
@ISA = qw(Exporter);
|
||||||
@EXPORT = qw( initTesting createRemoteDir removeRemoteDir createLocalDir cleanup csync
|
@EXPORT = qw( initTesting createRemoteDir removeRemoteDir createLocalDir cleanup csync
|
||||||
assertLocalDirs assertLocalAndRemoteDir glob_put put_to_dir
|
assertLocalDirs assertLocalAndRemoteDir glob_put put_to_dir
|
||||||
putToDirLWP localDir remoteDir localCleanup createLocalFile md5OfFile
|
putToDirLWP localDir remoteDir localCleanup createLocalFile md5OfFile
|
||||||
remoteCleanup server initLocalDir initRemoteDir moveRemoteFile
|
remoteCleanup server initLocalDir initRemoteDir moveRemoteFile
|
||||||
printInfo remoteFileId createShare removeShare assert
|
printInfo remoteFileId createShare removeShare assert
|
||||||
@@ -73,12 +73,12 @@ sub server
|
|||||||
{
|
{
|
||||||
return $owncloud;
|
return $owncloud;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub fromFileName($)
|
sub fromFileName($)
|
||||||
{
|
{
|
||||||
my ($file) = @_;
|
my ($file) = @_;
|
||||||
if ( $^O eq "darwin" ) {
|
if ( $^O eq "darwin" ) {
|
||||||
my $fromFileName = NFC( Encode::decode('utf-8', $file) );
|
my $fromFileName = NFC( Encode::decode('utf-8', $file) );
|
||||||
return $fromFileName;
|
return $fromFileName;
|
||||||
} else {
|
} else {
|
||||||
return $file;
|
return $file;
|
||||||
@@ -89,7 +89,7 @@ sub fromFileName($)
|
|||||||
sub initTesting(;$)
|
sub initTesting(;$)
|
||||||
{
|
{
|
||||||
my ($prefix) = @_;
|
my ($prefix) = @_;
|
||||||
|
|
||||||
my $cfgFile = "./t1.cfg";
|
my $cfgFile = "./t1.cfg";
|
||||||
$cfgFile = "/etc/ownCloud/t1.cfg" if( -r "/etc/ownCloud/t1.cfg" );
|
$cfgFile = "/etc/ownCloud/t1.cfg" if( -r "/etc/ownCloud/t1.cfg" );
|
||||||
|
|
||||||
@@ -115,6 +115,8 @@ sub initTesting(;$)
|
|||||||
|
|
||||||
$owncloud .= "/" unless( $owncloud =~ /\/$/ );
|
$owncloud .= "/" unless( $owncloud =~ /\/$/ );
|
||||||
|
|
||||||
|
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
|
||||||
|
|
||||||
print "Connecting to ownCloud at ". $owncloud ."\n";
|
print "Connecting to ownCloud at ". $owncloud ."\n";
|
||||||
|
|
||||||
# For SSL set the environment variable needed by the LWP module for SSL
|
# For SSL set the environment variable needed by the LWP module for SSL
|
||||||
@@ -129,15 +131,15 @@ sub initTesting(;$)
|
|||||||
-pass=> $passwd );
|
-pass=> $passwd );
|
||||||
# $d->DebugLevel(3);
|
# $d->DebugLevel(3);
|
||||||
$prefix = "t1" unless( defined $prefix );
|
$prefix = "t1" unless( defined $prefix );
|
||||||
|
|
||||||
my $dirId = sprintf("%02d", rand(100));
|
my $dirId = sprintf("%02d", rand(100));
|
||||||
my $dateTime = strftime('%Y%m%d%H%M%S',localtime);
|
my $dateTime = strftime('%Y%m%d%H%M%S',localtime);
|
||||||
my $dir = sprintf( "%s-%s-%s/", $prefix, $dateTime, $dirId );
|
my $dir = sprintf( "%s-%s-%s/", $prefix, $dateTime, $dirId );
|
||||||
|
|
||||||
$localDir = $dir;
|
$localDir = $dir;
|
||||||
$localDir .= "/" unless( $localDir =~ /\/$/ );
|
$localDir .= "/" unless( $localDir =~ /\/$/ );
|
||||||
$remoteDir = $dir;
|
$remoteDir = $dir;
|
||||||
|
|
||||||
initRemoteDir();
|
initRemoteDir();
|
||||||
initLocalDir();
|
initLocalDir();
|
||||||
printf( "Test directory name is %s\n", $dir );
|
printf( "Test directory name is %s\n", $dir );
|
||||||
@@ -166,7 +168,9 @@ sub testDirUrl()
|
|||||||
# the global var $remoteDir;
|
# the global var $remoteDir;
|
||||||
sub initRemoteDir
|
sub initRemoteDir
|
||||||
{
|
{
|
||||||
$d->open( $owncloud );
|
$d->open( $owncloud )
|
||||||
|
or die("Couldn't open $owncloud: " .$d->message . "\n");
|
||||||
|
|
||||||
my $url = testDirUrl();
|
my $url = testDirUrl();
|
||||||
|
|
||||||
my $re = $d->mkcol( $url );
|
my $re = $d->mkcol( $url );
|
||||||
@@ -204,7 +208,7 @@ sub removeRemoteDir($;$)
|
|||||||
if( $re == 0 ) {
|
if( $re == 0 ) {
|
||||||
print "Failed to remove directory <$url>:" . $d->message() ."\n";
|
print "Failed to remove directory <$url>:" . $d->message() ."\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
return $re;
|
return $re;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,7 +340,7 @@ sub localDir()
|
|||||||
return $localDir;
|
return $localDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub remoteDir()
|
sub remoteDir()
|
||||||
{
|
{
|
||||||
return $remoteDir;
|
return $remoteDir;
|
||||||
}
|
}
|
||||||
@@ -358,6 +362,8 @@ sub assertFile($$)
|
|||||||
}
|
}
|
||||||
my $stat_ok = stat( $localFile2 );
|
my $stat_ok = stat( $localFile2 );
|
||||||
print " *** STAT failed for $localFile2\n" unless( $stat_ok );
|
print " *** STAT failed for $localFile2\n" unless( $stat_ok );
|
||||||
|
assert($stat_ok, "Stat failed for file $localFile");
|
||||||
|
|
||||||
my @info = stat( $localFile2 );
|
my @info = stat( $localFile2 );
|
||||||
my $localModTime = $info[9];
|
my $localModTime = $info[9];
|
||||||
assert( $remoteModTime == $localModTime, "Modified-Times differ: remote: $remoteModTime <-> local: $localModTime" );
|
assert( $remoteModTime == $localModTime, "Modified-Times differ: remote: $remoteModTime <-> local: $localModTime" );
|
||||||
@@ -367,7 +373,7 @@ sub assertFile($$)
|
|||||||
my $remoteSize = $res->get_property( "getcontentlength" );
|
my $remoteSize = $res->get_property( "getcontentlength" );
|
||||||
if( $remoteSize ) { # directories do not have a contentlength
|
if( $remoteSize ) { # directories do not have a contentlength
|
||||||
print "Local versus Remote size: $localSize <-> $remoteSize\n";
|
print "Local versus Remote size: $localSize <-> $remoteSize\n";
|
||||||
assert( $localSize == $remoteSize, "File sizes differ" );
|
# assert( $localSize == $remoteSize, "File sizes differ" ); # FIXME enable this again but it causes trouble on Jenkins all the time.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,7 +387,7 @@ sub traverse( $$;$ )
|
|||||||
{
|
{
|
||||||
my ($remote, $acceptConflicts, $aurl) = @_;
|
my ($remote, $acceptConflicts, $aurl) = @_;
|
||||||
$remote .= '/' unless $remote =~ /(^|\/)$/;
|
$remote .= '/' unless $remote =~ /(^|\/)$/;
|
||||||
|
|
||||||
my $url = testDirUrl() . $remote;
|
my $url = testDirUrl() . $remote;
|
||||||
if( $aurl ) {
|
if( $aurl ) {
|
||||||
$url = $aurl . $remote;
|
$url = $aurl . $remote;
|
||||||
@@ -489,13 +495,13 @@ sub glob_put( $$;$ )
|
|||||||
print " *** Putting $lfile to $puturl\n";
|
print " *** Putting $lfile to $puturl\n";
|
||||||
# putToDirLWP( $lfile, $puturl );
|
# putToDirLWP( $lfile, $puturl );
|
||||||
put_to_dir($lfile, $puturl, $optionsRef);
|
put_to_dir($lfile, $puturl, $optionsRef);
|
||||||
|
|
||||||
# if( ! $d->put( -local=>$lfile, -url=> $puturl ) ) {
|
# if( ! $d->put( -local=>$lfile, -url=> $puturl ) ) {
|
||||||
#print " ### FAILED to put: ". $d->message . '\n';
|
#print " ### FAILED to put: ". $d->message . '\n';
|
||||||
# s}
|
# s}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,7 +531,7 @@ sub put_to_dir( $$;$ )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# The HTTP DAV module often does a PROPFIND before it really PUTs. That
|
# The HTTP DAV module often does a PROPFIND before it really PUTs. That
|
||||||
# is not neccessary if we know that the directory is really there.
|
# is not neccessary if we know that the directory is really there.
|
||||||
# Use this function in this case:
|
# Use this function in this case:
|
||||||
sub putToDirLWP($$)
|
sub putToDirLWP($$)
|
||||||
@@ -545,13 +551,13 @@ sub putToDirLWP($$)
|
|||||||
my $string = <FILE>;
|
my $string = <FILE>;
|
||||||
close FILE;
|
close FILE;
|
||||||
|
|
||||||
my $ua = LWP::UserAgent->new();
|
my $ua = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0 });
|
||||||
$ua->agent( "ownCloudTest_$localDir");
|
$ua->agent( "ownCloudTest_$localDir");
|
||||||
my $req = PUT $puturl, Content_Type => 'application/octet-stream',
|
my $req = PUT $puturl, Content_Type => 'application/octet-stream',
|
||||||
Content => $string;
|
Content => $string;
|
||||||
$req->authorization_basic($user, $passwd);
|
$req->authorization_basic($user, $passwd);
|
||||||
my $response = $ua->request($req);
|
my $response = $ua->request($req);
|
||||||
|
|
||||||
if ($response->is_success()) {
|
if ($response->is_success()) {
|
||||||
# print "OK: ", $response->content;
|
# print "OK: ", $response->content;
|
||||||
} else {
|
} else {
|
||||||
@@ -579,7 +585,7 @@ sub getToFileLWP( $$ )
|
|||||||
my $geturl = testDirUrl() . $file;
|
my $geturl = testDirUrl() . $file;
|
||||||
print "GETting $geturl to $localFile\n";
|
print "GETting $geturl to $localFile\n";
|
||||||
|
|
||||||
my $ua = LWP::UserAgent->new();
|
my $ua = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0 });
|
||||||
$ua->agent( "ownCloudTest_$localDir");
|
$ua->agent( "ownCloudTest_$localDir");
|
||||||
$ua->credentials( server(), "foo", $user, $passwd);
|
$ua->credentials( server(), "foo", $user, $passwd);
|
||||||
my $req = $ua->get($geturl, ":content_file" => $localFile);
|
my $req = $ua->get($geturl, ":content_file" => $localFile);
|
||||||
@@ -594,15 +600,15 @@ sub getToFileLWP( $$ )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub createLocalFile( $$ )
|
sub createLocalFile( $$ )
|
||||||
{
|
{
|
||||||
my ($fname, $size) = @_;
|
my ($fname, $size) = @_;
|
||||||
$size = 1024 unless( $size );
|
$size = 1024 unless( $size );
|
||||||
|
|
||||||
my $md5 = Digest::MD5->new;
|
my $md5 = Digest::MD5->new;
|
||||||
|
|
||||||
open(FILE, ">", $fname) or die "Can't open $fname for writing ($!)";
|
open(FILE, ">", $fname) or die "Can't open $fname for writing ($!)";
|
||||||
|
|
||||||
my $minimum = 32;
|
my $minimum = 32;
|
||||||
my $range = 96;
|
my $range = 96;
|
||||||
|
|
||||||
@@ -620,20 +626,20 @@ sub createLocalFile( $$ )
|
|||||||
print FILE $s;
|
print FILE $s;
|
||||||
$md5->add($s);
|
$md5->add($s);
|
||||||
close FILE;
|
close FILE;
|
||||||
return $md5->hexdigest;
|
return $md5->hexdigest;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub md5OfFile( $ )
|
sub md5OfFile( $ )
|
||||||
{
|
{
|
||||||
my ($file) = @_;
|
my ($file) = @_;
|
||||||
|
|
||||||
open FILE, "$file";
|
open FILE, "$file";
|
||||||
|
|
||||||
my $ctx = Digest::MD5->new;
|
my $ctx = Digest::MD5->new;
|
||||||
$ctx->addfile (*FILE);
|
$ctx->addfile (*FILE);
|
||||||
my $hash = $ctx->hexdigest;
|
my $hash = $ctx->hexdigest;
|
||||||
close (FILE);
|
close (FILE);
|
||||||
|
|
||||||
return $hash;
|
return $hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -647,27 +653,27 @@ sub moveRemoteFile($$;$)
|
|||||||
|
|
||||||
my $fromUrl = testDirUrl(). $from;
|
my $fromUrl = testDirUrl(). $from;
|
||||||
my $toUrl = testDirUrl() . $to;
|
my $toUrl = testDirUrl() . $to;
|
||||||
|
|
||||||
if( $no_testdir ) {
|
if( $no_testdir ) {
|
||||||
$fromUrl = $from;
|
$fromUrl = $from;
|
||||||
$toUrl = $to;
|
$toUrl = $to;
|
||||||
}
|
}
|
||||||
|
|
||||||
$d->move($fromUrl, $toUrl);
|
$d->move($fromUrl, $toUrl);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub printInfo($)
|
sub printInfo($)
|
||||||
{
|
{
|
||||||
my ($info) = @_;
|
my ($info) = @_;
|
||||||
my $tt = 6+length( $info );
|
my $tt = 6+length( $info );
|
||||||
|
|
||||||
print "#" x $tt;
|
print "#" x $tt;
|
||||||
printf( "\n# %2d. %s", $infoCnt, $info );
|
printf( "\n# %2d. %s", $infoCnt, $info );
|
||||||
print "\n" unless $info =~ /\n$/;
|
print "\n" unless $info =~ /\n$/;
|
||||||
print "#" x $tt;
|
print "#" x $tt;
|
||||||
print "\n";
|
print "\n";
|
||||||
|
|
||||||
$infoCnt++;
|
$infoCnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -718,16 +724,15 @@ sub createShare($$)
|
|||||||
my $re = $dd->mkcol( $url );
|
my $re = $dd->mkcol( $url );
|
||||||
if( $re == 0 ) {
|
if( $re == 0 ) {
|
||||||
print "Failed to create test dir $url\n";
|
print "Failed to create test dir $url\n";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
my $ua = LWP::UserAgent->new();
|
my $ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 0 } );
|
||||||
$ua->agent( "ownCloudTest_sharing");
|
$ua->agent( "ownCloudTest_sharing");
|
||||||
# http://localhost/ocm/ocs/v1.php/apps/files_sharing/api/v1/shares
|
# http://localhost/ocm/ocs/v1.php/apps/files_sharing/api/v1/shares
|
||||||
my $puturl = $ocs_url . "apps/files_sharing/api/v1/shares";
|
my $puturl = $ocs_url . "apps/files_sharing/api/v1/shares";
|
||||||
|
|
||||||
my $string = "path=$dir&shareType=0&shareWith=$user&publicUpload=false&permissions=$readWrite";
|
my $string = "path=$dir&shareType=0&shareWith=$user&publicUpload=false&permissions=$readWrite";
|
||||||
print ">>>>>>>>>> $string\n";
|
print ">>>>>>>>>> $puturl $string\n";
|
||||||
|
|
||||||
my $req = POST $puturl, Content => $string;
|
my $req = POST $puturl, Content => $string;
|
||||||
$req->authorization_basic($share_user, $share_passwd);
|
$req->authorization_basic($share_user, $share_passwd);
|
||||||
@@ -757,17 +762,16 @@ sub removeShare($$)
|
|||||||
-pass => $share_passwd );
|
-pass => $share_passwd );
|
||||||
$dd->open( $owncloud);
|
$dd->open( $owncloud);
|
||||||
|
|
||||||
my $ua = LWP::UserAgent->new();
|
my $ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 0 });
|
||||||
$ua->agent( "ownCloudTest_sharing");
|
$ua->agent( "ownCloudTest_sharing");
|
||||||
# http://localhost/ocm/ocs/v1.php/apps/files_sharing/api/v1/shares
|
|
||||||
my $url = $ocs_url . "apps/files_sharing/api/v1/shares/" . $shareId;
|
my $url = $ocs_url . "ocs/v1.php/apps/files_sharing/api/v1/shares/" . $shareId;
|
||||||
|
|
||||||
my $req = DELETE $url;
|
my $req = DELETE $url;
|
||||||
$req->authorization_basic($share_user, $share_passwd);
|
$req->authorization_basic($share_user, $share_passwd);
|
||||||
my $response = $ua->request($req);
|
my $response = $ua->request($req);
|
||||||
|
|
||||||
if ($response->is_success()) {
|
if ($response->is_success()) {
|
||||||
# print "OK: ", $response->content;
|
|
||||||
print $response->decoded_content;
|
print $response->decoded_content;
|
||||||
if( $response->decoded_content =~ /<status_code>(\d+)<\/status_code>/m) {
|
if( $response->decoded_content =~ /<status_code>(\d+)<\/status_code>/m) {
|
||||||
my $code = $1;
|
my $code = $1;
|
||||||
|
|||||||
@@ -122,8 +122,24 @@ assertLocalAndRemoteDir( '', 0);
|
|||||||
|
|
||||||
# The previous sync should have updated the etags, and this should NOT be a conflict
|
# The previous sync should have updated the etags, and this should NOT be a conflict
|
||||||
printInfo( "Update the file again");
|
printInfo( "Update the file again");
|
||||||
createLocalFile( localDir() . "remoteToLocal1/kernelcrash.txt", 2136 );
|
|
||||||
createLocalFile( localDir() . "remoteToLocal1/kraft_logo.gif", 2332 );
|
my $f1 = localDir() . "remoteToLocal1/kernelcrash.txt";
|
||||||
|
my $s1 = 2136;
|
||||||
|
createLocalFile( $f1, $s1);
|
||||||
|
|
||||||
|
# stat the file
|
||||||
|
my @stat1 = stat $f1;
|
||||||
|
print "Updating File $f1 to $s1, size is $stat1[7]\n";
|
||||||
|
|
||||||
|
|
||||||
|
my $f2 = localDir() . "remoteToLocal1/kraft_logo.gif";
|
||||||
|
my $s2 = 2332;
|
||||||
|
|
||||||
|
createLocalFile( $f2, $s2);
|
||||||
|
# stat the file
|
||||||
|
my @stat2 = stat $f2;
|
||||||
|
print "Updating File $f2 to $s2, size is $stat2[7]\n";
|
||||||
|
|
||||||
system( "sleep 2 && touch " . localDir() . "remoteToLocal1/kernelcrash.txt" );
|
system( "sleep 2 && touch " . localDir() . "remoteToLocal1/kernelcrash.txt" );
|
||||||
csync( );
|
csync( );
|
||||||
assertLocalAndRemoteDir( '', 0);
|
assertLocalAndRemoteDir( '', 0);
|
||||||
@@ -169,6 +185,19 @@ assertLocalAndRemoteDir( '', 0);
|
|||||||
assert( -e localDir().'remoteToLocal1/rtlX' );
|
assert( -e localDir().'remoteToLocal1/rtlX' );
|
||||||
assert( -e localDir().'remoteToLocal1/rtlX/rtl11/file.txt' );
|
assert( -e localDir().'remoteToLocal1/rtlX/rtl11/file.txt' );
|
||||||
|
|
||||||
|
printInfo( "Remove a directory on the server with new files on the client");
|
||||||
|
removeRemoteDir('remoteToLocal1/rtlX');
|
||||||
|
system("echo hello > " . localDir(). "remoteToLocal1/rtlX/rtl11/hello.txt");
|
||||||
|
csync();
|
||||||
|
assertLocalAndRemoteDir( '', 0);
|
||||||
|
# file.txt must be gone because the directory was removed on the server, but hello.txt must be there
|
||||||
|
# as it is a new file
|
||||||
|
assert( ! -e localDir().'remoteToLocal1/rtlX/rtl11/file.txt' );
|
||||||
|
assert( -e localDir().'remoteToLocal1/rtlX/rtl11/hello.txt' );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ==================================================================
|
# ==================================================================
|
||||||
|
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|||||||
@@ -91,7 +91,10 @@ assertLocalAndRemoteDir( 'newdir', 0);
|
|||||||
assert( -e localDir().'newdir/rtl1/rtl11/newfile.dat' );
|
assert( -e localDir().'newdir/rtl1/rtl11/newfile.dat' );
|
||||||
assert( -e localDir().'newdir/rtl1/rtl11/myfile.txt' );
|
assert( -e localDir().'newdir/rtl1/rtl11/myfile.txt' );
|
||||||
assert( ! -e localDir().'newdir/rtl11/test.txt' );
|
assert( ! -e localDir().'newdir/rtl11/test.txt' );
|
||||||
assert( ! -e localDir().'remoteToLocal1' );
|
# BUG! remoteToLocal1 is not deleted because changes were detected
|
||||||
|
# (even if the changed fileswere moved)
|
||||||
|
# assert( ! -e localDir().'remoteToLocal1' );
|
||||||
|
assert( ! -e localDir().'remoteToLocal1/rtl1' );
|
||||||
|
|
||||||
printInfo("Move file and create another one with the same name.");
|
printInfo("Move file and create another one with the same name.");
|
||||||
move( localDir() . 'newdir/myfile.txt', localDir() . 'newdir/oldfile.txt' );
|
move( localDir() . 'newdir/myfile.txt', localDir() . 'newdir/oldfile.txt' );
|
||||||
|
|||||||
@@ -51,6 +51,11 @@ print "Created share with id <$shareId>\n";
|
|||||||
|
|
||||||
assert( $shareId > 0 );
|
assert( $shareId > 0 );
|
||||||
|
|
||||||
|
if( $ENV{SERVER_VERSION} eq "owncloud6" ) {
|
||||||
|
print "This test does not make more sense for ownCloud6, leaving for good!\n\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
# put a couple of files into the shared directory in the sharer account
|
# put a couple of files into the shared directory in the sharer account
|
||||||
glob_put( 'sharing/*', $share_dir, $sharee);
|
glob_put( 'sharing/*', $share_dir, $sharee);
|
||||||
|
|
||||||
@@ -62,7 +67,6 @@ moveRemoteFile( server() . $share_dir, localDir(), 1 );
|
|||||||
printInfo("Initial sync, sync stuff down.");
|
printInfo("Initial sync, sync stuff down.");
|
||||||
csync();
|
csync();
|
||||||
|
|
||||||
|
|
||||||
assertLocalAndRemoteDir( '', 0 );
|
assertLocalAndRemoteDir( '', 0 );
|
||||||
|
|
||||||
# Local file to a read/write share should be synced up
|
# Local file to a read/write share should be synced up
|
||||||
|
|||||||
@@ -33,11 +33,13 @@ print "Hello, this is t6, a tester for csync with ownCloud.\n";
|
|||||||
|
|
||||||
initTesting();
|
initTesting();
|
||||||
|
|
||||||
sub createPostUpdateScript()
|
sub createPostUpdateScript($)
|
||||||
{
|
{
|
||||||
my $srcFile = localDir()."BIG.file";
|
my ($name) = @_;
|
||||||
|
|
||||||
|
my $srcFile = localDir().'BIG1.file';
|
||||||
my $cred = configValue("user") . ":" . configValue("passwd");
|
my $cred = configValue("user") . ":" . configValue("passwd");
|
||||||
my $cmd = "curl -T $srcFile -u $cred " . testDirUrl();
|
my $cmd = "curl -T $srcFile -u $cred --insecure " . testDirUrl().$name;
|
||||||
my $script = "/tmp/post_update_script.sh";
|
my $script = "/tmp/post_update_script.sh";
|
||||||
open SC, ">$script" || die("Can not create script file");
|
open SC, ">$script" || die("Can not create script file");
|
||||||
print SC "#!/bin/bash\n";
|
print SC "#!/bin/bash\n";
|
||||||
@@ -48,11 +50,11 @@ sub createPostUpdateScript()
|
|||||||
return $script;
|
return $script;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub getETagFromJournal($)
|
sub getETagFromJournal($$)
|
||||||
{
|
{
|
||||||
my ($num) = @_;
|
my ($name,$num) = @_;
|
||||||
|
|
||||||
my $sql = "sqlite3 " . localDir() . ".csync_journal.db \"SELECT md5 FROM metadata WHERE path='BIG.file';\"";
|
my $sql = "sqlite3 " . localDir() . ".csync_journal.db \"SELECT md5 FROM metadata WHERE path='$name';\"";
|
||||||
open(my $fh, '-|', $sql) or die $!;
|
open(my $fh, '-|', $sql) or die $!;
|
||||||
my $etag = <$fh>;
|
my $etag = <$fh>;
|
||||||
close $fh;
|
close $fh;
|
||||||
@@ -61,14 +63,14 @@ sub getETagFromJournal($)
|
|||||||
return $etag;
|
return $etag;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub chunkFileTest( $$ )
|
sub chunkFileTest( $$ )
|
||||||
{
|
{
|
||||||
my ($name, $size) = @_;
|
my ($name, $size) = @_;
|
||||||
|
|
||||||
# Big file chunking
|
# Big file chunking
|
||||||
createLocalFile( localDir().$name, $size );
|
createLocalFile( localDir().$name, $size );
|
||||||
assert( -e localDir().$name );
|
assert( -e localDir().$name );
|
||||||
|
|
||||||
my $bigMd5 = md5OfFile( localDir().$name );
|
my $bigMd5 = md5OfFile( localDir().$name );
|
||||||
|
|
||||||
csync();
|
csync();
|
||||||
@@ -89,26 +91,39 @@ sub chunkFileTest( $$ )
|
|||||||
}
|
}
|
||||||
|
|
||||||
printInfo("Big file that needs chunking with default chunk size");
|
printInfo("Big file that needs chunking with default chunk size");
|
||||||
chunkFileTest( "BIG.file", 23251233 );
|
chunkFileTest( "BIG1.file", 23251233 );
|
||||||
|
|
||||||
printInfo("Update the existing file and trigger reupload");
|
printInfo("Update the existing file and trigger reupload");
|
||||||
# change the existing file again -> update
|
# change the existing file again -> update
|
||||||
chunkFileTest( "BIG.file", 21762122 );
|
chunkFileTest( "BIG2.file", 21762122 );
|
||||||
|
|
||||||
printInfo("Cause a precondition failed error");
|
printInfo("Cause a precondition failed error");
|
||||||
# Now overwrite the existing file to change it
|
# Now overwrite the existing file to change it
|
||||||
createLocalFile( localDir()."BIG.file", 21832199 );
|
createLocalFile( localDir()."BIG3.file", 21832 );
|
||||||
|
sleep(2);
|
||||||
|
csync();
|
||||||
|
createLocalFile( localDir().'BIG3.file', 34323 );
|
||||||
|
sleep(2);
|
||||||
# and create a post update script
|
# and create a post update script
|
||||||
my $script = createPostUpdateScript();
|
my $script = createPostUpdateScript('BIG3.file');
|
||||||
$ENV{'OWNCLOUD_POST_UPDATE_SCRIPT'} = $script;
|
$ENV{'OWNCLOUD_POST_UPDATE_SCRIPT'} = $script;
|
||||||
|
|
||||||
# Save the etag before the sync
|
# Save the etag before the sync
|
||||||
my $firstETag = getETagFromJournal('First');
|
my $firstETag = getETagFromJournal('BIG3.file', 'First');
|
||||||
csync(); # Sync, which ends in a precondition failed error
|
sleep(2);
|
||||||
|
csync(); # Sync, which ends in a precondition failed error
|
||||||
# get the etag again. It has to be unchanged because of the error.
|
# get the etag again. It has to be unchanged because of the error.
|
||||||
my $secondETag = getETagFromJournal('Second');
|
my $secondETag = getETagFromJournal('BIG3.file', 'Second');
|
||||||
assert( $firstETag eq $secondETag, "Different ETags, no precondition error." );
|
|
||||||
|
|
||||||
|
# Now the result is that there is a conflict file because since 1.7
|
||||||
|
# the sync is stopped on preconditoin failed and done again.
|
||||||
|
my $seen = 0;
|
||||||
|
opendir(my $dh, localDir() );
|
||||||
|
while(readdir $dh) {
|
||||||
|
$seen = 1 if ( /BIG3_conflict.*\.file/ );
|
||||||
|
}
|
||||||
|
closedir $dh;
|
||||||
|
assert( $seen == 1, "No conflict file created on precondition failed!" );
|
||||||
unlink($script);
|
unlink($script);
|
||||||
|
|
||||||
# Set a custom chunk size in environment.
|
# Set a custom chunk size in environment.
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ print "Hello, this is t8, a tester for syncing of files on a case sensitive FS\n
|
|||||||
# The test is run on a 'normal' file system, but we tell pwncloud that it is case preserving anyway
|
# The test is run on a 'normal' file system, but we tell pwncloud that it is case preserving anyway
|
||||||
$ENV{OWNCLOUD_TEST_CASE_PRESERVING} = "1";
|
$ENV{OWNCLOUD_TEST_CASE_PRESERVING} = "1";
|
||||||
|
|
||||||
# FIXME! the code does not work with parallelism
|
# No parallelism for more deterministic action.
|
||||||
$ENV{OWNCLOUD_MAX_PARALLEL}="1";
|
$ENV{OWNCLOUD_MAX_PARALLEL}="1";
|
||||||
|
|
||||||
initTesting();
|
initTesting();
|
||||||
@@ -48,6 +48,7 @@ mkdir($tmpdir);
|
|||||||
createLocalFile( $tmpdir . "HELLO.dat", 100 );
|
createLocalFile( $tmpdir . "HELLO.dat", 100 );
|
||||||
createLocalFile( $tmpdir . "Hello.dat", 150 );
|
createLocalFile( $tmpdir . "Hello.dat", 150 );
|
||||||
createLocalFile( $tmpdir . "Normal.dat", 110 );
|
createLocalFile( $tmpdir . "Normal.dat", 110 );
|
||||||
|
createLocalFile( $tmpdir . "test.dat", 170 );
|
||||||
|
|
||||||
#put them in some directories
|
#put them in some directories
|
||||||
createRemoteDir( "dir" );
|
createRemoteDir( "dir" );
|
||||||
@@ -73,14 +74,20 @@ assertLocalAndRemoteDir( '', 0);
|
|||||||
|
|
||||||
printInfo( "Renaming one file to the same name as another one with different casing" );
|
printInfo( "Renaming one file to the same name as another one with different casing" );
|
||||||
moveRemoteFile( 'dir/Hello.dat', 'dir/NORMAL.dat');
|
moveRemoteFile( 'dir/Hello.dat', 'dir/NORMAL.dat');
|
||||||
|
moveRemoteFile( 'dir/test.dat', 'dir/TEST.dat');
|
||||||
|
|
||||||
csync();
|
csync();
|
||||||
|
|
||||||
#It should not have do the move
|
# Hello -> NORMAL should not have do the move since the case conflict
|
||||||
assert( -e localDir() . 'dir/Hello.dat' );
|
assert( -e localDir() . 'dir/Hello.dat' );
|
||||||
assert( !-e localDir() . 'dir/NORMAL.dat' );
|
assert( !-e localDir() . 'dir/NORMAL.dat' );
|
||||||
assert( -e localDir() . 'dir/Normal.dat' );
|
assert( -e localDir() . 'dir/Normal.dat' );
|
||||||
|
|
||||||
|
#test->TEST should have been worked.
|
||||||
|
assert( -e localDir() . 'dir/TEST.dat' );
|
||||||
|
assert( !-e localDir() . 'dir/test.dat' );
|
||||||
|
|
||||||
|
|
||||||
printInfo( "Another directory with the same name but different casing is created" );
|
printInfo( "Another directory with the same name but different casing is created" );
|
||||||
|
|
||||||
createRemoteDir( "DIR" );
|
createRemoteDir( "DIR" );
|
||||||
@@ -105,6 +112,26 @@ assert( !-e localDir() . 'dir' );
|
|||||||
|
|
||||||
# dir/NORMAL.dat is still on the server
|
# dir/NORMAL.dat is still on the server
|
||||||
|
|
||||||
|
|
||||||
|
printInfo( "Attempt downloading two clashing files in parallel" );
|
||||||
|
|
||||||
|
# Enable parallelism
|
||||||
|
$ENV{OWNCLOUD_MAX_PARALLEL}="2";
|
||||||
|
|
||||||
|
my $tmpdir2 = "/tmp/t8/parallel/";
|
||||||
|
mkdir($tmpdir2);
|
||||||
|
createLocalFile( $tmpdir2 . "FILE.dat", 23251233 );
|
||||||
|
createLocalFile( $tmpdir2 . "file.dat", 33 );
|
||||||
|
createRemoteDir( "parallel" );
|
||||||
|
glob_put( "$tmpdir2/*", "parallel" );
|
||||||
|
|
||||||
|
csync();
|
||||||
|
|
||||||
|
# We assume the smaller file finished first, blocking
|
||||||
|
# the second file from being saved.
|
||||||
|
assert( !-e localDir() . 'parallel/FILE.dat' );
|
||||||
|
assert( -e localDir() . 'parallel/file.dat' );
|
||||||
|
|
||||||
cleanup();
|
cleanup();
|
||||||
system("rm -r " . $tmpdir);
|
system("rm -r " . $tmpdir);
|
||||||
|
|
||||||
|
|||||||
@@ -61,9 +61,10 @@ update check mechanism whereas the second method prevents any manual overrides.
|
|||||||
|
|
||||||
To prevent automatic updates, but allow manual overrides:
|
To prevent automatic updates, but allow manual overrides:
|
||||||
|
|
||||||
1. Migrate to the following directory::
|
1. Migrate to the following directory:
|
||||||
|
|
||||||
HKEY_LOCAL_MACHINE\Software\ownCloud\ownCloud
|
a. (32-bit) ``HKEY_LOCAL_MACHINE\Software\ownCloud\ownCloud``
|
||||||
|
b. (64-bit) ``HKEY_LOCAL_MACHINE\Software\Wow6432Node\ownCloud\ownCloud``
|
||||||
|
|
||||||
2. Add the key ``skipUpdateCheck`` (of type DWORD).
|
2. Add the key ``skipUpdateCheck`` (of type DWORD).
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ major platforms. You should read this section if you want to develop for the
|
|||||||
desktop client.
|
desktop client.
|
||||||
|
|
||||||
.. note:: Building instruction are subject to change as development proceeds.
|
.. note:: Building instruction are subject to change as development proceeds.
|
||||||
Please check the version for which you want to built.
|
Please check the version for which you want to build.
|
||||||
|
|
||||||
The instructions contained in this topic were updated to work with version 1.5 of the ownCloud Client.
|
The instructions contained in this topic were updated to work with version 1.7 of the ownCloud Client.
|
||||||
|
|
||||||
Linux
|
Linux
|
||||||
-----
|
-----
|
||||||
@@ -24,6 +24,11 @@ Linux
|
|||||||
|
|
||||||
3. Follow the `generic build instructions`_.
|
3. Follow the `generic build instructions`_.
|
||||||
|
|
||||||
|
4. (Optional) Call ``make install`` to install the client to the ``/usr/local/bin`` directory.
|
||||||
|
|
||||||
|
.. note:: This step requires the ``mingw32-cross-nsis`` packages be installed on
|
||||||
|
Windows.
|
||||||
|
|
||||||
Mac OS X
|
Mac OS X
|
||||||
--------
|
--------
|
||||||
|
|
||||||
@@ -41,17 +46,30 @@ To set up your build enviroment for development using HomeBrew_:
|
|||||||
|
|
||||||
1. Add the ownCloud repository using the following command::
|
1. Add the ownCloud repository using the following command::
|
||||||
|
|
||||||
brew tap owncloud/owncloud
|
brew tap owncloud/owncloud
|
||||||
|
|
||||||
2. Install any missing dependencies::
|
2. Install any missing dependencies::
|
||||||
|
|
||||||
brew install $(brew deps mirall)
|
brew install $(brew deps mirall)
|
||||||
|
|
||||||
To build mirall, follow the `generic build instructions`_.
|
3. Add Qt from brew to the path::
|
||||||
|
|
||||||
.. note:: Because the product from the mirall build is an app bundle, do not
|
export PATH=/usr/local/Cellar/qt5/5.x.y/bin/qmake
|
||||||
call ``make install`` at any time. Instead, call ``make package`` to create an
|
|
||||||
install-ready disk image.
|
Where ``x.z`` is the current version of Qt 5 that brew has installed
|
||||||
|
on your machine.
|
||||||
|
|
||||||
|
5. For compilation of mirall, follow the `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
|
||||||
|
its Common Name as a third parameter (use quotes) to have the package
|
||||||
|
signed automatically.
|
||||||
|
|
||||||
|
.. note:: Contrary to earlier versions, ownCloud 1.7 and later are packaged
|
||||||
|
as a ``pkg`` installer. Do not call "make package" at any time when
|
||||||
|
compiling for OS X, as this will build a disk image, and will not
|
||||||
|
work correctly.
|
||||||
|
|
||||||
Windows (Cross-Compile)
|
Windows (Cross-Compile)
|
||||||
-----------------------
|
-----------------------
|
||||||
@@ -63,15 +81,14 @@ have it installed already.
|
|||||||
|
|
||||||
To cross-compile:
|
To cross-compile:
|
||||||
|
|
||||||
1. Add the following repositories using YaST or ``zypper ar`` (adjust when using openSUSE 12.2 or 13.1):
|
1. Add the following repositories using YaST or ``zypper ar`` (adjust when using openSUSE 12.2 or 13.1)::
|
||||||
|
|
||||||
- ``zypper ar http://download.opensuse.org/repositories/windows:/mingw:/win32/openSUSE_13.1/windows:mingw:win32.repo``
|
zypper ar http://download.opensuse.org/repositories/windows:/mingw:/win32/openSUSE_13.1/windows:mingw:win32.repo
|
||||||
|
zypper ar http://download.opensuse.org/repositories/windows:/mingw/openSUSE_13.1/windows:mingw.repo
|
||||||
- ``zypper ar http://download.opensuse.org/repositories/windows:/mingw/openSUSE_13.1/windows:mingw.repo``
|
|
||||||
|
|
||||||
2. Install the cross-compiler packages and the cross-compiled dependencies::
|
2. Install the cross-compiler packages and the cross-compiled dependencies::
|
||||||
|
|
||||||
``zypper install cmake make mingw32-cross-binutils mingw32-cross-cpp mingw32-cross-gcc \
|
zypper install cmake make mingw32-cross-binutils mingw32-cross-cpp mingw32-cross-gcc \
|
||||||
mingw32-cross-gcc-c++ mingw32-cross-pkg-config mingw32-filesystem \
|
mingw32-cross-gcc-c++ mingw32-cross-pkg-config mingw32-filesystem \
|
||||||
mingw32-headers mingw32-runtime site-config mingw32-libqt4-sql \
|
mingw32-headers mingw32-runtime site-config mingw32-libqt4-sql \
|
||||||
mingw32-libqt4-sql-sqlite mingw32-sqlite mingw32-libsqlite-devel \
|
mingw32-libqt4-sql-sqlite mingw32-sqlite mingw32-libsqlite-devel \
|
||||||
@@ -82,42 +99,44 @@ To cross-compile:
|
|||||||
mingw32-libpng-devel mingw32-libsqlite mingw32-qtkeychain \
|
mingw32-libpng-devel mingw32-libsqlite mingw32-qtkeychain \
|
||||||
mingw32-qtkeychain-devel mingw32-dlfcn mingw32-libintl-devel \
|
mingw32-qtkeychain-devel mingw32-dlfcn mingw32-libintl-devel \
|
||||||
mingw32-libneon-devel mingw32-libopenssl-devel mingw32-libproxy-devel \
|
mingw32-libneon-devel mingw32-libopenssl-devel mingw32-libproxy-devel \
|
||||||
mingw32-libxml2-devel mingw32-zlib-devel``
|
mingw32-libxml2-devel mingw32-zlib-devel
|
||||||
|
|
||||||
3. For the installer, install the NSIS installer package::
|
3. For the installer, install the NSIS installer package::
|
||||||
|
|
||||||
``zypper install mingw32-cross-nsis``
|
zypper install mingw32-cross-nsis
|
||||||
|
|
||||||
4. Install the following plugin::
|
4. Install the following plugin::
|
||||||
|
|
||||||
``mingw32-cross-nsis-plugin-processes mingw32-cross-nsis-plugin-uac``
|
mingw32-cross-nsis-plugin-processes mingw32-cross-nsis-plugin-uac
|
||||||
|
|
||||||
.. note:: This plugin is typically required. However, due to a current bug
|
.. note:: This plugin is typically required. However, due to a current bug
|
||||||
in ``mingw``, the plugins do not currently build properly from source.
|
in ``mingw``, the plugins do not currently build properly from source.
|
||||||
|
|
||||||
5. Manually download and install the following files using ``rpm -ivh <package>``:
|
5. Manually download and install the following files using ``rpm -ivh <package>``:
|
||||||
|
|
||||||
..note:: These files operate using openSUSE 12.2 and newer.
|
.. note:: These files also work for more recent openSUSE versions!
|
||||||
|
|
||||||
- ``rpm -ihv 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 -ihv http://download.tomahawk-player.org/packman/mingw:32/openSUSE_12.1/x86_64/mingw32-cross-nsis-plugin-uac-0-3.1.x86_64.rpm``
|
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`_
|
6. Follow the `generic build instructions`_
|
||||||
|
|
||||||
.. note:: When building for Windows platforms, you must specify a special
|
.. note:: When building for Windows platforms, you must specify a special
|
||||||
toolchain file that enables cmake to locate the platform-specific tools. To add
|
toolchain file that enables cmake to locate the platform-specific tools. To add
|
||||||
this parameter to the call to cmake, enter
|
this parameter to the call to cmake, enter
|
||||||
``DCMAKE_TOOLCHAIN_FILE=../mirall/admin/win/Toolchain-mingw32-openSUSE.cmake``.
|
``-DCMAKE_TOOLCHAIN_FILE=../mirall/admin/win/Toolchain-mingw32-openSUSE.cmake``.
|
||||||
|
|
||||||
7. Build by running ``make``.
|
7. Build by running ``make``.
|
||||||
|
|
||||||
..note:: Using ``make package`` produces an NSIS-based installer, provided
|
.. note:: Using ``make package`` produces an NSIS-based installer, provided
|
||||||
the NSIS mingw32 packages are installed.
|
the NSIS mingw32 packages are installed.
|
||||||
|
|
||||||
|
.. _`generic build instructions`:
|
||||||
|
|
||||||
Generic Build Instructions
|
Generic Build Instructions
|
||||||
--------------------------
|
--------------------------
|
||||||
.. _`generic build instructions`
|
|
||||||
|
|
||||||
Compared to previous versions, building Mirall has become easier. Unlike
|
Compared to previous versions, building Mirall has become easier. Unlike
|
||||||
earlier versions, CSync, which is the sync engine library of Mirall, is now
|
earlier versions, CSync, which is the sync engine library of Mirall, is now
|
||||||
@@ -140,33 +159,32 @@ To build the most up to date version of the client:
|
|||||||
``cd ../mirall-build``
|
``cd ../mirall-build``
|
||||||
``cmake -DCMAKE_BUILD_TYPE="Debug" ../mirall``
|
``cmake -DCMAKE_BUILD_TYPE="Debug" ../mirall``
|
||||||
|
|
||||||
..note:: You must use absolute pathes for the ``include`` and ``library`` directories.
|
..note:: You must use absolute paths for the ``include`` and ``library``
|
||||||
|
directories.
|
||||||
|
|
||||||
|
..note:: On Mac OS X, you need to specify ``-DCMAKE_INSTALL_PREFIX=target``,
|
||||||
|
where ``target`` is a private location, i.e. in parallel to your build
|
||||||
|
dir by specifying ``../install``.
|
||||||
|
|
||||||
4. Call ``make``.
|
4. Call ``make``.
|
||||||
|
|
||||||
The owncloud binary appear in the ``bin`` directory.
|
The owncloud binary appear in the ``bin`` directory.
|
||||||
|
|
||||||
5. (Optional) Call ``make install`` to install the client to the ``/usr/local/bin`` directory.
|
|
||||||
|
|
||||||
6. (Optional) Call ``make package`` to build an installer/app bundle
|
|
||||||
|
|
||||||
..note:: This step requires the ``mingw32-cross-nsis`` packages be installed on Windows.
|
|
||||||
|
|
||||||
The following are known cmake parameters:
|
The following are known cmake parameters:
|
||||||
|
|
||||||
* ``QTKEYCHAIN_LIBRARY=/path/to/qtkeychain.dylib -DQTKEYCHAIN_INCLUDE_DIR=/path/to/qtkeychain/``:
|
* ``QTKEYCHAIN_LIBRARY=/path/to/qtkeychain.dylib -DQTKEYCHAIN_INCLUDE_DIR=/path/to/qtkeychain/``:
|
||||||
Used for stored credentials. When compiling with Qt5, the library is called ``qt5keychain.dylib.``
|
Used for stored credentials. When compiling with Qt5, the library is called ``qt5keychain.dylib.``
|
||||||
You need to compile QtKeychain with the same Qt version.
|
You need to compile QtKeychain with the same Qt version.
|
||||||
* ``WITH_DOC=TRUE``: Creates doc and manpages through running ``make``; also
|
* ``WITH_DOC=TRUE``: Creates doc and manpages through running ``make``; also adds install statements,
|
||||||
* adds install statements, providing the ability to install using ``make
|
providing the ability to install using ``make install``.
|
||||||
* install``.
|
|
||||||
* ``CMAKE_PREFIX_PATH=/path/to/Qt5.2.0/5.2.0/yourarch/lib/cmake/``: Builds using Qt5.
|
* ``CMAKE_PREFIX_PATH=/path/to/Qt5.2.0/5.2.0/yourarch/lib/cmake/``: Builds using Qt5.
|
||||||
* ``BUILD_WITH_QT4=ON``: Builds using Qt4 (even if Qt5 is found).
|
* ``BUILD_WITH_QT4=ON``: Builds using Qt4 (even if Qt5 is found).
|
||||||
|
* ``CMAKE_INSTALL_PREFIX=path``: Set an install prefix. This is mandatory on Mac OS
|
||||||
|
|
||||||
.. _`ownCloud repository from OBS`: http://software.opensuse.org/download/package?project=isv:ownCloud:devel&package=owncloud-client
|
.. _`ownCloud repository from OBS`: http://software.opensuse.org/download/package?project=isv:ownCloud:desktop&package=owncloud-client
|
||||||
.. _CSync: http://www.csync.org
|
.. _CSync: http://www.csync.org
|
||||||
.. _`Client Download Page`: http://owncloud.org/sync-clients/
|
.. _`Client Download Page`: http://owncloud.org/sync-clients/
|
||||||
.. _Git: http://git-scm.com
|
.. _Git: http://git-scm.com
|
||||||
.. _MacPorts: http://www.macports.org
|
.. _MacPorts: http://www.macports.org
|
||||||
.. _Homebrew: http://mxcl.github.com/homebrew/
|
.. _Homebrew: http://mxcl.github.com/homebrew/
|
||||||
.. _QtKeychain https://github.com/frankosterfeld/qtkeychain
|
.. _QtKeychain: https://github.com/frankosterfeld/qtkeychain
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
if(APPLE)
|
if(APPLE)
|
||||||
add_custom_target( mac_overlayplugin ALL
|
add_custom_target( mac_overlayplugin ALL
|
||||||
xcodebuild -workspace ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloud.xcworkspace
|
xcodebuild -workspace ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloud.xcworkspace
|
||||||
-scheme OwnCloudFinder.osax SYMROOT=${CMAKE_CURRENT_BINARY_DIR} archive
|
-scheme SyncStateFinder.osax SYMROOT=${CMAKE_CURRENT_BINARY_DIR} archive
|
||||||
COMMENT building Mac Overlay icons)
|
COMMENT building Mac Overlay icons)
|
||||||
|
|
||||||
INSTALL( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/OwnCloudFinder.osax/Contents
|
INSTALL( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/SyncStateFinder.osax/Contents
|
||||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/Library/ScriptingAdditions/OwnCloudFinder.osax/ )
|
DESTINATION ${CMAKE_INSTALL_PREFIX}/Library/ScriptingAdditions/SyncStateFinder.osax/ )
|
||||||
endif(APPLE)
|
endif(APPLE)
|
||||||
|
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ static ContentManager* sharedInstance = nil;
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( [keysToDelete count] > 0 ) {
|
if( [keysToDelete count] > 0 ) {
|
||||||
NSLog( @"Entries to delete: %d", [keysToDelete count]);
|
NSLog( @"Entries to delete: %lu", (unsigned long)[keysToDelete count]);
|
||||||
[_fileNamesCache removeObjectsForKeys:keysToDelete];
|
[_fileNamesCache removeObjectsForKeys:keysToDelete];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,7 +233,7 @@ static ContentManager* sharedInstance = nil;
|
|||||||
- (void)repaintAllWindowsIfNeeded
|
- (void)repaintAllWindowsIfNeeded
|
||||||
{
|
{
|
||||||
if (!_hasChangedContent) {
|
if (!_hasChangedContent) {
|
||||||
NSLog(@"%@ Repaint scheduled but not needed", NSStringFromSelector(_cmd));
|
//NSLog(@"%@ Repaint scheduled but not needed", NSStringFromSelector(_cmd));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
24
shell_integration/MacOSX/OwnCloudFinder/FinishedIconCache.h
Normal file
24
shell_integration/MacOSX/OwnCloudFinder/FinishedIconCache.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// FinishedIconCache.h
|
||||||
|
// OwnCloudFinder
|
||||||
|
//
|
||||||
|
// Created by Markus Goetz on 01/10/14.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
@interface FinishedIconCache : NSObject {
|
||||||
|
NSCache *_cache;
|
||||||
|
long long _hits;
|
||||||
|
long long _misses;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (FinishedIconCache*)sharedInstance;
|
||||||
|
|
||||||
|
- (NSImage*)getIcon:(NSString*)fileName overlayIconIndex:(int)idx width:(float)w height:(float)h;
|
||||||
|
- (void)registerIcon:(NSImage*)icon withFileName:(NSString*)fileName overlayIconIndex:(int)idx width:(float)w height:(float)h;
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
||||||
91
shell_integration/MacOSX/OwnCloudFinder/FinishedIconCache.m
Normal file
91
shell_integration/MacOSX/OwnCloudFinder/FinishedIconCache.m
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
//
|
||||||
|
// FinishedIconCache.m
|
||||||
|
// OwnCloudFinder
|
||||||
|
//
|
||||||
|
// Created by Markus Goetz on 01/10/14.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "FinishedIconCache.h"
|
||||||
|
|
||||||
|
|
||||||
|
@interface FinishedIconCacheItem : NSObject
|
||||||
|
@property (nonatomic, strong) NSImage *icon;
|
||||||
|
@property (nonatomic) NSTimeInterval maxAge;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FinishedIconCacheItem
|
||||||
|
@synthesize icon;
|
||||||
|
@synthesize maxAge;
|
||||||
|
- (void)dealloc {
|
||||||
|
//NSLog(@"RELEASE %@ %@", self, self.icon);
|
||||||
|
if (self.icon) {
|
||||||
|
[self->icon release];
|
||||||
|
}
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FinishedIconCache
|
||||||
|
|
||||||
|
static FinishedIconCache* sharedInstance = nil;
|
||||||
|
|
||||||
|
- init
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self)
|
||||||
|
{
|
||||||
|
_cache = [[NSCache alloc] init];
|
||||||
|
_cache.totalCostLimit = (2880 * 1800); // mbp15 screen size
|
||||||
|
_hits = 0;
|
||||||
|
_misses = 0;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
[_cache dealloc];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (FinishedIconCache*)sharedInstance
|
||||||
|
{
|
||||||
|
@synchronized(self)
|
||||||
|
{
|
||||||
|
if (sharedInstance == nil)
|
||||||
|
{
|
||||||
|
sharedInstance = [[self alloc] init];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sharedInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (NSImage*)getIcon:(NSString*)fileName overlayIconIndex:(int)idx width:(float)w height:(float)h
|
||||||
|
{
|
||||||
|
NSString *cacheKey = [NSString stringWithFormat:@"%@--%d--%f%f", fileName, idx, w,h];
|
||||||
|
FinishedIconCacheItem *item = [_cache objectForKey:cacheKey];
|
||||||
|
if (item) {
|
||||||
|
if (item.maxAge > [[NSDate date] timeIntervalSinceReferenceDate]) {
|
||||||
|
_hits++;
|
||||||
|
return item.icon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_misses++;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)registerIcon:(NSImage*)icon withFileName:(NSString*)fileName overlayIconIndex:(int)idx width:(float)w height:(float)h
|
||||||
|
{
|
||||||
|
NSString *cacheKey = [NSString stringWithFormat:@"%@--%d--%f%f", fileName, idx, w, h];
|
||||||
|
FinishedIconCacheItem *item = [[FinishedIconCacheItem alloc] init];
|
||||||
|
item.icon = icon;
|
||||||
|
// max age between 1 sec and 5 sec
|
||||||
|
item.maxAge = [[NSDate date] timeIntervalSinceReferenceDate] + 1.0 + 4.0*((double)arc4random() / 0x100000000);
|
||||||
|
[_cache setObject:item forKey:cacheKey cost:w*h];
|
||||||
|
[item release];
|
||||||
|
//NSLog(@"CACHE hit/miss ratio: %f", (float)_hits/(float)_misses);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
#import <objc/runtime.h>
|
#import <objc/runtime.h>
|
||||||
#import "ContentManager.h"
|
#import "ContentManager.h"
|
||||||
#import "IconCache.h"
|
#import "IconCache.h"
|
||||||
|
#import "FinishedIconCache.h"
|
||||||
#import "IconOverlayHandlers.h"
|
#import "IconOverlayHandlers.h"
|
||||||
#import "Finder/Finder.h"
|
#import "Finder/Finder.h"
|
||||||
|
|
||||||
@@ -69,7 +70,6 @@
|
|||||||
|
|
||||||
NSURL* url = [node previewItemURL];
|
NSURL* url = [node previewItemURL];
|
||||||
|
|
||||||
NSError *error;
|
|
||||||
BOOL isDir;
|
BOOL isDir;
|
||||||
if ([[NSFileManager defaultManager] fileExistsAtPath:[url path] isDirectory:&isDir] == NO) {
|
if ([[NSFileManager defaultManager] fileExistsAtPath:[url path] isDirectory:&isDir] == NO) {
|
||||||
NSLog(@"ERROR: Could not determine file type of %@", [url path]);
|
NSLog(@"ERROR: Could not determine file type of %@", [url path]);
|
||||||
@@ -83,15 +83,26 @@
|
|||||||
{
|
{
|
||||||
NSImage* icon = [arg1 _nsImage];
|
NSImage* icon = [arg1 _nsImage];
|
||||||
|
|
||||||
[icon lockFocus];
|
// Use the short term icon cache that possibly has the finished icon
|
||||||
|
FinishedIconCache *finishedIconCache = [FinishedIconCache sharedInstance];
|
||||||
CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort];
|
NSImage *finishedImage = [finishedIconCache getIcon:[url path] overlayIconIndex:imageIndex width:[icon size].width height:[icon size].height];
|
||||||
|
if (finishedImage) {
|
||||||
|
//NSLog(@"X Got finished image from cache %@ %@", finishedImage, [url path]);
|
||||||
|
return [[[IKImageWrapper alloc] initWithNSImage:finishedImage] autorelease];;
|
||||||
|
} else {
|
||||||
|
//NSLog(@"X Need to redraw %@", [url path]);
|
||||||
|
}
|
||||||
|
|
||||||
NSImage* iconimage = [[IconCache sharedInstance] getIcon:[NSNumber numberWithInt:[imageIndex intValue]]];
|
NSImage* iconimage = [[IconCache sharedInstance] getIcon:[NSNumber numberWithInt:[imageIndex intValue]]];
|
||||||
|
|
||||||
if (iconimage != nil)
|
if (iconimage != nil)
|
||||||
{
|
{
|
||||||
|
[icon lockFocus];
|
||||||
|
|
||||||
|
CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort];
|
||||||
|
|
||||||
CGRect destRect = CGRectMake(0, 0, [icon size].width, [icon size].height);
|
CGRect destRect = CGRectMake(0, 0, [icon size].width, [icon size].height);
|
||||||
|
|
||||||
CGImageRef cgImage = [iconimage CGImageForProposedRect:&destRect
|
CGImageRef cgImage = [iconimage CGImageForProposedRect:&destRect
|
||||||
context:[NSGraphicsContext currentContext]
|
context:[NSGraphicsContext currentContext]
|
||||||
hints:nil];
|
hints:nil];
|
||||||
@@ -103,9 +114,11 @@
|
|||||||
NSLog(@"No image given!!!!!11 %@", [url path]);
|
NSLog(@"No image given!!!!!11 %@", [url path]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[icon unlockFocus];
|
||||||
}
|
}
|
||||||
|
|
||||||
[icon unlockFocus];
|
// Insert into cache
|
||||||
|
[finishedIconCache registerIcon:icon withFileName:[url path] overlayIconIndex:imageIndex width:[icon size].width height:[icon size].height];
|
||||||
|
|
||||||
return [[[IKImageWrapper alloc] initWithNSImage:icon] autorelease];
|
return [[[IKImageWrapper alloc] initWithNSImage:icon] autorelease];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,251 +0,0 @@
|
|||||||
//
|
|
||||||
// JSONKit.h
|
|
||||||
// http://github.com/johnezang/JSONKit
|
|
||||||
// Dual licensed under either the terms of the BSD License, or alternatively
|
|
||||||
// under the terms of the Apache License, Version 2.0, as specified below.
|
|
||||||
//
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright (c) 2011, John Engelhart
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the Zang Industries nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright 2011 John Engelhart
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <TargetConditionals.h>
|
|
||||||
#include <AvailabilityMacros.h>
|
|
||||||
|
|
||||||
#ifdef __OBJC__
|
|
||||||
#import <Foundation/NSArray.h>
|
|
||||||
#import <Foundation/NSData.h>
|
|
||||||
#import <Foundation/NSDictionary.h>
|
|
||||||
#import <Foundation/NSError.h>
|
|
||||||
#import <Foundation/NSObjCRuntime.h>
|
|
||||||
#import <Foundation/NSString.h>
|
|
||||||
#endif // __OBJC__
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// For Mac OS X < 10.5.
|
|
||||||
#ifndef NSINTEGER_DEFINED
|
|
||||||
#define NSINTEGER_DEFINED
|
|
||||||
#if defined(__LP64__) || defined(NS_BUILD_32_LIKE_64)
|
|
||||||
typedef long NSInteger;
|
|
||||||
typedef unsigned long NSUInteger;
|
|
||||||
#define NSIntegerMin LONG_MIN
|
|
||||||
#define NSIntegerMax LONG_MAX
|
|
||||||
#define NSUIntegerMax ULONG_MAX
|
|
||||||
#else // defined(__LP64__) || defined(NS_BUILD_32_LIKE_64)
|
|
||||||
typedef int NSInteger;
|
|
||||||
typedef unsigned int NSUInteger;
|
|
||||||
#define NSIntegerMin INT_MIN
|
|
||||||
#define NSIntegerMax INT_MAX
|
|
||||||
#define NSUIntegerMax UINT_MAX
|
|
||||||
#endif // defined(__LP64__) || defined(NS_BUILD_32_LIKE_64)
|
|
||||||
#endif // NSINTEGER_DEFINED
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef _JSONKIT_H_
|
|
||||||
#define _JSONKIT_H_
|
|
||||||
|
|
||||||
#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__APPLE_CC__) && (__APPLE_CC__ >= 5465)
|
|
||||||
#define JK_DEPRECATED_ATTRIBUTE __attribute__((deprecated))
|
|
||||||
#else
|
|
||||||
#define JK_DEPRECATED_ATTRIBUTE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define JSONKIT_VERSION_MAJOR 1
|
|
||||||
#define JSONKIT_VERSION_MINOR 4
|
|
||||||
|
|
||||||
typedef NSUInteger JKFlags;
|
|
||||||
|
|
||||||
/*
|
|
||||||
JKParseOptionComments : Allow C style // and /_* ... *_/ (without a _, obviously) comments in JSON.
|
|
||||||
JKParseOptionUnicodeNewlines : Allow Unicode recommended (?:\r\n|[\n\v\f\r\x85\p{Zl}\p{Zp}]) newlines.
|
|
||||||
JKParseOptionLooseUnicode : Normally the decoder will stop with an error at any malformed Unicode.
|
|
||||||
This option allows JSON with malformed Unicode to be parsed without reporting an error.
|
|
||||||
Any malformed Unicode is replaced with \uFFFD, or "REPLACEMENT CHARACTER".
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum {
|
|
||||||
JKParseOptionNone = 0,
|
|
||||||
JKParseOptionStrict = 0,
|
|
||||||
JKParseOptionComments = (1 << 0),
|
|
||||||
JKParseOptionUnicodeNewlines = (1 << 1),
|
|
||||||
JKParseOptionLooseUnicode = (1 << 2),
|
|
||||||
JKParseOptionPermitTextAfterValidJSON = (1 << 3),
|
|
||||||
JKParseOptionValidFlags = (JKParseOptionComments | JKParseOptionUnicodeNewlines | JKParseOptionLooseUnicode | JKParseOptionPermitTextAfterValidJSON),
|
|
||||||
};
|
|
||||||
typedef JKFlags JKParseOptionFlags;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
JKSerializeOptionNone = 0,
|
|
||||||
JKSerializeOptionPretty = (1 << 0),
|
|
||||||
JKSerializeOptionEscapeUnicode = (1 << 1),
|
|
||||||
JKSerializeOptionEscapeForwardSlashes = (1 << 4),
|
|
||||||
JKSerializeOptionValidFlags = (JKSerializeOptionPretty | JKSerializeOptionEscapeUnicode | JKSerializeOptionEscapeForwardSlashes),
|
|
||||||
};
|
|
||||||
typedef JKFlags JKSerializeOptionFlags;
|
|
||||||
|
|
||||||
#ifdef __OBJC__
|
|
||||||
|
|
||||||
typedef struct JKParseState JKParseState; // Opaque internal, private type.
|
|
||||||
|
|
||||||
// As a general rule of thumb, if you use a method that doesn't accept a JKParseOptionFlags argument, it defaults to JKParseOptionStrict
|
|
||||||
|
|
||||||
@interface JSONDecoder : NSObject {
|
|
||||||
JKParseState *parseState;
|
|
||||||
}
|
|
||||||
+ (id)decoder;
|
|
||||||
+ (id)decoderWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
|
|
||||||
- (id)initWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
|
|
||||||
- (void)clearCache;
|
|
||||||
|
|
||||||
// The parse... methods were deprecated in v1.4 in favor of the v1.4 objectWith... methods.
|
|
||||||
- (id)parseUTF8String:(const unsigned char *)string length:(size_t)length JK_DEPRECATED_ATTRIBUTE; // Deprecated in JSONKit v1.4. Use objectWithUTF8String:length: instead.
|
|
||||||
- (id)parseUTF8String:(const unsigned char *)string length:(size_t)length error:(NSError **)error JK_DEPRECATED_ATTRIBUTE; // Deprecated in JSONKit v1.4. Use objectWithUTF8String:length:error: instead.
|
|
||||||
// The NSData MUST be UTF8 encoded JSON.
|
|
||||||
- (id)parseJSONData:(NSData *)jsonData JK_DEPRECATED_ATTRIBUTE; // Deprecated in JSONKit v1.4. Use objectWithData: instead.
|
|
||||||
- (id)parseJSONData:(NSData *)jsonData error:(NSError **)error JK_DEPRECATED_ATTRIBUTE; // Deprecated in JSONKit v1.4. Use objectWithData:error: instead.
|
|
||||||
|
|
||||||
// Methods that return immutable collection objects.
|
|
||||||
- (id)objectWithUTF8String:(const unsigned char *)string length:(NSUInteger)length;
|
|
||||||
- (id)objectWithUTF8String:(const unsigned char *)string length:(NSUInteger)length error:(NSError **)error;
|
|
||||||
// The NSData MUST be UTF8 encoded JSON.
|
|
||||||
- (id)objectWithData:(NSData *)jsonData;
|
|
||||||
- (id)objectWithData:(NSData *)jsonData error:(NSError **)error;
|
|
||||||
|
|
||||||
// Methods that return mutable collection objects.
|
|
||||||
- (id)mutableObjectWithUTF8String:(const unsigned char *)string length:(NSUInteger)length;
|
|
||||||
- (id)mutableObjectWithUTF8String:(const unsigned char *)string length:(NSUInteger)length error:(NSError **)error;
|
|
||||||
// The NSData MUST be UTF8 encoded JSON.
|
|
||||||
- (id)mutableObjectWithData:(NSData *)jsonData;
|
|
||||||
- (id)mutableObjectWithData:(NSData *)jsonData error:(NSError **)error;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
////////////
|
|
||||||
#pragma mark Deserializing methods
|
|
||||||
////////////
|
|
||||||
|
|
||||||
@interface NSString (JSONKitDeserializing)
|
|
||||||
- (id)objectFromJSONString;
|
|
||||||
- (id)objectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
|
|
||||||
- (id)objectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;
|
|
||||||
- (id)mutableObjectFromJSONString;
|
|
||||||
- (id)mutableObjectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
|
|
||||||
- (id)mutableObjectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface NSData (JSONKitDeserializing)
|
|
||||||
// The NSData MUST be UTF8 encoded JSON.
|
|
||||||
- (id)objectFromJSONData;
|
|
||||||
- (id)objectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
|
|
||||||
- (id)objectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;
|
|
||||||
- (id)mutableObjectFromJSONData;
|
|
||||||
- (id)mutableObjectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
|
|
||||||
- (id)mutableObjectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;
|
|
||||||
@end
|
|
||||||
|
|
||||||
////////////
|
|
||||||
#pragma mark Serializing methods
|
|
||||||
////////////
|
|
||||||
|
|
||||||
@interface NSString (JSONKitSerializing)
|
|
||||||
// Convenience methods for those that need to serialize the receiving NSString (i.e., instead of having to serialize a NSArray with a single NSString, you can "serialize to JSON" just the NSString).
|
|
||||||
// Normally, a string that is serialized to JSON has quotation marks surrounding it, which you may or may not want when serializing a single string, and can be controlled with includeQuotes:
|
|
||||||
// includeQuotes:YES `a "test"...` -> `"a \"test\"..."`
|
|
||||||
// includeQuotes:NO `a "test"...` -> `a \"test\"...`
|
|
||||||
- (NSData *)JSONData; // Invokes JSONDataWithOptions:JKSerializeOptionNone includeQuotes:YES
|
|
||||||
- (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions includeQuotes:(BOOL)includeQuotes error:(NSError **)error;
|
|
||||||
- (NSString *)JSONString; // Invokes JSONStringWithOptions:JKSerializeOptionNone includeQuotes:YES
|
|
||||||
- (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions includeQuotes:(BOOL)includeQuotes error:(NSError **)error;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface NSArray (JSONKitSerializing)
|
|
||||||
- (NSData *)JSONData;
|
|
||||||
- (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;
|
|
||||||
- (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingDelegate:(id)delegate selector:(SEL)selector error:(NSError **)error;
|
|
||||||
- (NSString *)JSONString;
|
|
||||||
- (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;
|
|
||||||
- (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingDelegate:(id)delegate selector:(SEL)selector error:(NSError **)error;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface NSDictionary (JSONKitSerializing)
|
|
||||||
- (NSData *)JSONData;
|
|
||||||
- (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;
|
|
||||||
- (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingDelegate:(id)delegate selector:(SEL)selector error:(NSError **)error;
|
|
||||||
- (NSString *)JSONString;
|
|
||||||
- (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;
|
|
||||||
- (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingDelegate:(id)delegate selector:(SEL)selector error:(NSError **)error;
|
|
||||||
@end
|
|
||||||
|
|
||||||
#ifdef __BLOCKS__
|
|
||||||
|
|
||||||
@interface NSArray (JSONKitSerializingBlockAdditions)
|
|
||||||
- (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingBlock:(id(^)(id object))block error:(NSError **)error;
|
|
||||||
- (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingBlock:(id(^)(id object))block error:(NSError **)error;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface NSDictionary (JSONKitSerializingBlockAdditions)
|
|
||||||
- (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingBlock:(id(^)(id object))block error:(NSError **)error;
|
|
||||||
- (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingBlock:(id(^)(id object))block error:(NSError **)error;
|
|
||||||
@end
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif // __OBJC__
|
|
||||||
|
|
||||||
#endif // _JSONKIT_H_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} // extern "C"
|
|
||||||
#endif
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -7,9 +7,9 @@
|
|||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
0B13ECAE173C687400548DA1 /* GCDAsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B13ECAD173C686A00548DA1 /* GCDAsyncSocket.m */; };
|
0B13ECAE173C687400548DA1 /* GCDAsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B13ECAD173C686A00548DA1 /* GCDAsyncSocket.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
|
||||||
0B13ECAF173C687900548DA1 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BFC9ACB173C57E400CDD329 /* Security.framework */; };
|
0B13ECAF173C687900548DA1 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BFC9ACB173C57E400CDD329 /* Security.framework */; };
|
||||||
0BFAF21C16F8E6C10017EA7E /* JSONKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BFAF21B16F8E6C10017EA7E /* JSONKit.m */; };
|
5BB74A8719DBF9BB001BAAAC /* FinishedIconCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BB74A8619DBF9BB001BAAAC /* FinishedIconCache.m */; };
|
||||||
692C18A516660C4700BF6A53 /* ContextMenuHandlers.m in Sources */ = {isa = PBXBuildFile; fileRef = 692C18A416660C4600BF6A53 /* ContextMenuHandlers.m */; };
|
692C18A516660C4700BF6A53 /* ContextMenuHandlers.m in Sources */ = {isa = PBXBuildFile; fileRef = 692C18A416660C4600BF6A53 /* ContextMenuHandlers.m */; };
|
||||||
692C18A9166617F500BF6A53 /* IconOverlayHandlers.m in Sources */ = {isa = PBXBuildFile; fileRef = 692C18A8166617F500BF6A53 /* IconOverlayHandlers.m */; };
|
692C18A9166617F500BF6A53 /* IconOverlayHandlers.m in Sources */ = {isa = PBXBuildFile; fileRef = 692C18A8166617F500BF6A53 /* IconOverlayHandlers.m */; };
|
||||||
692C18AC1666392700BF6A53 /* MenuManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 692C18AB1666392700BF6A53 /* MenuManager.m */; };
|
692C18AC1666392700BF6A53 /* MenuManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 692C18AB1666392700BF6A53 /* MenuManager.m */; };
|
||||||
@@ -29,9 +29,9 @@
|
|||||||
0B13ECAC173C686900548DA1 /* GCDAsyncSocket.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GCDAsyncSocket.h; sourceTree = "<group>"; };
|
0B13ECAC173C686900548DA1 /* GCDAsyncSocket.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GCDAsyncSocket.h; sourceTree = "<group>"; };
|
||||||
0B13ECAD173C686A00548DA1 /* GCDAsyncSocket.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GCDAsyncSocket.m; sourceTree = "<group>"; };
|
0B13ECAD173C686A00548DA1 /* GCDAsyncSocket.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GCDAsyncSocket.m; sourceTree = "<group>"; };
|
||||||
0B2BF60B176A43DB001246CD /* Finder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Finder.h; sourceTree = "<group>"; };
|
0B2BF60B176A43DB001246CD /* Finder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Finder.h; sourceTree = "<group>"; };
|
||||||
0BFAF21A16F8E6C10017EA7E /* JSONKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONKit.h; sourceTree = "<group>"; };
|
|
||||||
0BFAF21B16F8E6C10017EA7E /* JSONKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSONKit.m; sourceTree = "<group>"; };
|
|
||||||
0BFC9ACB173C57E400CDD329 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
|
0BFC9ACB173C57E400CDD329 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
|
||||||
|
5BB74A8519DBF9BB001BAAAC /* FinishedIconCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FinishedIconCache.h; sourceTree = "<group>"; };
|
||||||
|
5BB74A8619DBF9BB001BAAAC /* FinishedIconCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FinishedIconCache.m; sourceTree = "<group>"; };
|
||||||
692C18A316660C4600BF6A53 /* ContextMenuHandlers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContextMenuHandlers.h; sourceTree = "<group>"; };
|
692C18A316660C4600BF6A53 /* ContextMenuHandlers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContextMenuHandlers.h; sourceTree = "<group>"; };
|
||||||
692C18A416660C4600BF6A53 /* ContextMenuHandlers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContextMenuHandlers.m; sourceTree = "<group>"; };
|
692C18A416660C4600BF6A53 /* ContextMenuHandlers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContextMenuHandlers.m; sourceTree = "<group>"; };
|
||||||
692C18A7166617F500BF6A53 /* IconOverlayHandlers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IconOverlayHandlers.h; sourceTree = "<group>"; };
|
692C18A7166617F500BF6A53 /* IconOverlayHandlers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IconOverlayHandlers.h; sourceTree = "<group>"; };
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
8C37DDB9161594B400016A95 /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = System/Library/Frameworks/Quartz.framework; sourceTree = SDKROOT; };
|
8C37DDB9161594B400016A95 /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = System/Library/Frameworks/Quartz.framework; sourceTree = SDKROOT; };
|
||||||
8C99F6921622D145002D2135 /* IconCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IconCache.h; sourceTree = "<group>"; };
|
8C99F6921622D145002D2135 /* IconCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IconCache.h; sourceTree = "<group>"; };
|
||||||
8C99F6931622D145002D2135 /* IconCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IconCache.m; sourceTree = "<group>"; };
|
8C99F6931622D145002D2135 /* IconCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IconCache.m; sourceTree = "<group>"; };
|
||||||
8D576316048677EA00EA77CD /* OwnCloudFinder.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OwnCloudFinder.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
8D576316048677EA00EA77CD /* SyncStateFinder.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SyncStateFinder.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
8D576317048677EA00EA77CD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
8D576317048677EA00EA77CD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
089C166AFE841209C02AAC07 /* OwnCloudFinder */ = {
|
089C166AFE841209C02AAC07 /* SyncStateFinder */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
08FB77AFFE84173DC02AAC07 /* Source */,
|
08FB77AFFE84173DC02AAC07 /* Source */,
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
089C1671FE841209C02AAC07 /* External Frameworks and Libraries */,
|
089C1671FE841209C02AAC07 /* External Frameworks and Libraries */,
|
||||||
19C28FB6FE9D52B211CA2CBB /* Products */,
|
19C28FB6FE9D52B211CA2CBB /* Products */,
|
||||||
);
|
);
|
||||||
name = OwnCloudFinder;
|
name = SyncStateFinder;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
usesTabs = 1;
|
usesTabs = 1;
|
||||||
};
|
};
|
||||||
@@ -104,7 +104,6 @@
|
|||||||
children = (
|
children = (
|
||||||
0B2BF60A176A43DB001246CD /* Finder */,
|
0B2BF60A176A43DB001246CD /* Finder */,
|
||||||
0B08BAC21759627700C8351E /* GCDAsyncSocket */,
|
0B08BAC21759627700C8351E /* GCDAsyncSocket */,
|
||||||
0BFAF21916F8E6910017EA7E /* JSONKit */,
|
|
||||||
8C37DD99161593BD00016A95 /* FinderHook.h */,
|
8C37DD99161593BD00016A95 /* FinderHook.h */,
|
||||||
8C37DD9A161593BD00016A95 /* FinderHook.m */,
|
8C37DD9A161593BD00016A95 /* FinderHook.m */,
|
||||||
692C18A316660C4600BF6A53 /* ContextMenuHandlers.h */,
|
692C18A316660C4600BF6A53 /* ContextMenuHandlers.h */,
|
||||||
@@ -117,6 +116,8 @@
|
|||||||
69948B351636D50E0093B6CE /* ContentManager.m */,
|
69948B351636D50E0093B6CE /* ContentManager.m */,
|
||||||
8C99F6921622D145002D2135 /* IconCache.h */,
|
8C99F6921622D145002D2135 /* IconCache.h */,
|
||||||
8C99F6931622D145002D2135 /* IconCache.m */,
|
8C99F6931622D145002D2135 /* IconCache.m */,
|
||||||
|
5BB74A8519DBF9BB001BAAAC /* FinishedIconCache.h */,
|
||||||
|
5BB74A8619DBF9BB001BAAAC /* FinishedIconCache.m */,
|
||||||
692C18AA1666392700BF6A53 /* MenuManager.h */,
|
692C18AA1666392700BF6A53 /* MenuManager.h */,
|
||||||
692C18AB1666392700BF6A53 /* MenuManager.m */,
|
692C18AB1666392700BF6A53 /* MenuManager.m */,
|
||||||
);
|
);
|
||||||
@@ -140,19 +141,10 @@
|
|||||||
path = Finder;
|
path = Finder;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
0BFAF21916F8E6910017EA7E /* JSONKit */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
0BFAF21A16F8E6C10017EA7E /* JSONKit.h */,
|
|
||||||
0BFAF21B16F8E6C10017EA7E /* JSONKit.m */,
|
|
||||||
);
|
|
||||||
name = JSONKit;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
19C28FB6FE9D52B211CA2CBB /* Products */ = {
|
19C28FB6FE9D52B211CA2CBB /* Products */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
8D576316048677EA00EA77CD /* OwnCloudFinder.bundle */,
|
8D576316048677EA00EA77CD /* SyncStateFinder.bundle */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -160,9 +152,9 @@
|
|||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
8D57630D048677EA00EA77CD /* OwnCloudFinder */ = {
|
8D57630D048677EA00EA77CD /* SyncStateFinder */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "OwnCloudFinder" */;
|
buildConfigurationList = 1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "SyncStateFinder" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
8D57630F048677EA00EA77CD /* Resources */,
|
8D57630F048677EA00EA77CD /* Resources */,
|
||||||
8D576311048677EA00EA77CD /* Sources */,
|
8D576311048677EA00EA77CD /* Sources */,
|
||||||
@@ -172,10 +164,10 @@
|
|||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
);
|
);
|
||||||
name = OwnCloudFinder;
|
name = SyncStateFinder;
|
||||||
productInstallPath = "$(HOME)/Library/Bundles";
|
productInstallPath = "$(HOME)/Library/Bundles";
|
||||||
productName = OwnCloudFinder;
|
productName = SyncStateFinder;
|
||||||
productReference = 8D576316048677EA00EA77CD /* OwnCloudFinder.bundle */;
|
productReference = 8D576316048677EA00EA77CD /* SyncStateFinder.bundle */;
|
||||||
productType = "com.apple.product-type.bundle";
|
productType = "com.apple.product-type.bundle";
|
||||||
};
|
};
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
@@ -186,7 +178,7 @@
|
|||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 0460;
|
LastUpgradeCheck = 0460;
|
||||||
};
|
};
|
||||||
buildConfigurationList = 1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "OwnCloudFinder" */;
|
buildConfigurationList = 1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "SyncStateFinder" */;
|
||||||
compatibilityVersion = "Xcode 3.2";
|
compatibilityVersion = "Xcode 3.2";
|
||||||
developmentRegion = English;
|
developmentRegion = English;
|
||||||
hasScannedForEncodings = 1;
|
hasScannedForEncodings = 1;
|
||||||
@@ -196,11 +188,11 @@
|
|||||||
French,
|
French,
|
||||||
German,
|
German,
|
||||||
);
|
);
|
||||||
mainGroup = 089C166AFE841209C02AAC07 /* OwnCloudFinder */;
|
mainGroup = 089C166AFE841209C02AAC07 /* SyncStateFinder` */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
8D57630D048677EA00EA77CD /* OwnCloudFinder */,
|
8D57630D048677EA00EA77CD /* SyncStateFinder */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
@@ -226,10 +218,10 @@
|
|||||||
8C99F6941622D145002D2135 /* IconCache.m in Sources */,
|
8C99F6941622D145002D2135 /* IconCache.m in Sources */,
|
||||||
69948B361636D50E0093B6CE /* ContentManager.m in Sources */,
|
69948B361636D50E0093B6CE /* ContentManager.m in Sources */,
|
||||||
6993878616494C000044E4DF /* RequestManager.m in Sources */,
|
6993878616494C000044E4DF /* RequestManager.m in Sources */,
|
||||||
|
5BB74A8719DBF9BB001BAAAC /* FinishedIconCache.m in Sources */,
|
||||||
692C18A516660C4700BF6A53 /* ContextMenuHandlers.m in Sources */,
|
692C18A516660C4700BF6A53 /* ContextMenuHandlers.m in Sources */,
|
||||||
692C18A9166617F500BF6A53 /* IconOverlayHandlers.m in Sources */,
|
692C18A9166617F500BF6A53 /* IconOverlayHandlers.m in Sources */,
|
||||||
692C18AC1666392700BF6A53 /* MenuManager.m in Sources */,
|
692C18AC1666392700BF6A53 /* MenuManager.m in Sources */,
|
||||||
0BFAF21C16F8E6C10017EA7E /* JSONKit.m in Sources */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -260,7 +252,7 @@
|
|||||||
GCC_OPTIMIZATION_LEVEL = 0;
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
INFOPLIST_FILE = Info.plist;
|
INFOPLIST_FILE = Info.plist;
|
||||||
INSTALL_PATH = "$(HOME)/Library/Bundles";
|
INSTALL_PATH = "$(HOME)/Library/Bundles";
|
||||||
PRODUCT_NAME = OwnCloudFinder;
|
PRODUCT_NAME = SyncStateFinder;
|
||||||
WRAPPER_EXTENSION = bundle;
|
WRAPPER_EXTENSION = bundle;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
@@ -277,7 +269,7 @@
|
|||||||
GCC_MODEL_TUNING = G5;
|
GCC_MODEL_TUNING = G5;
|
||||||
INFOPLIST_FILE = Info.plist;
|
INFOPLIST_FILE = Info.plist;
|
||||||
INSTALL_PATH = "$(HOME)/Library/Bundles";
|
INSTALL_PATH = "$(HOME)/Library/Bundles";
|
||||||
PRODUCT_NAME = OwnCloudFinder;
|
PRODUCT_NAME = SyncStateFinder;
|
||||||
WRAPPER_EXTENSION = bundle;
|
WRAPPER_EXTENSION = bundle;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
@@ -302,8 +294,9 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
|
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
|
||||||
COPY_PHASE_STRIP = YES;
|
COPY_PHASE_STRIP = NO;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||||
@@ -315,7 +308,7 @@
|
|||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "OwnCloudFinder" */ = {
|
1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "SyncStateFinder" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
1DEB911B08733D790010E9CD /* Debug */,
|
1DEB911B08733D790010E9CD /* Debug */,
|
||||||
@@ -324,7 +317,7 @@
|
|||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "OwnCloudFinder" */ = {
|
1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "SyncStateFinder" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
1DEB911F08733D790010E9CD /* Debug */,
|
1DEB911F08733D790010E9CD /* Debug */,
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ static RequestManager* sharedInstance = nil;
|
|||||||
NSArray *regPathes = [_registeredPathes allKeys];
|
NSArray *regPathes = [_registeredPathes allKeys];
|
||||||
BOOL registered = NO;
|
BOOL registered = NO;
|
||||||
|
|
||||||
NSString* checkPath = [[NSString alloc] initWithString:path];
|
NSString* checkPath = [NSString stringWithString:path];
|
||||||
if (isDir) {
|
if (isDir) {
|
||||||
// append a slash
|
// append a slash
|
||||||
checkPath = [path stringByAppendingString:@"/"];
|
checkPath = [path stringByAppendingString:@"/"];
|
||||||
@@ -127,17 +127,17 @@ static RequestManager* sharedInstance = nil;
|
|||||||
|
|
||||||
- (void)socket:(GCDAsyncSocket*)socket didReadData:(NSData*)data withTag:(long)tag
|
- (void)socket:(GCDAsyncSocket*)socket didReadData:(NSData*)data withTag:(long)tag
|
||||||
{
|
{
|
||||||
NSArray *chunks;
|
|
||||||
NSString *answer = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
NSString *answer = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||||
|
NSArray *chunks = nil;
|
||||||
if (answer != nil && [answer length] > 0) {
|
if (answer != nil && [answer length] > 0) {
|
||||||
// cut a trailing newline
|
// cut a trailing newline
|
||||||
answer = [answer substringToIndex:[answer length] - 1];
|
answer = [answer substringToIndex:[answer length] - 1];
|
||||||
chunks = [answer componentsSeparatedByString: @":"];
|
chunks = [answer componentsSeparatedByString: @":"];
|
||||||
}
|
}
|
||||||
NSLog(@"READ from socket (%ld): <%@>", tag, answer);
|
|
||||||
ContentManager *contentman = [ContentManager sharedInstance];
|
ContentManager *contentman = [ContentManager sharedInstance];
|
||||||
|
|
||||||
if( [chunks count] > 0 && tag == READ_TAG ) {
|
if( chunks && [chunks count] > 0 && tag == READ_TAG ) {
|
||||||
|
NSLog(@"READ from socket (%ld): <%@>", tag, answer);
|
||||||
if( [[chunks objectAtIndex:0] isEqualToString:@"STATUS"] ) {
|
if( [[chunks objectAtIndex:0] isEqualToString:@"STATUS"] ) {
|
||||||
NSString *path = [chunks objectAtIndex:2];
|
NSString *path = [chunks objectAtIndex:2];
|
||||||
if( [chunks count] > 3 ) {
|
if( [chunks count] > 3 ) {
|
||||||
@@ -168,8 +168,8 @@ static RequestManager* sharedInstance = nil;
|
|||||||
} else {
|
} else {
|
||||||
NSLog(@"Unknown command %@", [chunks objectAtIndex:0]);
|
NSLog(@"Unknown command %@", [chunks objectAtIndex:0]);
|
||||||
}
|
}
|
||||||
} else {
|
} else if (tag != READ_TAG) {
|
||||||
NSLog(@"Received unknown tag %ld", tag);
|
NSLog(@"Received unknown tag %ld <%@>", tag, answer);
|
||||||
}
|
}
|
||||||
// Read on and on
|
// Read on and on
|
||||||
NSData* stop = [@"\n" dataUsingEncoding:NSUTF8StringEncoding];
|
NSData* stop = [@"\n" dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
@@ -202,7 +202,7 @@ static RequestManager* sharedInstance = nil;
|
|||||||
if( [_requestQueue count] > 0 ) {
|
if( [_requestQueue count] > 0 ) {
|
||||||
NSLog( @"We have to empty the queue");
|
NSLog( @"We have to empty the queue");
|
||||||
for( NSString *path in _requestQueue ) {
|
for( NSString *path in _requestQueue ) {
|
||||||
[self askOnSocket:path];
|
[self askOnSocket:path query:@"RETRIEVE_FILE_STATUS"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,7 +253,7 @@ static RequestManager* sharedInstance = nil;
|
|||||||
NSLog(@"I goofed: %@", err);
|
NSLog(@"I goofed: %@", err);
|
||||||
}
|
}
|
||||||
} else if (!useTcp) {
|
} else if (!useTcp) {
|
||||||
NSURL *url;
|
NSURL *url = nil;
|
||||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||||
if ([paths count])
|
if ([paths count])
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ static NSString* globalLock = @"I'm the global lock to prevent concruent handler
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
static bool liferayNativityLoaded = false;
|
static bool liferayNativityLoaded = false;
|
||||||
static NSString* liferayNativityBundleName = @"OwnCloudFinder";
|
static NSString* liferayNativityBundleName = @"SyncStateFinder";
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
NSString* location;
|
NSString* location;
|
||||||
@@ -85,7 +85,7 @@ static OSErr loadBundle(LNBundleType type, AppleEvent* reply, long refcon) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isLoaded) {
|
if (isLoaded) {
|
||||||
NSLog(@"LiferayNativityInjector: %@ already loaded.", bundleName);
|
NSLog(@"OwnCloudInjector: %@ already loaded.", bundleName);
|
||||||
return noErr;
|
return noErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
0B36CB92182461A10039B237 /* OwnCloudFinder.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 0B36CB91182461A10039B237 /* OwnCloudFinder.bundle */; };
|
0B36CB92182461A10039B237 /* SyncStateFinder.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 0B36CB91182461A10039B237 /* SyncStateFinder.bundle */; };
|
||||||
0BD9C38E1778EF450094CF5D /* license.txt in Resources */ = {isa = PBXBuildFile; fileRef = 0BD9C38D1778EF450094CF5D /* license.txt */; };
|
0BD9C38E1778EF450094CF5D /* license.txt in Resources */ = {isa = PBXBuildFile; fileRef = 0BD9C38D1778EF450094CF5D /* license.txt */; };
|
||||||
8D576314048677EA00EA77CD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */; };
|
8D576314048677EA00EA77CD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */; };
|
||||||
8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8D5B49A704867FD3000E48DA /* InfoPlist.strings */; };
|
8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8D5B49A704867FD3000E48DA /* InfoPlist.strings */; };
|
||||||
@@ -19,10 +19,10 @@
|
|||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||||
0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
|
0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
|
||||||
0B36CB91182461A10039B237 /* OwnCloudFinder.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; path = OwnCloudFinder.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
0B36CB91182461A10039B237 /* SyncStateFinder.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; path = SyncStateFinder.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
0BD9C38D1778EF450094CF5D /* license.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = license.txt; sourceTree = "<group>"; };
|
0BD9C38D1778EF450094CF5D /* license.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = license.txt; sourceTree = "<group>"; };
|
||||||
8D576317048677EA00EA77CD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
8D576317048677EA00EA77CD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
D60A992314CE37030061AD6D /* OwnCloudFinder.osax */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OwnCloudFinder.osax; sourceTree = BUILT_PRODUCTS_DIR; };
|
D60A992314CE37030061AD6D /* SyncStateFinder.osax */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SyncStateFinder.osax; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
D6ACBE9E117B7D5600F6691C /* OwnCloudInjector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OwnCloudInjector.m; sourceTree = "<group>"; };
|
D6ACBE9E117B7D5600F6691C /* OwnCloudInjector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OwnCloudInjector.m; sourceTree = "<group>"; };
|
||||||
D6ACBE9F117B7D5600F6691C /* LNVersionComparisonProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNVersionComparisonProtocol.h; sourceTree = "<group>"; };
|
D6ACBE9F117B7D5600F6691C /* LNVersionComparisonProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNVersionComparisonProtocol.h; sourceTree = "<group>"; };
|
||||||
D6ACBEA0117B7D5600F6691C /* LNStandardVersionComparator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNStandardVersionComparator.m; sourceTree = "<group>"; };
|
D6ACBEA0117B7D5600F6691C /* LNStandardVersionComparator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNStandardVersionComparator.m; sourceTree = "<group>"; };
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
D60A992414CE37030061AD6D /* Products */,
|
D60A992414CE37030061AD6D /* Products */,
|
||||||
);
|
);
|
||||||
indentWidth = 2;
|
indentWidth = 2;
|
||||||
name = "TotalFinder-osax";
|
name = "SyncStateFinder-osax";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
tabWidth = 2;
|
tabWidth = 2;
|
||||||
usesTabs = 0;
|
usesTabs = 0;
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
089C167CFE841241C02AAC07 /* Resources */ = {
|
089C167CFE841241C02AAC07 /* Resources */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
0B36CB91182461A10039B237 /* OwnCloudFinder.bundle */,
|
0B36CB91182461A10039B237 /* SyncStateFinder.bundle */,
|
||||||
D6ACBEA4117B7D6100F6691C /* OwnCloudInjector.sdef */,
|
D6ACBEA4117B7D6100F6691C /* OwnCloudInjector.sdef */,
|
||||||
8D576317048677EA00EA77CD /* Info.plist */,
|
8D576317048677EA00EA77CD /* Info.plist */,
|
||||||
8D5B49A704867FD3000E48DA /* InfoPlist.strings */,
|
8D5B49A704867FD3000E48DA /* InfoPlist.strings */,
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
D60A992414CE37030061AD6D /* Products */ = {
|
D60A992414CE37030061AD6D /* Products */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
D60A992314CE37030061AD6D /* OwnCloudFinder.osax */,
|
D60A992314CE37030061AD6D /* SyncStateFinder.osax */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -98,9 +98,9 @@
|
|||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
8D57630D048677EA00EA77CD /* OwnCloudFinder.osax */ = {
|
8D57630D048677EA00EA77CD /* SyncStateFinder.osax */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "OwnCloudFinder.osax" */;
|
buildConfigurationList = 1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "SyncStateFinder.osax" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
8D57630F048677EA00EA77CD /* Resources */,
|
8D57630F048677EA00EA77CD /* Resources */,
|
||||||
8D576311048677EA00EA77CD /* Sources */,
|
8D576311048677EA00EA77CD /* Sources */,
|
||||||
@@ -110,10 +110,10 @@
|
|||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
);
|
);
|
||||||
name = OwnCloudFinder.osax;
|
name = SyncStateFinder.osax;
|
||||||
productInstallPath = "$(HOME)/Library/Bundles";
|
productInstallPath = "$(HOME)/Library/Bundles";
|
||||||
productName = "TotalFinder-osax";
|
productName = "SyncStateFinder-osax";
|
||||||
productReference = D60A992314CE37030061AD6D /* OwnCloudFinder.osax */;
|
productReference = D60A992314CE37030061AD6D /* SyncStateFinder.osax */;
|
||||||
productType = "com.apple.product-type.bundle";
|
productType = "com.apple.product-type.bundle";
|
||||||
};
|
};
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
8D57630D048677EA00EA77CD /* OwnCloudFinder.osax */,
|
8D57630D048677EA00EA77CD /* SyncStateFinder.osax */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
@@ -149,7 +149,7 @@
|
|||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
0B36CB92182461A10039B237 /* OwnCloudFinder.bundle in Resources */,
|
0B36CB92182461A10039B237 /* SyncStateFinder.bundle in Resources */,
|
||||||
8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */,
|
8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */,
|
||||||
D6ACBEA5117B7D6100F6691C /* OwnCloudInjector.sdef in Resources */,
|
D6ACBEA5117B7D6100F6691C /* OwnCloudInjector.sdef in Resources */,
|
||||||
0BD9C38E1778EF450094CF5D /* license.txt in Resources */,
|
0BD9C38E1778EF450094CF5D /* license.txt in Resources */,
|
||||||
@@ -195,7 +195,7 @@
|
|||||||
"-framework",
|
"-framework",
|
||||||
AppKit,
|
AppKit,
|
||||||
);
|
);
|
||||||
PRODUCT_NAME = OwnCloudFinder;
|
PRODUCT_NAME = SyncStateFinder;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
WRAPPER_EXTENSION = osax;
|
WRAPPER_EXTENSION = osax;
|
||||||
};
|
};
|
||||||
@@ -214,7 +214,7 @@
|
|||||||
"-framework",
|
"-framework",
|
||||||
AppKit,
|
AppKit,
|
||||||
);
|
);
|
||||||
PRODUCT_NAME = OwnCloudFinder;
|
PRODUCT_NAME = SyncStateFinder;
|
||||||
WRAPPER_EXTENSION = osax;
|
WRAPPER_EXTENSION = osax;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
@@ -245,7 +245,7 @@
|
|||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "OwnCloudFinder.osax" */ = {
|
1DEB911A08733D790010E9CD /* Build configuration list for PBXNativeTarget "SyncStateFinder.osax" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
1DEB911B08733D790010E9CD /* Debug */,
|
1DEB911B08733D790010E9CD /* Debug */,
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = "primary"
|
BuildableIdentifier = "primary"
|
||||||
BlueprintIdentifier = "8D57630D048677EA00EA77CD"
|
BlueprintIdentifier = "8D57630D048677EA00EA77CD"
|
||||||
BuildableName = "OwnCloudFinder.bundle"
|
BuildableName = "SyncStateFinder.bundle"
|
||||||
BlueprintName = "OwnCloudFinder"
|
BlueprintName = "SyncStateFinder"
|
||||||
ReferencedContainer = "container:../OwnCloudFinder/OwnCloudFinder.xcodeproj">
|
ReferencedContainer = "container:../OwnCloudFinder/OwnCloudFinder.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildActionEntry>
|
</BuildActionEntry>
|
||||||
@@ -29,8 +29,8 @@
|
|||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = "primary"
|
BuildableIdentifier = "primary"
|
||||||
BlueprintIdentifier = "8D57630D048677EA00EA77CD"
|
BlueprintIdentifier = "8D57630D048677EA00EA77CD"
|
||||||
BuildableName = "OwnCloudFinder.osax"
|
BuildableName = "SyncStateFinder.osax"
|
||||||
BlueprintName = "OwnCloudFinder.osax"
|
BlueprintName = "SyncStateFinder.osax"
|
||||||
ReferencedContainer = "container:OwnCloudInjector.xcodeproj">
|
ReferencedContainer = "container:OwnCloudInjector.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildActionEntry>
|
</BuildActionEntry>
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# osascript $HOME/owncloud.com/mirall/shell_integration/MacOSX/unload.scpt
|
# osascript $HOME/owncloud.com/mirall/shell_integration/MacOSX/unload.scpt
|
||||||
|
|
||||||
sudo rm -rf /Library/ScriptingAdditions/OwnCloudFinder.osax
|
sudo rm -rf /Library/ScriptingAdditions/SyncStateFinder.osax
|
||||||
# Klaas' machine
|
# Klaas' machine
|
||||||
OSAXDIR=$HOME/Library/Developer/Xcode/DerivedData/OwnCloud-*/Build/Products/Debug/OwnCloudFinder.osax
|
OSAXDIR=$HOME/Library/Developer/Xcode/DerivedData/OwnCloud-*/Build/Products/Debug/SyncStateFinder.osax
|
||||||
[ -d $OSAXDIR ] ||OSAXDIR=$HOME/Library/Developer/Xcode/DerivedData/OwnCloud-*/Build/Intermediates/ArchiveIntermediates/OwnCloudFinder.osax/IntermediateBuildFilesPath/UninstalledProducts/OwnCloudFinder.osax
|
[ -d $OSAXDIR ] ||OSAXDIR=$HOME/Library/Developer/Xcode/DerivedData/OwnCloud-*/Build/Intermediates/ArchiveIntermediates/SyncStateFinder.osax/IntermediateBuildFilesPath/UninstalledProducts/SyncStateFinder.osax
|
||||||
|
|
||||||
# Markus' machine
|
# Markus' machine
|
||||||
[ -d $OSAXDIR ] || echo "OSAX does not exist"
|
[ -d $OSAXDIR ] || echo "OSAX does not exist"
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ class syncStateExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.Info
|
|||||||
GObject.timeout_add(5000, self.connectToSocketServer)
|
GObject.timeout_add(5000, self.connectToSocketServer)
|
||||||
|
|
||||||
def connectToSocketServer(self):
|
def connectToSocketServer(self):
|
||||||
|
do_reconnect = True
|
||||||
try:
|
try:
|
||||||
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||||
postfix = "/"+self.appname+"/socket"
|
postfix = "/"+self.appname+"/socket"
|
||||||
@@ -44,15 +45,18 @@ class syncStateExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.Info
|
|||||||
print("Socket File: "+sock_file)
|
print("Socket File: "+sock_file)
|
||||||
self.sock.connect(sock_file)
|
self.sock.connect(sock_file)
|
||||||
self.connected = True
|
self.connected = True
|
||||||
|
print("Setting connected to %r" % self.connected )
|
||||||
self.watch_id = GObject.io_add_watch(self.sock, GObject.IO_IN, self.handle_notify)
|
self.watch_id = GObject.io_add_watch(self.sock, GObject.IO_IN, self.handle_notify)
|
||||||
except:
|
do_reconnect = False
|
||||||
print("Could not connect to unix socket.")
|
except Exception, e:
|
||||||
|
print("Could not connect to unix socket." + str(e))
|
||||||
else:
|
else:
|
||||||
print("Sock-File not valid: "+sock_file)
|
print("Sock-File not valid: "+sock_file)
|
||||||
except:
|
except Exception, e:
|
||||||
print("Connect could not be established, try again later!")
|
print("Connect could not be established, try again later " + str(e))
|
||||||
self.sock.close()
|
self.sock.close()
|
||||||
return not self.connected
|
# print("Returning %r" % do_reconnect)
|
||||||
|
return do_reconnect
|
||||||
|
|
||||||
def sendCommand(self, cmd):
|
def sendCommand(self, cmd):
|
||||||
if self.connected:
|
if self.connected:
|
||||||
@@ -122,7 +126,7 @@ class syncStateExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.Info
|
|||||||
if( not itemStore['state'] or newState != itemStore['state'] ):
|
if( not itemStore['state'] or newState != itemStore['state'] ):
|
||||||
item = itemStore['item']
|
item = itemStore['item']
|
||||||
item.add_emblem(emblem)
|
item.add_emblem(emblem)
|
||||||
# print "Setting emblem on " + parts[2]
|
# print "Setting emblem on " + parts[2]+ "<>"+emblem+"<>"
|
||||||
self.nautilusVFSFile_table[parts[2]] = {'item': item, 'state':newState}
|
self.nautilusVFSFile_table[parts[2]] = {'item': item, 'state':newState}
|
||||||
|
|
||||||
elif action == 'UPDATE_VIEW':
|
elif action == 'UPDATE_VIEW':
|
||||||
@@ -191,4 +195,5 @@ class syncStateExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.Info
|
|||||||
self.askForOverlay(filename)
|
self.askForOverlay(filename)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
print("Not in scope:"+filename)
|
# print("Not in scope:"+filename)
|
||||||
|
pass
|
||||||
|
|||||||
@@ -1,3 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QLocalSocket>
|
#include <QLocalSocket>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
|||||||
@@ -1,3 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "socketclient.h"
|
#include "socketclient.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef SOCKETCLIENT_H
|
#ifndef SOCKETCLIENT_H
|
||||||
#define SOCKETCLIENT_H
|
#define SOCKETCLIENT_H
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "ui_window.h"
|
#include "ui_window.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef WINDOW_H
|
#ifndef WINDOW_H
|
||||||
#define WINDOW_H
|
#define WINDOW_H
|
||||||
|
|
||||||
|
|||||||
@@ -36,17 +36,13 @@ extern HINSTANCE instanceHandle;
|
|||||||
#define IDM_DISPLAY 0
|
#define IDM_DISPLAY 0
|
||||||
#define IDB_OK 101
|
#define IDB_OK 101
|
||||||
|
|
||||||
namespace {
|
|
||||||
static std::vector<std::wstring> s_watchedDirectories;
|
|
||||||
}
|
|
||||||
|
|
||||||
OCOverlay::OCOverlay(int state)
|
OCOverlay::OCOverlay(int state)
|
||||||
: _communicationSocket(0)
|
: _referenceCount(1)
|
||||||
, _referenceCount(1)
|
|
||||||
, _checker(new RemotePathChecker(PORT))
|
|
||||||
, _state(state)
|
, _state(state)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
static RemotePathChecker s_remotePathChecker;
|
||||||
|
_checker = &s_remotePathChecker;
|
||||||
}
|
}
|
||||||
|
|
||||||
OCOverlay::~OCOverlay(void)
|
OCOverlay::~OCOverlay(void)
|
||||||
@@ -121,23 +117,13 @@ IFACEMETHODIMP OCOverlay::GetPriority(int *pPriority)
|
|||||||
|
|
||||||
IFACEMETHODIMP OCOverlay::IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib)
|
IFACEMETHODIMP OCOverlay::IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib)
|
||||||
{
|
{
|
||||||
|
auto watchedDirectories = _checker->WatchedDirectories();
|
||||||
//if(!_IsOverlaysEnabled())
|
|
||||||
//{
|
|
||||||
// return MAKE_HRESULT(S_FALSE, 0, 0);
|
|
||||||
//}
|
|
||||||
|
|
||||||
// FIXME: Use Registry instead, this will only trigger once
|
|
||||||
// and now follow any user changes in the client
|
|
||||||
if (s_watchedDirectories.empty()) {
|
|
||||||
s_watchedDirectories = _checker->WatchedDirectories();
|
|
||||||
}
|
|
||||||
|
|
||||||
wstring wpath(pwszPath);
|
wstring wpath(pwszPath);
|
||||||
wpath.append(L"\\");
|
//wpath.append(L"\\");
|
||||||
vector<wstring>::iterator it;
|
vector<wstring>::iterator it;
|
||||||
bool watched = false;
|
bool watched = false;
|
||||||
for (it = s_watchedDirectories.begin(); it != s_watchedDirectories.end(); ++it) {
|
for (it = watchedDirectories.begin(); it != watchedDirectories.end(); ++it) {
|
||||||
if (StringUtil::begins_with(wpath, *it)) {
|
if (StringUtil::begins_with(wpath, *it)) {
|
||||||
watched = true;
|
watched = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,14 +35,13 @@ public:
|
|||||||
IFACEMETHODIMP_(ULONG) Release();
|
IFACEMETHODIMP_(ULONG) Release();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~OCOverlay(void);
|
~OCOverlay();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//bool _GenerateMessage(const wchar_t*, std::wstring*);
|
//bool _GenerateMessage(const wchar_t*, std::wstring*);
|
||||||
|
|
||||||
bool _IsOverlaysEnabled();
|
bool _IsOverlaysEnabled();
|
||||||
long _referenceCount;
|
long _referenceCount;
|
||||||
CommunicationSocket* _communicationSocket;
|
|
||||||
RemotePathChecker* _checker;
|
RemotePathChecker* _checker;
|
||||||
int _state;
|
int _state;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ HRESULT OCOverlayRegistrationHandler::RemoveRegistryEntries(PCWSTR friendlyName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
HKEY syncExOverlayKey = NULL;
|
HKEY syncExOverlayKey = NULL;
|
||||||
hResult = HRESULT_FROM_WIN32(RegDeleteKeyEx(shellOverlayKey, friendlyName, DELETE, 0));
|
hResult = HRESULT_FROM_WIN32(RegDeleteKey(shellOverlayKey, friendlyName));
|
||||||
if (!SUCCEEDED(hResult)) {
|
if (!SUCCEEDED(hResult)) {
|
||||||
return hResult;
|
return hResult;
|
||||||
}
|
}
|
||||||
@@ -137,12 +137,12 @@ HRESULT OCOverlayRegistrationHandler::UnregisterCOMObject(const CLSID& clsid)
|
|||||||
return hResult;
|
return hResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
hResult = HRESULT_FROM_WIN32(RegDeleteKeyEx(clsidKey, REGISTRY_IN_PROCESS, DELETE, 0));
|
hResult = HRESULT_FROM_WIN32(RegDeleteKey(clsidKey, REGISTRY_IN_PROCESS));
|
||||||
if(!SUCCEEDED(hResult)) {
|
if(!SUCCEEDED(hResult)) {
|
||||||
return hResult;
|
return hResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
hResult = HRESULT_FROM_WIN32(RegDeleteKeyEx(hKey, stringCLSID, DELETE, 0));
|
hResult = HRESULT_FROM_WIN32(RegDeleteKey(hKey, stringCLSID));
|
||||||
if(!SUCCEEDED(hResult)) {
|
if(!SUCCEEDED(hResult)) {
|
||||||
return hResult;
|
return hResult;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
@@ -30,8 +31,8 @@ using namespace std;
|
|||||||
|
|
||||||
#define DEFAULT_BUFLEN 4096
|
#define DEFAULT_BUFLEN 4096
|
||||||
|
|
||||||
CommunicationSocket::CommunicationSocket(int port)
|
CommunicationSocket::CommunicationSocket()
|
||||||
: _port(port), _clientSocket(INVALID_SOCKET)
|
: _pipe(INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,64 +44,39 @@ CommunicationSocket::~CommunicationSocket()
|
|||||||
bool CommunicationSocket::Close()
|
bool CommunicationSocket::Close()
|
||||||
{
|
{
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
bool closed = (closesocket(_clientSocket) == 0);
|
if (_pipe == INVALID_HANDLE_VALUE) {
|
||||||
shutdown(_clientSocket, SD_BOTH);
|
return false;
|
||||||
_clientSocket = INVALID_SOCKET;
|
}
|
||||||
return closed;
|
CloseHandle(_pipe);
|
||||||
|
_pipe = INVALID_HANDLE_VALUE;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CommunicationSocket::Connect()
|
bool CommunicationSocket::Connect(const std::wstring &pipename)
|
||||||
{
|
{
|
||||||
WSADATA wsaData;
|
_pipe = CreateFile(pipename.data(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
|
|
||||||
HRESULT iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
if (_pipe == INVALID_HANDLE_VALUE) {
|
||||||
|
return false;
|
||||||
if (iResult != NO_ERROR) {
|
}
|
||||||
int error = WSAGetLastError();
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
_clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
||||||
|
|
||||||
if (_clientSocket == INVALID_SOCKET) {
|
|
||||||
//int error = WSAGetLastError();
|
|
||||||
Close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_in clientService;
|
|
||||||
|
|
||||||
clientService.sin_family = AF_INET;
|
|
||||||
clientService.sin_addr.s_addr = inet_addr(PLUG_IN_SOCKET_ADDRESS);
|
|
||||||
clientService.sin_port = htons(_port);
|
|
||||||
|
|
||||||
iResult = connect(_clientSocket, (SOCKADDR*)&clientService, sizeof(clientService));
|
|
||||||
DWORD timeout = 500; // ms
|
|
||||||
setsockopt(_clientSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*) &timeout, sizeof(DWORD));
|
|
||||||
|
|
||||||
if (iResult == SOCKET_ERROR) {
|
|
||||||
//int error = WSAGetLastError();
|
|
||||||
Close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommunicationSocket::SendMsg(const wchar_t* message)
|
bool CommunicationSocket::SendMsg(const wchar_t* message)
|
||||||
{
|
{
|
||||||
const char* utf8_msg = StringUtil::toUtf8(message);
|
auto utf8_msg = StringUtil::toUtf8(message);
|
||||||
size_t result = send(_clientSocket, utf8_msg, (int)strlen(utf8_msg), 0);
|
|
||||||
delete[] utf8_msg;
|
|
||||||
|
|
||||||
if (result == SOCKET_ERROR) {
|
DWORD numBytesWritten = 0;
|
||||||
//int error = WSAGetLastError();
|
auto result = WriteFile( _pipe, utf8_msg.c_str(), DWORD(utf8_msg.size()), &numBytesWritten, NULL);
|
||||||
closesocket(_clientSocket);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
if (result) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
Close();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommunicationSocket::ReadLine(wstring* response)
|
bool CommunicationSocket::ReadLine(wstring* response)
|
||||||
@@ -109,21 +85,43 @@ bool CommunicationSocket::ReadLine(wstring* response)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<char> resp_utf8;
|
response->clear();
|
||||||
char buffer;
|
|
||||||
|
if (_pipe == INVALID_HANDLE_VALUE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
int bytesRead = recv(_clientSocket, &buffer, 1, 0);
|
int lbPos = 0;
|
||||||
if (bytesRead <= 0) {
|
auto it = std::find(_buffer.begin() + lbPos, _buffer.end(), '\n');
|
||||||
response = 0;
|
if (it != _buffer.end()) {
|
||||||
|
*response = StringUtil::toUtf16(_buffer.data(), DWORD(it - _buffer.begin()));
|
||||||
|
_buffer.erase(_buffer.begin(), it + 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<char, 128> resp_utf8;
|
||||||
|
DWORD numBytesRead = 0;
|
||||||
|
DWORD totalBytesAvailable = 0;
|
||||||
|
auto result = PeekNamedPipe(_pipe, NULL, 0, 0, &totalBytesAvailable, 0);
|
||||||
|
if (!result) {
|
||||||
|
Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (totalBytesAvailable == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer == '\n') {
|
result = ReadFile(_pipe, resp_utf8.data(), DWORD(resp_utf8.size()), &numBytesRead, NULL);
|
||||||
resp_utf8.push_back(0);
|
if (!result) {
|
||||||
*response = StringUtil::toUtf16(&resp_utf8[0], resp_utf8.size());
|
Close();
|
||||||
return true;
|
return false;
|
||||||
} else {
|
}
|
||||||
resp_utf8.push_back(buffer);
|
if (numBytesRead <= 0) {
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
_buffer.insert(_buffer.end(), resp_utf8.begin(), resp_utf8.begin()+numBytesRead);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,23 +20,27 @@
|
|||||||
#pragma warning (disable : 4251)
|
#pragma warning (disable : 4251)
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include <WinSock2.h>
|
#include <WinSock2.h>
|
||||||
|
|
||||||
class __declspec(dllexport) CommunicationSocket
|
class __declspec(dllexport) CommunicationSocket
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CommunicationSocket(int port);
|
CommunicationSocket();
|
||||||
~CommunicationSocket();
|
~CommunicationSocket();
|
||||||
|
|
||||||
bool Connect();
|
bool Connect(const std::wstring& pipename);
|
||||||
bool Close();
|
bool Close();
|
||||||
|
|
||||||
bool SendMsg(const wchar_t*);
|
bool SendMsg(const wchar_t*);
|
||||||
bool ReadLine(std::wstring*);
|
bool ReadLine(std::wstring*);
|
||||||
|
|
||||||
|
HANDLE Event() { return _pipe; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _port;
|
HANDLE _pipe;
|
||||||
SOCKET _clientSocket;
|
std::vector<char> _buffer;
|
||||||
|
bool _connected;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -16,92 +16,188 @@
|
|||||||
#include "RemotePathChecker.h"
|
#include "RemotePathChecker.h"
|
||||||
#include "StringUtil.h"
|
#include "StringUtil.h"
|
||||||
|
|
||||||
|
#include <shlobj.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include <shlobj.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
RemotePathChecker::RemotePathChecker(int port)
|
|
||||||
: _port(port)
|
// This code is run in a thread
|
||||||
|
void RemotePathChecker::workerThreadLoop()
|
||||||
{
|
{
|
||||||
|
auto pipename = std::wstring(L"\\\\.\\pipe\\");
|
||||||
|
pipename += L"ownCloud";
|
||||||
|
|
||||||
|
bool connected = false;
|
||||||
|
CommunicationSocket socket;
|
||||||
|
std::unordered_set<std::wstring> asked;
|
||||||
|
|
||||||
|
while(!_stop) {
|
||||||
|
Sleep(50);
|
||||||
|
|
||||||
|
if (!connected) {
|
||||||
|
asked.clear();
|
||||||
|
if (!WaitNamedPipe(pipename.data(), 5 * 1000)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!socket.Connect(pipename)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
connected = true;
|
||||||
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
|
_connected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
|
while (!_pending.empty() && !_stop) {
|
||||||
|
auto filePath = _pending.front();
|
||||||
|
_pending.pop();
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
if (!asked.count(filePath)) {
|
||||||
|
asked.insert(filePath);
|
||||||
|
socket.SendMsg(wstring(L"RETRIEVE_FILE_STATUS:" + filePath + L'\n').data());
|
||||||
|
}
|
||||||
|
lock.lock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring response;
|
||||||
|
while (!_stop && socket.ReadLine(&response)) {
|
||||||
|
if (StringUtil::begins_with(response, wstring(L"REGISTER_PATH:"))) {
|
||||||
|
wstring responsePath = response.substr(14); // length of REGISTER_PATH:
|
||||||
|
|
||||||
|
{ std::unique_lock<std::mutex> lock(_mutex);
|
||||||
|
_watchedDirectories.push_back(responsePath);
|
||||||
|
}
|
||||||
|
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATH | SHCNF_FLUSHNOWAIT, responsePath.data(), NULL);
|
||||||
|
} else if (StringUtil::begins_with(response, wstring(L"UNREGISTER_PATH:"))) {
|
||||||
|
wstring responsePath = response.substr(16); // length of UNREGISTER_PATH:
|
||||||
|
|
||||||
|
{ std::unique_lock<std::mutex> lock(_mutex);
|
||||||
|
_watchedDirectories.erase(
|
||||||
|
std::remove(_watchedDirectories.begin(), _watchedDirectories.end(), responsePath),
|
||||||
|
_watchedDirectories.end());
|
||||||
|
|
||||||
|
// Remove any item from the cache
|
||||||
|
for (auto it = _cache.begin(); it != _cache.end() ; ) {
|
||||||
|
if (StringUtil::begins_with(it->first, responsePath)) {
|
||||||
|
it = _cache.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATH | SHCNF_FLUSHNOWAIT, responsePath.data(), NULL);
|
||||||
|
} else if (StringUtil::begins_with(response, wstring(L"STATUS:")) ||
|
||||||
|
StringUtil::begins_with(response, wstring(L"BROADCAST:"))) {
|
||||||
|
|
||||||
|
auto statusBegin = response.find(L':', 0);
|
||||||
|
assert(statusBegin != std::wstring::npos);
|
||||||
|
|
||||||
|
auto statusEnd = response.find(L':', statusBegin + 1);
|
||||||
|
if (statusEnd == std::wstring::npos) {
|
||||||
|
// the command do not contains two colon?
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto responseStatus = response.substr(statusBegin+1, statusEnd - statusBegin-1);
|
||||||
|
auto responsePath = response.substr(statusEnd+1);
|
||||||
|
auto state = _StrToFileState(responseStatus);
|
||||||
|
auto erased = asked.erase(responsePath);
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
{ std::unique_lock<std::mutex> lock(_mutex);
|
||||||
|
auto &it = _cache[responsePath];
|
||||||
|
changed = (it != state);
|
||||||
|
it = state;
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH | SHCNF_FLUSHNOWAIT, responsePath.data(), NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (StringUtil::begins_with(response, wstring(L"UPDATE_VIEW"))) {
|
||||||
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
|
// Request a status for all the items in the cache.
|
||||||
|
for (auto it = _cache.begin(); it != _cache.end(); ++it) {
|
||||||
|
if (!socket.SendMsg(wstring(L"RETRIEVE_FILE_STATUS:" + it->first + L'\n').data())) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (socket.Event() == INVALID_HANDLE_VALUE) {
|
||||||
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
|
_cache.clear();
|
||||||
|
_watchedDirectories.clear();
|
||||||
|
_connected = connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_stop) return;
|
||||||
|
|
||||||
|
HANDLE handles[2] = { _newQueries, socket.Event() };
|
||||||
|
WaitForMultipleObjects(2, handles, false, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
RemotePathChecker::RemotePathChecker()
|
||||||
|
: _connected(false)
|
||||||
|
, _newQueries(CreateEvent(NULL, true, true, NULL))
|
||||||
|
, _thread([this]{ this->workerThreadLoop(); })
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RemotePathChecker::~RemotePathChecker()
|
||||||
|
{
|
||||||
|
_stop = true;
|
||||||
|
//_newQueries.notify_all();
|
||||||
|
SetEvent(_newQueries);
|
||||||
|
_thread.join();
|
||||||
|
CloseHandle(_newQueries);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<wstring> RemotePathChecker::WatchedDirectories()
|
vector<wstring> RemotePathChecker::WatchedDirectories()
|
||||||
{
|
{
|
||||||
vector<wstring> watchedDirectories;
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
wstring response;
|
return _watchedDirectories;
|
||||||
bool needed = false;
|
|
||||||
|
|
||||||
CommunicationSocket socket(_port);
|
|
||||||
socket.Connect();
|
|
||||||
|
|
||||||
while (socket.ReadLine(&response)) {
|
|
||||||
if (StringUtil::begins_with(response, wstring(L"REGISTER_PATH:"))) {
|
|
||||||
size_t pathBegin = response.find(L':', 0);
|
|
||||||
if (pathBegin == -1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// chop trailing '\n'
|
|
||||||
wstring responsePath = response.substr(pathBegin + 1, response.length()-1);
|
|
||||||
watchedDirectories.push_back(responsePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return watchedDirectories;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RemotePathChecker::IsMonitoredPath(const wchar_t* filePath, int* state)
|
bool RemotePathChecker::IsMonitoredPath(const wchar_t* filePath, int* state)
|
||||||
{
|
{
|
||||||
wstring request;
|
assert(state); assert(filePath);
|
||||||
wstring response;
|
|
||||||
bool needed = false;
|
|
||||||
|
|
||||||
CommunicationSocket socket(_port);
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
socket.Connect();
|
if (!_connected) {
|
||||||
request = L"RETRIEVE_FILE_STATUS:";
|
return false;
|
||||||
request += filePath;
|
}
|
||||||
request += L'\n';
|
|
||||||
|
|
||||||
if (!socket.SendMsg(request.c_str())) {
|
auto path = std::wstring(filePath);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (socket.ReadLine(&response)) {
|
auto it = _cache.find(path);
|
||||||
// discard broadcast messages
|
if (it != _cache.end()) {
|
||||||
if (StringUtil::begins_with(response, wstring(L"STATUS:"))) {
|
*state = it->second;
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
size_t statusBegin = response.find(L':', 0);
|
_pending.push(filePath);
|
||||||
if (statusBegin == -1)
|
SetEvent(_newQueries);
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
size_t statusEnd = response.find(L':', statusBegin + 1);
|
|
||||||
if (statusEnd == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
|
|
||||||
wstring responseStatus = response.substr(statusBegin+1, statusEnd - statusBegin-1);
|
|
||||||
wstring responsePath = response.substr(statusEnd+1);
|
|
||||||
if (responsePath == filePath) {
|
|
||||||
if (!state) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*state = _StrToFileState(responseStatus);
|
|
||||||
if (*state == StateNone) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
needed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return needed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int RemotePathChecker::_StrToFileState(const std::wstring &str)
|
RemotePathChecker::FileState RemotePathChecker::_StrToFileState(const std::wstring &str)
|
||||||
{
|
{
|
||||||
if (str == L"NOP" || str == L"NONE") {
|
if (str == L"NOP" || str == L"NONE") {
|
||||||
return StateNone;
|
return StateNone;
|
||||||
|
|||||||
@@ -16,6 +16,12 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <queue>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <atomic>
|
||||||
|
#include <condition_variable>
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@@ -29,14 +35,33 @@ public:
|
|||||||
StateWarning, StateWarningSWM,
|
StateWarning, StateWarningSWM,
|
||||||
StateNone
|
StateNone
|
||||||
};
|
};
|
||||||
RemotePathChecker(int port);
|
RemotePathChecker();
|
||||||
|
~RemotePathChecker();
|
||||||
std::vector<std::wstring> WatchedDirectories();
|
std::vector<std::wstring> WatchedDirectories();
|
||||||
bool IsMonitoredPath(const wchar_t* filePath, int* state);
|
bool IsMonitoredPath(const wchar_t* filePath, int* state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _StrToFileState(const std::wstring &str);
|
FileState _StrToFileState(const std::wstring &str);
|
||||||
int _port;
|
std::mutex _mutex;
|
||||||
|
std::atomic<bool> _stop;
|
||||||
|
|
||||||
|
// Everything here is protected by the _mutex
|
||||||
|
|
||||||
|
/** The list of paths we need to query. The main thread fill this, and the worker thread
|
||||||
|
* send that to the socket. */
|
||||||
|
std::queue<std::wstring> _pending;
|
||||||
|
|
||||||
|
std::unordered_map<std::wstring, FileState> _cache;
|
||||||
|
std::vector<std::wstring> _watchedDirectories;
|
||||||
|
bool _connected;
|
||||||
|
|
||||||
|
|
||||||
|
// The main thread notifies when there are new items in _pending
|
||||||
|
//std::condition_variable _newQueries;
|
||||||
|
HANDLE _newQueries;
|
||||||
|
|
||||||
|
std::thread _thread;
|
||||||
|
void workerThreadLoop();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -11,22 +11,26 @@
|
|||||||
* details.
|
* details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <locale>
|
||||||
|
#include <string>
|
||||||
|
#include <codecvt>
|
||||||
|
|
||||||
#include "StringUtil.h"
|
#include "StringUtil.h"
|
||||||
|
|
||||||
char* StringUtil::toUtf8(const wchar_t *utf16, int len)
|
std::string StringUtil::toUtf8(const wchar_t *utf16, int len)
|
||||||
{
|
{
|
||||||
int newlen = WideCharToMultiByte(CP_UTF8, 0, utf16, len, NULL, 0, NULL, NULL);
|
if (len < 0) {
|
||||||
char* str = new char[newlen];
|
len = wcslen(utf16);
|
||||||
WideCharToMultiByte(CP_UTF8, 0, utf16, -1, str, newlen, NULL, NULL);
|
}
|
||||||
return str;
|
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t> > converter;
|
||||||
|
return converter.to_bytes(utf16, utf16+len);
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t* StringUtil::toUtf16(const char *utf8, int len)
|
std::wstring StringUtil::toUtf16(const char *utf8, int len)
|
||||||
{
|
{
|
||||||
int newlen = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0);
|
if (len < 0) {
|
||||||
wchar_t* wstr = new wchar_t[newlen];
|
len = strlen(utf8);
|
||||||
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, newlen);
|
}
|
||||||
return wstr;
|
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t> > converter;
|
||||||
|
return converter.from_bytes(utf8, utf8+len);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,15 +20,14 @@
|
|||||||
|
|
||||||
class __declspec(dllexport) StringUtil {
|
class __declspec(dllexport) StringUtil {
|
||||||
public:
|
public:
|
||||||
static char* toUtf8(const wchar_t* utf16, int len = -1);
|
static std::string toUtf8(const wchar_t* utf16, int len = -1);
|
||||||
static wchar_t* toUtf16(const char* utf8, int len = -1);
|
static std::wstring toUtf16(const char* utf8, int len = -1);
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
static bool begins_with(const T& input, const T& match)
|
static bool begins_with(const T& input, const T& match)
|
||||||
{
|
{
|
||||||
return input.size() >= match.size()
|
return input.size() >= match.size()
|
||||||
&& equal(match.begin(), match.end(), input.begin());
|
&& std::equal(match.begin(), match.end(), input.begin());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
2
src/3rdparty/qtmacgoodies
vendored
2
src/3rdparty/qtmacgoodies
vendored
Submodule src/3rdparty/qtmacgoodies updated: fa06775714...10621d46b5
148882
src/3rdparty/sqlite3/sqlite3.c
vendored
Normal file
148882
src/3rdparty/sqlite3/sqlite3.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7494
src/3rdparty/sqlite3/sqlite3.h
vendored
Normal file
7494
src/3rdparty/sqlite3/sqlite3.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -75,6 +75,7 @@ set(libsync_SRCS
|
|||||||
mirall/propagator_legacy.cpp
|
mirall/propagator_legacy.cpp
|
||||||
mirall/syncjournalfilerecord.cpp
|
mirall/syncjournalfilerecord.cpp
|
||||||
mirall/syncjournaldb.cpp
|
mirall/syncjournaldb.cpp
|
||||||
|
mirall/ownsql.cpp
|
||||||
mirall/theme.cpp
|
mirall/theme.cpp
|
||||||
mirall/owncloudtheme.cpp
|
mirall/owncloudtheme.cpp
|
||||||
mirall/logger.cpp
|
mirall/logger.cpp
|
||||||
@@ -337,7 +338,6 @@ set(ownCloud ${ownCloud_old})
|
|||||||
if (WITH_DBUS)
|
if (WITH_DBUS)
|
||||||
set(ADDITIONAL_APP_MODULES DBus)
|
set(ADDITIONAL_APP_MODULES DBus)
|
||||||
endif(WITH_DBUS)
|
endif(WITH_DBUS)
|
||||||
|
|
||||||
if(NOT BUILD_OWNCLOUD_OSX_BUNDLE AND NOT BUILD_LIBRARIES_ONLY)
|
if(NOT BUILD_OWNCLOUD_OSX_BUNDLE AND NOT BUILD_LIBRARIES_ONLY)
|
||||||
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
||||||
|
|
||||||
@@ -368,8 +368,15 @@ elseif(NOT BUILD_LIBRARIES_ONLY)
|
|||||||
|
|
||||||
set (QM_DIR ${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/Translations)
|
set (QM_DIR ${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/Translations)
|
||||||
install(FILES ${mirall_I18N} DESTINATION ${QM_DIR})
|
install(FILES ${mirall_I18N} DESTINATION ${QM_DIR})
|
||||||
|
get_target_property(_qmake Qt5::qmake LOCATION)
|
||||||
|
execute_process(COMMAND ${_qmake} -query QT_INSTALL_TRANSLATIONS
|
||||||
|
OUTPUT_VARIABLE QT_TRANSLATIONS_DIR
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
file(GLOB qt_I18N ${QT_TRANSLATIONS_DIR}/qt_??.qm ${QT_TRANSLATIONS_DIR}/qt_??_??.qm)
|
file(GLOB qt_I18N ${QT_TRANSLATIONS_DIR}/qt_??.qm ${QT_TRANSLATIONS_DIR}/qt_??_??.qm)
|
||||||
install(FILES ${qt_I18N} DESTINATION ${QM_DIR})
|
install(FILES ${qt_I18N} DESTINATION ${QM_DIR})
|
||||||
|
file(GLOB qtbase_I18N ${QT_TRANSLATIONS_DIR}/qtbase_??.qm ${QT_TRANSLATIONS_DIR}/qt_??_??.qm)
|
||||||
|
install(FILES ${qtbase_I18N} DESTINATION ${QM_DIR})
|
||||||
file(GLOB qtkeychain_I18N ${QT_TRANSLATIONS_DIR}/qtkeychain*.qm)
|
file(GLOB qtkeychain_I18N ${QT_TRANSLATIONS_DIR}/qtkeychain*.qm)
|
||||||
install(FILES ${qtkeychain_I18N} DESTINATION ${QM_DIR})
|
install(FILES ${qtkeychain_I18N} DESTINATION ${QM_DIR})
|
||||||
endif()
|
endif()
|
||||||
@@ -382,8 +389,10 @@ if(NOT BUILD_LIBRARIES_ONLY)
|
|||||||
set_target_properties( ${APPLICATION_EXECUTABLE} PROPERTIES
|
set_target_properties( ${APPLICATION_EXECUTABLE} PROPERTIES
|
||||||
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
|
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
|
||||||
)
|
)
|
||||||
|
# Only relevant for Linux? On OS X it by default properly checks in the bundle directory next to the exe
|
||||||
set_target_properties( ${APPLICATION_EXECUTABLE} PROPERTIES
|
set_target_properties( ${APPLICATION_EXECUTABLE} PROPERTIES
|
||||||
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/${APPLICATION_EXECUTABLE}" )
|
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/${APPLICATION_EXECUTABLE}" )
|
||||||
|
|
||||||
|
|
||||||
target_link_libraries( ${APPLICATION_EXECUTABLE} ${QT_LIBRARIES} )
|
target_link_libraries( ${APPLICATION_EXECUTABLE} ${QT_LIBRARIES} )
|
||||||
target_link_libraries( ${APPLICATION_EXECUTABLE} ${synclib_NAME} )
|
target_link_libraries( ${APPLICATION_EXECUTABLE} ${synclib_NAME} )
|
||||||
@@ -442,8 +451,9 @@ endif()
|
|||||||
# currently it needs to be done because the code right above needs to be executed no matter
|
# currently it needs to be done because the code right above needs to be executed no matter
|
||||||
# if building a bundle or not and the install_qt4_executable needs to be called afterwards
|
# if building a bundle or not and the install_qt4_executable needs to be called afterwards
|
||||||
if(BUILD_OWNCLOUD_OSX_BUNDLE AND NOT BUILD_LIBRARIES_ONLY)
|
if(BUILD_OWNCLOUD_OSX_BUNDLE AND NOT BUILD_LIBRARIES_ONLY)
|
||||||
|
get_target_property (QT_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION)
|
||||||
install(CODE "
|
install(CODE "
|
||||||
message(STATUS \"Deploying (Qt) dependencies and fixing library pathes...\")
|
message(STATUS \"Deploying (Qt) dependencies and fixing library pathes...\")
|
||||||
execute_process(COMMAND \"${CMAKE_SOURCE_DIR}/admin/osx/macdeployqt.py\" ${CMAKE_INSTALL_PREFIX}/${OWNCLOUD_OSX_BUNDLE})
|
execute_process(COMMAND \"${CMAKE_SOURCE_DIR}/admin/osx/macdeployqt.py\" ${CMAKE_INSTALL_PREFIX}/${OWNCLOUD_OSX_BUNDLE} ${QT_QMAKE_EXECUTABLE})
|
||||||
" COMPONENT RUNTIME)
|
" COMPONENT RUNTIME)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ QString AbstractCredentials::keychainKey(const QString &url, const QString &user
|
|||||||
return QString::null;
|
return QString::null;
|
||||||
}
|
}
|
||||||
if( user.isEmpty() ) {
|
if( user.isEmpty() ) {
|
||||||
qDebug() << "Error: User is emty!";
|
qDebug() << "Error: User is empty!";
|
||||||
return QString::null;
|
return QString::null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,11 @@ int getauth(const char *prompt,
|
|||||||
// qDebug() << "OOO Password requested!";
|
// qDebug() << "OOO Password requested!";
|
||||||
qstrncpy( buf, pwd.toUtf8().constData(), len );
|
qstrncpy( buf, pwd.toUtf8().constData(), len );
|
||||||
} else {
|
} else {
|
||||||
re = handleNeonSSLProblems(prompt, buf, len, echo, verify, userdata);
|
if( http_credentials->sslIsTrusted() ) {
|
||||||
|
qstrcpy( buf, "yes" ); // Certificate is fine!
|
||||||
|
} else {
|
||||||
|
re = handleNeonSSLProblems(prompt, buf, len, echo, verify, userdata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return re;
|
return re;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ public:
|
|||||||
virtual QString queryPassword(bool *ok) = 0;
|
virtual QString queryPassword(bool *ok) = 0;
|
||||||
void invalidateToken(Account *account) Q_DECL_OVERRIDE;
|
void invalidateToken(Account *account) Q_DECL_OVERRIDE;
|
||||||
QString fetchUser(Account *account);
|
QString fetchUser(Account *account);
|
||||||
|
virtual bool sslIsTrusted() { return false; }
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void slotAuthentication(QNetworkReply*, QAuthenticator*);
|
void slotAuthentication(QNetworkReply*, QAuthenticator*);
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
// if the application is already running, notify it.
|
// if the application is already running, notify it.
|
||||||
if( app.isRunning() ) {
|
if( app.isRunning() ) {
|
||||||
|
qDebug() << Q_FUNC_INFO << "Already running, exiting...";
|
||||||
QStringList args = app.arguments();
|
QStringList args = app.arguments();
|
||||||
if ( args.size() > 1 && ! app.giveHelp() ) {
|
if ( args.size() > 1 && ! app.giveHelp() ) {
|
||||||
QString msg = args.join( QLatin1String("|") );
|
QString msg = args.join( QLatin1String("|") );
|
||||||
|
|||||||
@@ -605,7 +605,7 @@ void AccountSettings::slotSetProgress(const QString& folder, const Progress::Inf
|
|||||||
item->setData( QVariant(true), FolderStatusDelegate::AddProgressSpace );
|
item->setData( QVariant(true), FolderStatusDelegate::AddProgressSpace );
|
||||||
|
|
||||||
if (!progress._currentDiscoveredFolder.isEmpty()) {
|
if (!progress._currentDiscoveredFolder.isEmpty()) {
|
||||||
item->setData( tr("Discovering %1").arg(progress._currentDiscoveredFolder) , FolderStatusDelegate::SyncProgressItemString );
|
item->setData( tr("Discovering '%1'").arg(progress._currentDiscoveredFolder) , FolderStatusDelegate::SyncProgressItemString );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -252,6 +252,10 @@ void Application::slotCredentialsFetched()
|
|||||||
{
|
{
|
||||||
Account *account = AccountManager::instance()->account();
|
Account *account = AccountManager::instance()->account();
|
||||||
Q_ASSERT(account);
|
Q_ASSERT(account);
|
||||||
|
if (!account) {
|
||||||
|
qDebug() << Q_FUNC_INFO << "No account!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
disconnect(account->credentials(), SIGNAL(fetched()), this, SLOT(slotCredentialsFetched()));
|
disconnect(account->credentials(), SIGNAL(fetched()), this, SLOT(slotCredentialsFetched()));
|
||||||
if (!account->credentials()->ready()) {
|
if (!account->credentials()->ready()) {
|
||||||
// User canceled the connection or did not give a password
|
// User canceled the connection or did not give a password
|
||||||
@@ -534,12 +538,15 @@ void Application::setupTranslations()
|
|||||||
setProperty("ui_lang", lang);
|
setProperty("ui_lang", lang);
|
||||||
const QString qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
|
const QString qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
|
||||||
const QString qtTrFile = QLatin1String("qt_") + lang;
|
const QString qtTrFile = QLatin1String("qt_") + lang;
|
||||||
if (qtTranslator->load(qtTrFile, qtTrPath)) {
|
const QString qtBaseTrFile = QLatin1String("qtbase_") + lang;
|
||||||
qtTranslator->load(qtTrFile, trPath);
|
if (!qtTranslator->load(qtTrFile, qtTrPath)) {
|
||||||
|
if (!qtTranslator->load(qtTrFile, trPath)) {
|
||||||
|
qtTranslator->load(qtBaseTrFile, trPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const QString qtkeychainFile = QLatin1String("qt_") + lang;
|
const QString qtkeychainTrFile = QLatin1String("qtkeychain_") + lang;
|
||||||
if (!qtkeychainTranslator->load(qtkeychainFile, qtTrPath)) {
|
if (!qtkeychainTranslator->load(qtkeychainTrFile, qtTrPath)) {
|
||||||
qtkeychainTranslator->load(qtkeychainFile, trPath);
|
qtkeychainTranslator->load(qtkeychainTrFile, trPath);
|
||||||
}
|
}
|
||||||
if (!translator->isEmpty())
|
if (!translator->isEmpty())
|
||||||
installTranslator(translator);
|
installTranslator(translator);
|
||||||
|
|||||||
@@ -101,6 +101,10 @@ void ClientProxy::setCSyncProxy( const QUrl& url, CSYNC *csync_ctx )
|
|||||||
QList<QNetworkProxy> proxies = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(url));
|
QList<QNetworkProxy> proxies = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(url));
|
||||||
// We set at least one in Application
|
// We set at least one in Application
|
||||||
Q_ASSERT(proxies.count() > 0);
|
Q_ASSERT(proxies.count() > 0);
|
||||||
|
if (proxies.count() == 0) {
|
||||||
|
qDebug() << Q_FUNC_INFO << "No proxy!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
QNetworkProxy proxy = proxies.first();
|
QNetworkProxy proxy = proxies.first();
|
||||||
if (proxy.type() == QNetworkProxy::NoProxy) {
|
if (proxy.type() == QNetworkProxy::NoProxy) {
|
||||||
qDebug() << "Passing NO proxy to csync for" << url.toString();
|
qDebug() << "Passing NO proxy to csync for" << url.toString();
|
||||||
|
|||||||
@@ -16,9 +16,11 @@
|
|||||||
#include <csync_private.h>
|
#include <csync_private.h>
|
||||||
#include <qdebug.h>
|
#include <qdebug.h>
|
||||||
|
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
bool DiscoveryJob::isInBlackList(const QString& path) const
|
bool DiscoveryJob::isInSelectiveSyncBlackList(const QString& path) const
|
||||||
{
|
{
|
||||||
if (_selectiveSyncBlackList.isEmpty()) {
|
if (_selectiveSyncBlackList.isEmpty()) {
|
||||||
// If there is no black list, everything is allowed
|
// If there is no black list, everything is allowed
|
||||||
@@ -35,19 +37,24 @@ bool DiscoveryJob::isInBlackList(const QString& path) const
|
|||||||
|
|
||||||
auto it = std::lower_bound(_selectiveSyncBlackList.begin(), _selectiveSyncBlackList.end(), pathSlash);
|
auto it = std::lower_bound(_selectiveSyncBlackList.begin(), _selectiveSyncBlackList.end(), pathSlash);
|
||||||
|
|
||||||
|
if (it != _selectiveSyncBlackList.end() && *it == pathSlash) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (it == _selectiveSyncBlackList.begin()) {
|
if (it == _selectiveSyncBlackList.begin()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
--it;
|
--it;
|
||||||
if (pathSlash.startsWith(*it + QLatin1Char('/'))) {
|
Q_ASSERT(it->endsWith(QLatin1Char('/'))); // Folder::setSelectiveSyncBlackList makes sure of that
|
||||||
|
if (pathSlash.startsWith(*it)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DiscoveryJob::isInBlackListCallBack(void *data, const char *path)
|
int DiscoveryJob::isInSelectiveSyncBlackListCallBack(void *data, const char *path)
|
||||||
{
|
{
|
||||||
return static_cast<DiscoveryJob*>(data)->isInBlackList(QString::fromUtf8(path));
|
return static_cast<DiscoveryJob*>(data)->isInSelectiveSyncBlackList(QString::fromUtf8(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiscoveryJob::update_job_update_callback (bool local,
|
void DiscoveryJob::update_job_update_callback (bool local,
|
||||||
@@ -65,15 +72,15 @@ void DiscoveryJob::update_job_update_callback (bool local,
|
|||||||
updateJob->lastUpdateProgressCallbackCall.restart();
|
updateJob->lastUpdateProgressCallbackCall.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString path = QString::fromUtf8(dirUrl).section('/', -1);
|
QString path(QUrl::fromPercentEncoding(QByteArray(dirUrl)).section('/', -1));
|
||||||
emit updateJob->folderDiscovered(local, path);
|
emit updateJob->folderDiscovered(local, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiscoveryJob::start() {
|
void DiscoveryJob::start() {
|
||||||
_selectiveSyncBlackList.sort();
|
_selectiveSyncBlackList.sort();
|
||||||
_csync_ctx->checkBlackListHook = isInBlackListCallBack;
|
_csync_ctx->checkSelectiveSyncBlackListHook = isInSelectiveSyncBlackListCallBack;
|
||||||
_csync_ctx->checkBlackListData = this;
|
_csync_ctx->checkSelectiveSyncBlackListData = this;
|
||||||
|
|
||||||
_csync_ctx->callbacks.update_callback = update_job_update_callback;
|
_csync_ctx->callbacks.update_callback = update_job_update_callback;
|
||||||
_csync_ctx->callbacks.update_callback_userdata = this;
|
_csync_ctx->callbacks.update_callback_userdata = this;
|
||||||
@@ -85,8 +92,8 @@ void DiscoveryJob::start() {
|
|||||||
lastUpdateProgressCallbackCall.invalidate();
|
lastUpdateProgressCallbackCall.invalidate();
|
||||||
int ret = csync_update(_csync_ctx);
|
int ret = csync_update(_csync_ctx);
|
||||||
|
|
||||||
_csync_ctx->checkBlackListHook = 0;
|
_csync_ctx->checkSelectiveSyncBlackListHook = 0;
|
||||||
_csync_ctx->checkBlackListData = 0;
|
_csync_ctx->checkSelectiveSyncBlackListData = 0;
|
||||||
|
|
||||||
_csync_ctx->callbacks.update_callback = 0;
|
_csync_ctx->callbacks.update_callback = 0;
|
||||||
_csync_ctx->callbacks.update_callback_userdata = 0;
|
_csync_ctx->callbacks.update_callback_userdata = 0;
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ class DiscoveryJob : public QObject {
|
|||||||
* return true if the given path should be synced,
|
* return true if the given path should be synced,
|
||||||
* false if the path should be ignored
|
* false if the path should be ignored
|
||||||
*/
|
*/
|
||||||
bool isInBlackList(const QString &path) const;
|
bool isInSelectiveSyncBlackList(const QString &path) const;
|
||||||
static int isInBlackListCallBack(void *, const char *);
|
static int isInSelectiveSyncBlackListCallBack(void *, const char *);
|
||||||
|
|
||||||
static void update_job_update_callback (bool local,
|
static void update_job_update_callback (bool local,
|
||||||
const char *dirname,
|
const char *dirname,
|
||||||
|
|||||||
@@ -96,12 +96,18 @@ time_t FileSystem::getModTime(const QString &filename)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileSystem::setModTime(const QString& filename, time_t modTime)
|
bool FileSystem::setModTime(const QString& filename, time_t modTime)
|
||||||
{
|
{
|
||||||
struct timeval times[2];
|
struct timeval times[2];
|
||||||
times[0].tv_sec = times[1].tv_sec = modTime;
|
times[0].tv_sec = times[1].tv_sec = modTime;
|
||||||
times[0].tv_usec = times[1].tv_usec = 0;
|
times[0].tv_usec = times[1].tv_usec = 0;
|
||||||
c_utimes(filename.toUtf8().data(), times);
|
int rc = c_utimes(filename.toUtf8().data(), times);
|
||||||
|
if (rc != 0) {
|
||||||
|
qDebug() << "Error setting mtime for" << filename
|
||||||
|
<< "failed: rc" << rc << ", errno:" << errno;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileSystem::renameReplace(const QString& originFileName, const QString& destinationFileName, QString* errorString)
|
bool FileSystem::renameReplace(const QString& originFileName, const QString& destinationFileName, QString* errorString)
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ void OWNCLOUDSYNC_EXPORT setFileHidden(const QString& filename, bool hidden);
|
|||||||
*/
|
*/
|
||||||
time_t OWNCLOUDSYNC_EXPORT getModTime(const QString &filename);
|
time_t OWNCLOUDSYNC_EXPORT getModTime(const QString &filename);
|
||||||
|
|
||||||
void setModTime(const QString &filename, time_t modTime);
|
bool setModTime(const QString &filename, time_t modTime);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rename the file \a originFileName to \a destinationFileName, and overwrite the destination if it
|
* Rename the file \a originFileName to \a destinationFileName, and overwrite the destination if it
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ Folder::Folder(const QString &alias, const QString &path, const QString& secondP
|
|||||||
, _csyncUnavail(false)
|
, _csyncUnavail(false)
|
||||||
, _wipeDb(false)
|
, _wipeDb(false)
|
||||||
, _proxyDirty(true)
|
, _proxyDirty(true)
|
||||||
|
, _forceSyncOnPollTimeout(false)
|
||||||
|
, _consecutiveFailingSyncs(0)
|
||||||
|
, _consecutiveFollowUpSyncs(0)
|
||||||
, _journal(path)
|
, _journal(path)
|
||||||
, _csync_ctx(0)
|
, _csync_ctx(0)
|
||||||
{
|
{
|
||||||
@@ -269,13 +272,40 @@ void Folder::slotPollTimerTimeout()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (quint64(_timeSinceLastSync.elapsed()) > MirallConfigFile().forceSyncInterval() ||
|
bool forceSyncIntervalExpired =
|
||||||
_lastEtag.isNull() ||
|
quint64(_timeSinceLastSync.elapsed()) > MirallConfigFile().forceSyncInterval();
|
||||||
!(_syncResult.status() == SyncResult::Success ||_syncResult.status() == SyncResult::Problem)) {
|
bool syncAgainAfterFail = _consecutiveFailingSyncs > 0 && _consecutiveFailingSyncs < 3;
|
||||||
qDebug() << "** Force Sync now, state is " << _syncResult.statusString();
|
|
||||||
|
// There are several conditions under which we trigger a full-discovery sync:
|
||||||
|
// * When a suitably long time has passed since the last sync finished
|
||||||
|
// * When the last sync failed (only a couple of times)
|
||||||
|
// * When the last sync requested another sync to be done (only a couple of times)
|
||||||
|
//
|
||||||
|
// Note that the etag check (see below) and the file watcher may also trigger
|
||||||
|
// syncs.
|
||||||
|
if (forceSyncIntervalExpired
|
||||||
|
|| _forceSyncOnPollTimeout
|
||||||
|
|| syncAgainAfterFail) {
|
||||||
|
|
||||||
|
if (forceSyncIntervalExpired) {
|
||||||
|
qDebug() << "** Force Sync, because it has been " << _timeSinceLastSync.elapsed() << "ms "
|
||||||
|
<< "since the last sync";
|
||||||
|
}
|
||||||
|
if (_forceSyncOnPollTimeout) {
|
||||||
|
qDebug() << "** Force Sync, because it was requested";
|
||||||
|
}
|
||||||
|
if (syncAgainAfterFail) {
|
||||||
|
qDebug() << "** Force Sync, because the last"
|
||||||
|
<< _consecutiveFailingSyncs << "syncs failed, last status:"
|
||||||
|
<< _syncResult.statusString();
|
||||||
|
}
|
||||||
|
_forceSyncOnPollTimeout = false;
|
||||||
emit scheduleToSync(alias());
|
emit scheduleToSync(alias());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// do the ordinary etag check for the root folder.
|
// Do the ordinary etag check for the root folder and only schedule a real
|
||||||
|
// sync if it's different.
|
||||||
|
|
||||||
RequestEtagJob* job = new RequestEtagJob(account, remotePath(), this);
|
RequestEtagJob* job = new RequestEtagJob(account, remotePath(), this);
|
||||||
// check if the etag is different
|
// check if the etag is different
|
||||||
QObject::connect(job, SIGNAL(etagRetreived(QString)), this, SLOT(etagRetreived(QString)));
|
QObject::connect(job, SIGNAL(etagRetreived(QString)), this, SLOT(etagRetreived(QString)));
|
||||||
@@ -286,7 +316,7 @@ void Folder::slotPollTimerTimeout()
|
|||||||
|
|
||||||
void Folder::etagRetreived(const QString& etag)
|
void Folder::etagRetreived(const QString& etag)
|
||||||
{
|
{
|
||||||
qDebug() << "* Compare etag with previous etag: " << (_lastEtag != etag);
|
qDebug() << "* Compare etag with previous etag: last:" << _lastEtag << ", received:" << etag;
|
||||||
|
|
||||||
// re-enable sync if it was disabled because network was down
|
// re-enable sync if it was disabled because network was down
|
||||||
FolderMan::instance()->setSyncEnabled(true);
|
FolderMan::instance()->setSyncEnabled(true);
|
||||||
@@ -476,6 +506,26 @@ void Folder::createGuiLog( const QString& filename, SyncFileStatus status, int c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Folder::slotDiscardDownloadProgress()
|
||||||
|
{
|
||||||
|
// Delete from journal and from filesystem.
|
||||||
|
QDir folderpath(_path);
|
||||||
|
QSet<QString> keep_nothing;
|
||||||
|
const QVector<SyncJournalDb::DownloadInfo> deleted_infos =
|
||||||
|
_journal.getAndDeleteStaleDownloadInfos(keep_nothing);
|
||||||
|
foreach (const SyncJournalDb::DownloadInfo & deleted_info, deleted_infos) {
|
||||||
|
const QString tmppath = folderpath.filePath(deleted_info._tmpfile);
|
||||||
|
qDebug() << "Deleting temporary file: " << tmppath;
|
||||||
|
QFile::remove(tmppath);
|
||||||
|
}
|
||||||
|
return deleted_infos.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Folder::downloadInfoCount()
|
||||||
|
{
|
||||||
|
return _journal.downloadInfoCount();
|
||||||
|
}
|
||||||
|
|
||||||
int Folder::blackListEntryCount()
|
int Folder::blackListEntryCount()
|
||||||
{
|
{
|
||||||
return _journal.blackListEntryCount();
|
return _journal.blackListEntryCount();
|
||||||
@@ -496,11 +546,88 @@ QString Folder::configFile()
|
|||||||
return _configFile;
|
return _configFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void addErroredSyncItemPathsToList(const SyncFileItemVector& items, QSet<QString>* set) {
|
||||||
|
Q_FOREACH(const SyncFileItem &item, items) {
|
||||||
|
if (item.hasErrorStatus()) {
|
||||||
|
set->insert(item._file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Folder::slotThreadTreeWalkResult(const SyncFileItemVector& items)
|
void Folder::slotThreadTreeWalkResult(const SyncFileItemVector& items)
|
||||||
{
|
{
|
||||||
|
addErroredSyncItemPathsToList(items, &this->_stateLastSyncItemsWithError);
|
||||||
_syncResult.setSyncFileItemVector(items);
|
_syncResult.setSyncFileItemVector(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Folder::slotAboutToPropagate(const SyncFileItemVector& items)
|
||||||
|
{
|
||||||
|
// empty the tainted list since the status generation code will use the _syncedItems
|
||||||
|
// (which imply the folder) to generate the syncing state icon now.
|
||||||
|
_stateTaintedFolders.clear();
|
||||||
|
|
||||||
|
addErroredSyncItemPathsToList(items, &this->_stateLastSyncItemsWithError);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Folder::estimateState(QString fn, csync_ftw_type_e t, SyncFileStatus* s)
|
||||||
|
{
|
||||||
|
if (t == CSYNC_FTW_TYPE_DIR) {
|
||||||
|
if (Utility::doesSetContainPrefix(_stateLastSyncItemsWithError, fn)) {
|
||||||
|
qDebug() << Q_FUNC_INFO << "Folder has error" << fn;
|
||||||
|
s->set(SyncFileStatus::STATUS_ERROR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// If sync is running, check _syncedItems, possibly give it STATUS_EVAL (=syncing down)
|
||||||
|
if (!_engine.isNull()) {
|
||||||
|
if (_engine->estimateState(fn, t, s)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Utility::doesSetContainPrefix(_stateTaintedFolders, fn)) {
|
||||||
|
qDebug() << Q_FUNC_INFO << "Folder is tainted, EVAL!" << fn;
|
||||||
|
s->set(SyncFileStatus::STATUS_EVAL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else if ( t== CSYNC_FTW_TYPE_FILE) {
|
||||||
|
// check if errorList has the directory/file
|
||||||
|
if (Utility::doesSetContainPrefix(_stateLastSyncItemsWithError, fn)) {
|
||||||
|
s->set(SyncFileStatus::STATUS_ERROR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// If sync running: _syncedItems -> SyncingState
|
||||||
|
if (!_engine.isNull()) {
|
||||||
|
if (_engine->estimateState(fn, t, s)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Folder::watcherSlot(QString fn)
|
||||||
|
{
|
||||||
|
// FIXME: On OS X we could not do this "if" since on OS X the file watcher ignores events for ourselves
|
||||||
|
// however to have the same behaviour atm on all platforms, we don't do it
|
||||||
|
if (!_engine.isNull()) {
|
||||||
|
qDebug() << Q_FUNC_INFO << "Sync running, IGNORE event for " << fn;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QFileInfo fi(fn);
|
||||||
|
if (fi.isFile()) {
|
||||||
|
fn = fi.path(); // depending on OS, file watcher might be for dir or file
|
||||||
|
}
|
||||||
|
// Make it a relative path depending on the folder
|
||||||
|
QString relativePath = fn.remove(0, path().length());
|
||||||
|
qDebug() << Q_FUNC_INFO << fi.canonicalFilePath() << fn << relativePath;
|
||||||
|
_stateTaintedFolders.insert(relativePath);
|
||||||
|
|
||||||
|
// Notify the SocketAPI?
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Folder::slotTerminateSync()
|
void Folder::slotTerminateSync()
|
||||||
{
|
{
|
||||||
qDebug() << "folder " << alias() << " Terminating!";
|
qDebug() << "folder " << alias() << " Terminating!";
|
||||||
@@ -522,6 +649,9 @@ void Folder::wipe()
|
|||||||
{
|
{
|
||||||
QString stateDbFile = path()+QLatin1String(".csync_journal.db");
|
QString stateDbFile = path()+QLatin1String(".csync_journal.db");
|
||||||
|
|
||||||
|
// Delete files that have been partially downloaded.
|
||||||
|
slotDiscardDownloadProgress();
|
||||||
|
|
||||||
_journal.close(); // close the sync journal
|
_journal.close(); // close the sync journal
|
||||||
|
|
||||||
QFile file(stateDbFile);
|
QFile file(stateDbFile);
|
||||||
@@ -534,12 +664,11 @@ void Folder::wipe()
|
|||||||
} else {
|
} else {
|
||||||
qDebug() << "WRN: statedb is empty, can not remove.";
|
qDebug() << "WRN: statedb is empty, can not remove.";
|
||||||
}
|
}
|
||||||
// Check if the tmp database file also exists
|
|
||||||
QString ctmpName = path() + QLatin1String(".csync_journal.db.ctmp");
|
// Also remove other db related files
|
||||||
QFile ctmpFile( ctmpName );
|
QFile::remove( stateDbFile + ".ctmp" );
|
||||||
if( ctmpFile.exists() ) {
|
QFile::remove( stateDbFile + "-shm" );
|
||||||
ctmpFile.remove();
|
QFile::remove( stateDbFile + "-wal" );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Folder::setIgnoredFiles()
|
bool Folder::setIgnoredFiles()
|
||||||
@@ -623,6 +752,8 @@ void Folder::startSync(const QStringList &pathList)
|
|||||||
|
|
||||||
connect( _engine.data(), SIGNAL(treeWalkResult(const SyncFileItemVector&)),
|
connect( _engine.data(), SIGNAL(treeWalkResult(const SyncFileItemVector&)),
|
||||||
this, SLOT(slotThreadTreeWalkResult(const SyncFileItemVector&)), Qt::QueuedConnection);
|
this, SLOT(slotThreadTreeWalkResult(const SyncFileItemVector&)), Qt::QueuedConnection);
|
||||||
|
connect( _engine.data(), SIGNAL(aboutToPropagate(const SyncFileItemVector&)),
|
||||||
|
this, SLOT(slotAboutToPropagate(const SyncFileItemVector&)), Qt::QueuedConnection);
|
||||||
|
|
||||||
connect(_engine.data(), SIGNAL(started()), SLOT(slotSyncStarted()), Qt::QueuedConnection);
|
connect(_engine.data(), SIGNAL(started()), SLOT(slotSyncStarted()), Qt::QueuedConnection);
|
||||||
connect(_engine.data(), SIGNAL(finished()), SLOT(slotSyncFinished()), Qt::QueuedConnection);
|
connect(_engine.data(), SIGNAL(finished()), SLOT(slotSyncFinished()), Qt::QueuedConnection);
|
||||||
@@ -669,6 +800,17 @@ void Folder::setDirtyNetworkLimits()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Folder::setSelectiveSyncBlackList(const QStringList& blackList)
|
||||||
|
{
|
||||||
|
_selectiveSyncBlackList = blackList;
|
||||||
|
for (int i = 0; i < _selectiveSyncBlackList.count(); ++i) {
|
||||||
|
if (!_selectiveSyncBlackList.at(i).endsWith(QLatin1Char('/'))) {
|
||||||
|
_selectiveSyncBlackList[i].append(QLatin1Char('/'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Folder::slotSyncError(const QString& err)
|
void Folder::slotSyncError(const QString& err)
|
||||||
{
|
{
|
||||||
_errors.append( err );
|
_errors.append( err );
|
||||||
@@ -689,8 +831,11 @@ void Folder::slotCsyncUnavailable()
|
|||||||
|
|
||||||
void Folder::slotSyncFinished()
|
void Folder::slotSyncFinished()
|
||||||
{
|
{
|
||||||
qDebug() << "-> CSync Finished slot with error " << _csyncError << "warn count" << _syncResult.warnCount();
|
if( _csyncError ) {
|
||||||
|
qDebug() << "-> SyncEngine finished with ERROR, warn count is" << _syncResult.warnCount();
|
||||||
|
} else {
|
||||||
|
qDebug() << "-> SyncEngine finished without problem.";
|
||||||
|
}
|
||||||
bubbleUpSyncResult();
|
bubbleUpSyncResult();
|
||||||
|
|
||||||
bool anotherSyncNeeded = false;
|
bool anotherSyncNeeded = false;
|
||||||
@@ -701,6 +846,10 @@ void Folder::slotSyncFinished()
|
|||||||
// _watcher->setEventsEnabledDelayed(2000);
|
// _watcher->setEventsEnabledDelayed(2000);
|
||||||
|
|
||||||
|
|
||||||
|
// This is for sync state calculation
|
||||||
|
_stateLastSyncItemsWithError = _stateLastSyncItemsWithErrorNew;
|
||||||
|
_stateLastSyncItemsWithErrorNew.clear();
|
||||||
|
_stateTaintedFolders.clear(); // heuristic: assume the sync had been done, new file watches needed to taint dirs
|
||||||
|
|
||||||
if (_csyncError) {
|
if (_csyncError) {
|
||||||
_syncResult.setStatus(SyncResult::Error);
|
_syncResult.setStatus(SyncResult::Error);
|
||||||
@@ -717,6 +866,18 @@ void Folder::slotSyncFinished()
|
|||||||
_syncResult.setStatus(SyncResult::Success);
|
_syncResult.setStatus(SyncResult::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Count the number of syncs that have failed in a row.
|
||||||
|
if (_syncResult.status() == SyncResult::Success
|
||||||
|
|| _syncResult.status() == SyncResult::Problem)
|
||||||
|
{
|
||||||
|
_consecutiveFailingSyncs = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_consecutiveFailingSyncs++;
|
||||||
|
qDebug() << "the last" << _consecutiveFailingSyncs << "syncs failed";
|
||||||
|
}
|
||||||
|
|
||||||
emit syncStateChange();
|
emit syncStateChange();
|
||||||
|
|
||||||
// The syncFinished result that is to be triggered here makes the folderman
|
// The syncFinished result that is to be triggered here makes the folderman
|
||||||
@@ -727,16 +888,28 @@ void Folder::slotSyncFinished()
|
|||||||
// all come in.
|
// all come in.
|
||||||
QTimer::singleShot(200, this, SLOT(slotEmitFinishedDelayed() ));
|
QTimer::singleShot(200, this, SLOT(slotEmitFinishedDelayed() ));
|
||||||
|
|
||||||
if (!anotherSyncNeeded) {
|
_timeSinceLastSync.restart();
|
||||||
_pollTimer.start();
|
|
||||||
_timeSinceLastSync.restart();
|
// Increment the follow-up sync counter if necessary.
|
||||||
|
if (anotherSyncNeeded) {
|
||||||
|
_consecutiveFollowUpSyncs++;
|
||||||
|
qDebug() << "another sync was requested by the finished sync, this has"
|
||||||
|
<< "happened" << _consecutiveFollowUpSyncs << "times";
|
||||||
} else {
|
} else {
|
||||||
// Another sync is required. We will make sure that the poll timer occurs soon enough
|
_consecutiveFollowUpSyncs = 0;
|
||||||
// and we clear the etag to force a sync
|
|
||||||
_lastEtag.clear();
|
|
||||||
QTimer::singleShot(1000, this, SLOT(slotPollTimerTimeout() ));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Maybe force a follow-up sync to take place, but only a couple of times.
|
||||||
|
if (anotherSyncNeeded && _consecutiveFollowUpSyncs <= 3)
|
||||||
|
{
|
||||||
|
_forceSyncOnPollTimeout = true;
|
||||||
|
// We will make sure that the poll timer occurs soon enough.
|
||||||
|
// delay 1s, 4s, 9s
|
||||||
|
int c = _consecutiveFollowUpSyncs;
|
||||||
|
QTimer::singleShot(c*c * 1000, this, SLOT(slotPollTimerTimeout() ));
|
||||||
|
} else {
|
||||||
|
_pollTimer.start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Folder::slotEmitFinishedDelayed()
|
void Folder::slotEmitFinishedDelayed()
|
||||||
@@ -767,6 +940,10 @@ void Folder::slotTransmissionProgress(const Progress::Info &pi)
|
|||||||
// a job is completed: count the errors and forward to the ProgressDispatcher
|
// a job is completed: count the errors and forward to the ProgressDispatcher
|
||||||
void Folder::slotJobCompleted(const SyncFileItem &item)
|
void Folder::slotJobCompleted(const SyncFileItem &item)
|
||||||
{
|
{
|
||||||
|
if (item.hasErrorStatus()) {
|
||||||
|
_stateLastSyncItemsWithError.insert(item._file);
|
||||||
|
}
|
||||||
|
|
||||||
if (Progress::isWarningKind(item._status)) {
|
if (Progress::isWarningKind(item._status)) {
|
||||||
// Count all error conditions.
|
// Count all error conditions.
|
||||||
_syncResult.setWarnCount(_syncResult.warnCount()+1);
|
_syncResult.setWarnCount(_syncResult.warnCount()+1);
|
||||||
@@ -799,7 +976,8 @@ void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction, bool *cancel)
|
|||||||
if (*cancel) {
|
if (*cancel) {
|
||||||
wipe();
|
wipe();
|
||||||
// speed up next sync
|
// speed up next sync
|
||||||
_lastEtag = QString();
|
_lastEtag.clear();
|
||||||
|
_forceSyncOnPollTimeout = true;
|
||||||
QTimer::singleShot(50, this, SLOT(slotPollTimerTimeout()));
|
QTimer::singleShot(50, this, SLOT(slotPollTimerTimeout()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
#include <QSet>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
@@ -34,15 +35,12 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <qelapsedtimer.h>
|
#include <qelapsedtimer.h>
|
||||||
|
|
||||||
class QFileSystemWatcher;
|
|
||||||
class QThread;
|
class QThread;
|
||||||
|
|
||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
class SyncEngine;
|
class SyncEngine;
|
||||||
|
|
||||||
class FolderWatcher;
|
|
||||||
|
|
||||||
class Folder : public QObject
|
class Folder : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -119,12 +117,11 @@ public:
|
|||||||
|
|
||||||
// Used by the Socket API
|
// Used by the Socket API
|
||||||
SyncJournalDb *journalDb() { return &_journal; }
|
SyncJournalDb *journalDb() { return &_journal; }
|
||||||
CSYNC *csyncContext() { return _csync_ctx; }
|
|
||||||
|
|
||||||
QStringList selectiveSyncBlackList() { return _selectiveSyncBlackList; }
|
QStringList selectiveSyncBlackList() { return _selectiveSyncBlackList; }
|
||||||
void setSelectiveSyncBlackList(const QStringList &blackList)
|
void setSelectiveSyncBlackList(const QStringList &blackList);
|
||||||
{ _selectiveSyncBlackList = blackList; }
|
|
||||||
|
|
||||||
|
bool estimateState(QString fn, csync_ftw_type_e t, SyncFileStatus* s);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void syncStateChange();
|
void syncStateChange();
|
||||||
@@ -152,6 +149,8 @@ public slots:
|
|||||||
void setProxyDirty(bool value);
|
void setProxyDirty(bool value);
|
||||||
bool proxyDirty();
|
bool proxyDirty();
|
||||||
|
|
||||||
|
int slotDiscardDownloadProgress();
|
||||||
|
int downloadInfoCount();
|
||||||
int slotWipeBlacklist();
|
int slotWipeBlacklist();
|
||||||
int blackListEntryCount();
|
int blackListEntryCount();
|
||||||
|
|
||||||
@@ -170,10 +169,13 @@ private slots:
|
|||||||
void etagRetreived(const QString &);
|
void etagRetreived(const QString &);
|
||||||
void slotNetworkUnavailable();
|
void slotNetworkUnavailable();
|
||||||
|
|
||||||
void slotThreadTreeWalkResult(const SyncFileItemVector& );
|
void slotAboutToPropagate(const SyncFileItemVector& );
|
||||||
|
void slotThreadTreeWalkResult(const SyncFileItemVector& ); // after sync is done
|
||||||
|
|
||||||
void slotEmitFinishedDelayed();
|
void slotEmitFinishedDelayed();
|
||||||
|
|
||||||
|
void watcherSlot(QString);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
@@ -202,6 +204,20 @@ private:
|
|||||||
QTimer _pollTimer;
|
QTimer _pollTimer;
|
||||||
QString _lastEtag;
|
QString _lastEtag;
|
||||||
QElapsedTimer _timeSinceLastSync;
|
QElapsedTimer _timeSinceLastSync;
|
||||||
|
bool _forceSyncOnPollTimeout;
|
||||||
|
|
||||||
|
/// The number of syncs that failed in a row.
|
||||||
|
/// Reset when a sync is successful.
|
||||||
|
int _consecutiveFailingSyncs;
|
||||||
|
|
||||||
|
/// The number of requested follow-up syncs.
|
||||||
|
/// Reset when no follow-up is requested.
|
||||||
|
int _consecutiveFollowUpSyncs;
|
||||||
|
|
||||||
|
// For the SocketAPI folder states
|
||||||
|
QSet<QString> _stateLastSyncItemsWithErrorNew; // gets moved to _stateLastSyncItemsWithError at end of sync
|
||||||
|
QSet<QString> _stateLastSyncItemsWithError;
|
||||||
|
QSet<QString> _stateTaintedFolders;
|
||||||
|
|
||||||
SyncJournalDb _journal;
|
SyncJournalDb _journal;
|
||||||
|
|
||||||
|
|||||||
@@ -147,6 +147,9 @@ void FolderMan::registerFolderMonitor( Folder *folder )
|
|||||||
connect(fw, SIGNAL(folderChanged(QString)), _folderWatcherSignalMapper, SLOT(map()));
|
connect(fw, SIGNAL(folderChanged(QString)), _folderWatcherSignalMapper, SLOT(map()));
|
||||||
_folderWatcherSignalMapper->setMapping(fw, folder->alias());
|
_folderWatcherSignalMapper->setMapping(fw, folder->alias());
|
||||||
_folderWatchers.insert(folder->alias(), fw);
|
_folderWatchers.insert(folder->alias(), fw);
|
||||||
|
|
||||||
|
// This is at the moment only for the behaviour of the SocketApi.
|
||||||
|
connect(fw, SIGNAL(folderChanged(QString)), folder, SLOT(watcherSlot(QString)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// register the folder with the socket API
|
// register the folder with the socket API
|
||||||
@@ -442,6 +445,24 @@ void FolderMan::slotScheduleSync( const QString& alias )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The folder watcher fires a lot of bogus notifications during
|
||||||
|
// a sync operation, both for actual user files and the database
|
||||||
|
// and log. Never enqueue a folder for sync while it is syncing.
|
||||||
|
// We lose some genuine sync requests that way, but that can't be
|
||||||
|
// helped.
|
||||||
|
// ^^ FIXME: Note that this is not the case on OS X
|
||||||
|
if( _currentSyncFolder == alias ) {
|
||||||
|
qDebug() << "folder " << alias << " is currently syncing. NOT scheduling.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( _socketApi ) {
|
||||||
|
// We want the SocketAPI to already now update so that it can show the EVAL icon
|
||||||
|
// for files/folders. Only do this when not syncing, else we might get a lot
|
||||||
|
// of those notifications.
|
||||||
|
_socketApi->slotUpdateFolderView(alias);
|
||||||
|
}
|
||||||
|
|
||||||
qDebug() << "Schedule folder " << alias << " to sync!";
|
qDebug() << "Schedule folder " << alias << " to sync!";
|
||||||
|
|
||||||
if( ! _scheduleQueue.contains(alias) ) {
|
if( ! _scheduleQueue.contains(alias) ) {
|
||||||
@@ -532,6 +553,8 @@ void FolderMan::slotFolderSyncStarted( )
|
|||||||
/*
|
/*
|
||||||
* a folder indicates that its syncing is finished.
|
* a folder indicates that its syncing is finished.
|
||||||
* Start the next sync after the system had some milliseconds to breath.
|
* Start the next sync after the system had some milliseconds to breath.
|
||||||
|
* This delay is particularly useful to avoid late file change notifications
|
||||||
|
* (that we caused ourselves by syncing) from triggering another spurious sync.
|
||||||
*/
|
*/
|
||||||
void FolderMan::slotFolderSyncFinished( const SyncResult& )
|
void FolderMan::slotFolderSyncFinished( const SyncResult& )
|
||||||
{
|
{
|
||||||
@@ -566,11 +589,11 @@ Folder *FolderMan::folderForPath(const QString &path)
|
|||||||
const QString folderPath = QDir::cleanPath(folder->path())+QLatin1Char('/');
|
const QString folderPath = QDir::cleanPath(folder->path())+QLatin1Char('/');
|
||||||
|
|
||||||
if(absolutePath.startsWith(folderPath)) {
|
if(absolutePath.startsWith(folderPath)) {
|
||||||
qDebug() << "found folder: " << folder->path() << " for " << absolutePath;
|
//qDebug() << "found folder: " << folder->path() << " for " << absolutePath;
|
||||||
return folder;
|
return folder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
qDebug() << "ERROR: could not find folder for " << absolutePath;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -675,6 +698,17 @@ bool FolderMan::startFromScratch( const QString& localFolder )
|
|||||||
qDebug() << "startFromScratch: Directory is empty!";
|
qDebug() << "startFromScratch: Directory is empty!";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// Disconnect the socket api from the database to avoid that locking of the
|
||||||
|
// db file does not allow to move this dir.
|
||||||
|
if( _socketApi ) {
|
||||||
|
Folder *f = folderForPath(localFolder);
|
||||||
|
if(f) {
|
||||||
|
if( localFolder.startsWith(f->path()) ) {
|
||||||
|
_socketApi->slotUnregisterPath(f->alias());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Make a backup of the folder/file.
|
// Make a backup of the folder/file.
|
||||||
QString newName = getBackupName( parentDir.absoluteFilePath( folderName ) );
|
QString newName = getBackupName( parentDir.absoluteFilePath( folderName ) );
|
||||||
if( !parentDir.rename( fi.absoluteFilePath(), newName ) ) {
|
if( !parentDir.rename( fi.absoluteFilePath(), newName ) ) {
|
||||||
|
|||||||
@@ -71,6 +71,12 @@ bool FolderWatcher::pathIsIgnored( const QString& path )
|
|||||||
{
|
{
|
||||||
if( path.isEmpty() ) return true;
|
if( path.isEmpty() ) return true;
|
||||||
|
|
||||||
|
QFileInfo fInfo(path);
|
||||||
|
if( fInfo.isHidden() ) {
|
||||||
|
qDebug() << "* Discarded as is hidden!" << fInfo.filePath();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Remember: here only directories are checked!
|
// Remember: here only directories are checked!
|
||||||
// If that changes to files too at some day, remember to check
|
// If that changes to files too at some day, remember to check
|
||||||
// for the database name as well as the trailing slash rule for
|
// for the database name as well as the trailing slash rule for
|
||||||
@@ -79,12 +85,6 @@ bool FolderWatcher::pathIsIgnored( const QString& path )
|
|||||||
QRegExp regexp(pattern);
|
QRegExp regexp(pattern);
|
||||||
regexp.setPatternSyntax(QRegExp::Wildcard);
|
regexp.setPatternSyntax(QRegExp::Wildcard);
|
||||||
|
|
||||||
QFileInfo fInfo(path);
|
|
||||||
if( fInfo.isHidden() ) {
|
|
||||||
qDebug() << "* Discarded as is hidden!";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pattern.endsWith('/')) {
|
if(pattern.endsWith('/')) {
|
||||||
// directory only pattern. But since only dirs here, we cut off the trailing dir.
|
// directory only pattern. But since only dirs here, we cut off the trailing dir.
|
||||||
pattern.remove(pattern.length()-1, 1); // remove the last char.
|
pattern.remove(pattern.length()-1, 1); // remove the last char.
|
||||||
|
|||||||
@@ -232,6 +232,9 @@ FolderWizardRemotePath::FolderWizardRemotePath()
|
|||||||
_ui.setupUi(this);
|
_ui.setupUi(this);
|
||||||
_ui.warnFrame->hide();
|
_ui.warnFrame->hide();
|
||||||
|
|
||||||
|
_ui.folderTreeWidget->setSortingEnabled(true);
|
||||||
|
_ui.folderTreeWidget->sortByColumn(0, Qt::AscendingOrder);
|
||||||
|
|
||||||
connect(_ui.addFolderButton, SIGNAL(clicked()), SLOT(slotAddRemoteFolder()));
|
connect(_ui.addFolderButton, SIGNAL(clicked()), SLOT(slotAddRemoteFolder()));
|
||||||
connect(_ui.refreshButton, SIGNAL(clicked()), SLOT(slotRefreshFolders()));
|
connect(_ui.refreshButton, SIGNAL(clicked()), SLOT(slotRefreshFolders()));
|
||||||
connect(_ui.folderTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)), SIGNAL(completeChanged()));
|
connect(_ui.folderTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)), SIGNAL(completeChanged()));
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
@@ -85,6 +86,7 @@ void Logger::log(Log log)
|
|||||||
} else {
|
} else {
|
||||||
// msg += "ownCloud - ";
|
// msg += "ownCloud - ";
|
||||||
}
|
}
|
||||||
|
msg += QString().sprintf("%p ", (void*)QThread::currentThread());
|
||||||
msg += log.message;
|
msg += log.message;
|
||||||
// _logs.append(log);
|
// _logs.append(log);
|
||||||
// std::cout << qPrintable(log.message) << std::endl;
|
// std::cout << qPrintable(log.message) << std::endl;
|
||||||
|
|||||||
@@ -206,15 +206,16 @@ QString MirallConfigFile::configPathWithAppName() const
|
|||||||
return QFileInfo( configFile() ).dir().absolutePath().append("/");
|
return QFileInfo( configFile() ).dir().absolutePath().append("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const QLatin1String exclFile("sync-exclude.lst");
|
||||||
|
|
||||||
QString MirallConfigFile::excludeFile(Scope scope) const
|
QString MirallConfigFile::excludeFile(Scope scope) const
|
||||||
{
|
{
|
||||||
// prefer sync-exclude.lst, but if it does not exist, check for
|
// prefer sync-exclude.lst, but if it does not exist, check for
|
||||||
// exclude.lst for compatibility reasons in the user writeable
|
// exclude.lst for compatibility reasons in the user writeable
|
||||||
// directories.
|
// directories.
|
||||||
const QString exclFile("sync-exclude.lst");
|
|
||||||
QFileInfo fi;
|
|
||||||
|
|
||||||
if (scope != SystemScope) {
|
if (scope != SystemScope) {
|
||||||
|
QFileInfo fi;
|
||||||
fi.setFile( configPath(), exclFile );
|
fi.setFile( configPath(), exclFile );
|
||||||
|
|
||||||
if( ! fi.isReadable() ) {
|
if( ! fi.isReadable() ) {
|
||||||
@@ -223,32 +224,37 @@ QString MirallConfigFile::excludeFile(Scope scope) const
|
|||||||
if( ! fi.isReadable() ) {
|
if( ! fi.isReadable() ) {
|
||||||
fi.setFile( configPath(), exclFile );
|
fi.setFile( configPath(), exclFile );
|
||||||
}
|
}
|
||||||
|
return fi.absoluteFilePath();
|
||||||
|
} else if (scope != UserScope) {
|
||||||
|
return MirallConfigFile::excludeFileFromSystem();
|
||||||
|
} else {
|
||||||
|
Q_ASSERT(false);
|
||||||
|
return QString(); // unreachable
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (scope != UserScope) {
|
QString MirallConfigFile::excludeFileFromSystem()
|
||||||
// Check alternative places...
|
{
|
||||||
if( ! fi.isReadable() ) {
|
QFileInfo fi;
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
fi.setFile( QCoreApplication::applicationDirPath(), exclFile );
|
fi.setFile( QCoreApplication::applicationDirPath(), exclFile );
|
||||||
#endif
|
#endif
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
fi.setFile( QString( SYSCONFDIR "/%1").arg(Theme::instance()->appName()), exclFile );
|
fi.setFile( QString( SYSCONFDIR "/%1").arg(Theme::instance()->appName()), exclFile );
|
||||||
if ( ! fi.exists() ) {
|
if ( ! fi.exists() ) {
|
||||||
// Prefer to return the preferred path! Only use the fallback location
|
// Prefer to return the preferred path! Only use the fallback location
|
||||||
// if the other path does not exist and the fallback is valid.
|
// if the other path does not exist and the fallback is valid.
|
||||||
QFileInfo nextToBinary( QCoreApplication::applicationDirPath(), exclFile );
|
QFileInfo nextToBinary( QCoreApplication::applicationDirPath(), exclFile );
|
||||||
if (nextToBinary.exists()) {
|
if (nextToBinary.exists()) {
|
||||||
fi = nextToBinary;
|
fi = nextToBinary;
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
// exec path is inside the bundle
|
|
||||||
fi.setFile( QCoreApplication::applicationDirPath(),
|
|
||||||
QLatin1String("../Resources/") + exclFile );
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
// exec path is inside the bundle
|
||||||
|
fi.setFile( QCoreApplication::applicationDirPath(),
|
||||||
|
QLatin1String("../Resources/") + exclFile );
|
||||||
|
#endif
|
||||||
return fi.absoluteFilePath();
|
return fi.absoluteFilePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ public:
|
|||||||
QString configPathWithAppName() const;
|
QString configPathWithAppName() const;
|
||||||
QString configFile() const;
|
QString configFile() const;
|
||||||
QString excludeFile(Scope scope) const;
|
QString excludeFile(Scope scope) const;
|
||||||
|
static QString excludeFileFromSystem(); // doesn't access config dir
|
||||||
|
|
||||||
bool exists();
|
bool exists();
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ Q_DECLARE_METATYPE(QTimer*)
|
|||||||
|
|
||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
|
bool AbstractNetworkJob::preOc7WasDetected = false;
|
||||||
|
|
||||||
AbstractNetworkJob::AbstractNetworkJob(Account *account, const QString &path, QObject *parent)
|
AbstractNetworkJob::AbstractNetworkJob(Account *account, const QString &path, QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, _duration(0)
|
, _duration(0)
|
||||||
@@ -48,7 +50,12 @@ AbstractNetworkJob::AbstractNetworkJob(Account *account, const QString &path, QO
|
|||||||
, _path(path)
|
, _path(path)
|
||||||
{
|
{
|
||||||
_timer.setSingleShot(true);
|
_timer.setSingleShot(true);
|
||||||
_timer.setInterval(10*1000); // default to 10 seconds.
|
if (!AbstractNetworkJob::preOc7WasDetected) {
|
||||||
|
_timer.setInterval(15*1000); // default to 15 seconds.
|
||||||
|
} else {
|
||||||
|
qDebug() << "Pre-oc7 server detected, adjusting timeout values";
|
||||||
|
_timer.setInterval(60*1000); // long PROPFINDs in oc6 might take too long
|
||||||
|
}
|
||||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(slotTimeout()));
|
connect(&_timer, SIGNAL(timeout()), this, SLOT(slotTimeout()));
|
||||||
|
|
||||||
connect(this, SIGNAL(networkActivity()), SLOT(resetTimeout()));
|
connect(this, SIGNAL(networkActivity()), SLOT(resetTimeout()));
|
||||||
@@ -97,6 +104,12 @@ void AbstractNetworkJob::setPath(const QString &path)
|
|||||||
void AbstractNetworkJob::setupConnections(QNetworkReply *reply)
|
void AbstractNetworkJob::setupConnections(QNetworkReply *reply)
|
||||||
{
|
{
|
||||||
connect(reply, SIGNAL(finished()), SLOT(slotFinished()));
|
connect(reply, SIGNAL(finished()), SLOT(slotFinished()));
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
connect(reply, SIGNAL(encrypted()), SIGNAL(networkActivity()));
|
||||||
|
#endif
|
||||||
|
connect(reply->manager(), SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), SIGNAL(networkActivity()));
|
||||||
|
connect(reply, SIGNAL(sslErrors(QList<QSslError>)), SIGNAL(networkActivity()));
|
||||||
|
connect(reply, SIGNAL(metaDataChanged()), SIGNAL(networkActivity()));
|
||||||
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), SIGNAL(networkActivity()));
|
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), SIGNAL(networkActivity()));
|
||||||
connect(reply, SIGNAL(uploadProgress(qint64,qint64)), SIGNAL(networkActivity()));
|
connect(reply, SIGNAL(uploadProgress(qint64,qint64)), SIGNAL(networkActivity()));
|
||||||
}
|
}
|
||||||
@@ -375,8 +388,11 @@ void CheckServerJob::start()
|
|||||||
void CheckServerJob::slotTimeout()
|
void CheckServerJob::slotTimeout()
|
||||||
{
|
{
|
||||||
qDebug() << "TIMEOUT" << Q_FUNC_INFO;
|
qDebug() << "TIMEOUT" << Q_FUNC_INFO;
|
||||||
if (reply()->isRunning())
|
if (reply() && reply()->isRunning()) {
|
||||||
emit timeout(reply()->url());
|
emit timeout(reply()->url());
|
||||||
|
} else if (!reply()) {
|
||||||
|
qDebug() << Q_FUNC_INFO << "Timeout even there was no reply?";
|
||||||
|
}
|
||||||
deleteLater();
|
deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,7 +446,9 @@ bool CheckServerJob::finished()
|
|||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
QByteArray body = reply()->readAll();
|
QByteArray body = reply()->readAll();
|
||||||
if( body.isEmpty() ) {
|
int httpStatus = reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
if( body.isEmpty() || httpStatus != 200) {
|
||||||
|
qDebug() << "error: status.php replied " << httpStatus << body;
|
||||||
emit instanceNotFound(reply());
|
emit instanceNotFound(reply());
|
||||||
} else {
|
} else {
|
||||||
QVariantMap status = QtJson::parse(QString::fromUtf8(body), success).toMap();
|
QVariantMap status = QtJson::parse(QString::fromUtf8(body), success).toMap();
|
||||||
@@ -443,6 +461,12 @@ bool CheckServerJob::finished()
|
|||||||
if( status.contains("installed")
|
if( status.contains("installed")
|
||||||
&& status.contains("version")
|
&& status.contains("version")
|
||||||
&& status.contains("versionstring") ) {
|
&& status.contains("versionstring") ) {
|
||||||
|
|
||||||
|
QString versionString = status.value("version").toString();
|
||||||
|
if (versionString.contains('.') && versionString.split('.')[0].toInt() < 7) {
|
||||||
|
AbstractNetworkJob::preOc7WasDetected = true;
|
||||||
|
}
|
||||||
|
|
||||||
emit instanceFound(reply()->url(), status);
|
emit instanceFound(reply()->url(), status);
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "No proper answer on " << requestedUrl;
|
qDebug() << "No proper answer on " << requestedUrl;
|
||||||
|
|||||||
@@ -94,6 +94,9 @@ protected:
|
|||||||
QElapsedTimer _durationTimer;
|
QElapsedTimer _durationTimer;
|
||||||
quint64 _duration;
|
quint64 _duration;
|
||||||
|
|
||||||
|
// Timeout workarounds (Because of PHP session locking)
|
||||||
|
static bool preOc7WasDetected;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void slotFinished();
|
void slotFinished();
|
||||||
virtual void slotTimeout();
|
virtual void slotTimeout();
|
||||||
|
|||||||
@@ -90,18 +90,22 @@ void showInFileManager(const QString &localPath)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
QString explorer = "explorer.exe "; // FIXME: we trust it's in PATH
|
QString explorer = "explorer.exe "; // FIXME: we trust it's in PATH
|
||||||
|
QFileInfo fi(localPath);
|
||||||
|
|
||||||
if (!QFileInfo(localPath).isDir()) {
|
// canonicalFilePath returns empty if the file does not exist
|
||||||
explorer += QLatin1String("/select,");
|
if( !fi.canonicalFilePath().isEmpty() ) {
|
||||||
|
if (!fi.isDir()) {
|
||||||
|
explorer += QLatin1String("/select,");
|
||||||
|
}
|
||||||
|
explorer += QLatin1Char('"');
|
||||||
|
explorer += QDir::toNativeSeparators(fi.canonicalFilePath());
|
||||||
|
explorer += QLatin1Char('"');
|
||||||
|
|
||||||
|
qDebug() << "OO Open explorer commandline:" << explorer;
|
||||||
|
QProcess p;
|
||||||
|
p.start(explorer);
|
||||||
|
p.waitForFinished(5000);
|
||||||
}
|
}
|
||||||
explorer += QLatin1Char('"');
|
|
||||||
explorer += QDir::toNativeSeparators(localPath);
|
|
||||||
explorer += QLatin1Char('"');
|
|
||||||
|
|
||||||
qDebug() << "OO Open explorer commandline:" << explorer;
|
|
||||||
QProcess p;
|
|
||||||
p.start(explorer);
|
|
||||||
p.waitForFinished(5000);
|
|
||||||
} else if (Utility::isMac()) {
|
} else if (Utility::isMac()) {
|
||||||
QStringList scriptArgs;
|
QStringList scriptArgs;
|
||||||
scriptArgs << QLatin1String("-e")
|
scriptArgs << QLatin1String("-e")
|
||||||
@@ -182,4 +186,4 @@ void showInFileManager(const QString &localPath)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ ownCloudGui::ownCloudGui(Application *parent) :
|
|||||||
_settingsDialog(new SettingsDialog(this)),
|
_settingsDialog(new SettingsDialog(this)),
|
||||||
#endif
|
#endif
|
||||||
_logBrowser(0),
|
_logBrowser(0),
|
||||||
_contextMenu(0),
|
|
||||||
_recentActionsMenu(0),
|
_recentActionsMenu(0),
|
||||||
_folderOpenActionMapper(new QSignalMapper(this)),
|
_folderOpenActionMapper(new QSignalMapper(this)),
|
||||||
_recentItemsMapper(new QSignalMapper(this)),
|
_recentItemsMapper(new QSignalMapper(this)),
|
||||||
@@ -102,8 +101,9 @@ ownCloudGui::ownCloudGui(Application *parent) :
|
|||||||
|
|
||||||
void ownCloudGui::setupOverlayIcons()
|
void ownCloudGui::setupOverlayIcons()
|
||||||
{
|
{
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
if( Utility::isMac() && QFile::exists("/Library/ScriptingAdditions/OwnCloudFinder.osax") ) {
|
const QLatin1String finderExtension("/Library/ScriptingAdditions/SyncStateFinder.osax");
|
||||||
|
if(QFile::exists(finderExtension) ) {
|
||||||
QString aScript = QString::fromUtf8("tell application \"Finder\"\n"
|
QString aScript = QString::fromUtf8("tell application \"Finder\"\n"
|
||||||
" try\n"
|
" try\n"
|
||||||
" «event OWNCload»\n"
|
" «event OWNCload»\n"
|
||||||
@@ -123,7 +123,10 @@ void ownCloudGui::setupOverlayIcons()
|
|||||||
QString resultAsString(result); // if appropriate
|
QString resultAsString(result); // if appropriate
|
||||||
qDebug() << "Laod Finder Overlay-Plugin: " << resultAsString << ": " << p.exitCode()
|
qDebug() << "Laod Finder Overlay-Plugin: " << resultAsString << ": " << p.exitCode()
|
||||||
<< (p.exitCode() != 0 ? p.errorString() : QString::null);
|
<< (p.exitCode() != 0 ? p.errorString() : QString::null);
|
||||||
|
} else {
|
||||||
|
qDebug() << finderExtension << "does not exist! Finder Overlay Plugin loading failed";
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should rather be in application.... or rather in MirallConfigFile?
|
// This should rather be in application.... or rather in MirallConfigFile?
|
||||||
@@ -303,11 +306,11 @@ void ownCloudGui::setupContextMenu()
|
|||||||
_recentActionsMenu->addAction(tr("None."));
|
_recentActionsMenu->addAction(tr("None."));
|
||||||
_recentActionsMenu->addAction(_actionRecent);
|
_recentActionsMenu->addAction(_actionRecent);
|
||||||
} else {
|
} else {
|
||||||
_contextMenu = new QMenu(_contextMenu);
|
_contextMenu.reset(new QMenu());
|
||||||
_recentActionsMenu = new QMenu(tr("Recent Changes"));
|
_recentActionsMenu = new QMenu(tr("Recent Changes"), _contextMenu.data());
|
||||||
// this must be called only once after creating the context menu, or
|
// this must be called only once after creating the context menu, or
|
||||||
// it will trigger a bug in Ubuntu's SNI bridge patch (11.10, 12.04).
|
// it will trigger a bug in Ubuntu's SNI bridge patch (11.10, 12.04).
|
||||||
_tray->setContextMenu(_contextMenu);
|
_tray->setContextMenu(_contextMenu.data());
|
||||||
}
|
}
|
||||||
_contextMenu->setTitle(Theme::instance()->appNameGUI() );
|
_contextMenu->setTitle(Theme::instance()->appNameGUI() );
|
||||||
_contextMenu->addAction(_actionOpenoC);
|
_contextMenu->addAction(_actionOpenoC);
|
||||||
@@ -464,7 +467,7 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const Progress::Info
|
|||||||
Q_UNUSED(folder);
|
Q_UNUSED(folder);
|
||||||
|
|
||||||
if (!progress._currentDiscoveredFolder.isEmpty()) {
|
if (!progress._currentDiscoveredFolder.isEmpty()) {
|
||||||
_actionStatus->setText( tr("Discovering %1")
|
_actionStatus->setText( tr("Discovering '%1'")
|
||||||
.arg( progress._currentDiscoveredFolder ));
|
.arg( progress._currentDiscoveredFolder ));
|
||||||
} else if (progress._totalSize == 0 ) {
|
} else if (progress._totalSize == 0 ) {
|
||||||
quint64 currentFile = progress._completedFileCount + progress._currentItems.count();
|
quint64 currentFile = progress._completedFileCount + progress._currentItems.count();
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
QPointer<LogBrowser>_logBrowser;
|
QPointer<LogBrowser>_logBrowser;
|
||||||
// tray's menu
|
// tray's menu
|
||||||
QMenu *_contextMenu;
|
QScopedPointer<QMenu> _contextMenu;
|
||||||
QMenu *_recentActionsMenu;
|
QMenu *_recentActionsMenu;
|
||||||
|
|
||||||
QAction *_actionLogin;
|
QAction *_actionLogin;
|
||||||
|
|||||||
@@ -56,11 +56,10 @@ void PropagateItemJob::done(SyncFileItem::Status status, const QString &errorStr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( _propagator->_abortRequested.fetchAndAddRelaxed(0) ) {
|
if( _propagator->_abortRequested.fetchAndAddRelaxed(0) &&
|
||||||
|
(status == SyncFileItem::NormalError || status == SyncFileItem::FatalError)) {
|
||||||
// an abort request is ongoing. Change the status to Soft-Error
|
// an abort request is ongoing. Change the status to Soft-Error
|
||||||
|
|
||||||
status = SyncFileItem::SoftError;
|
status = SyncFileItem::SoftError;
|
||||||
_item._errorString = tr("Operation was canceled by user interaction.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_item._status = status;
|
_item._status = status;
|
||||||
@@ -78,7 +77,7 @@ void PropagateItemJob::done(SyncFileItem::Status status, const QString &errorStr
|
|||||||
}
|
}
|
||||||
retries = defaultRetriesCount.fetchAndAddAcquire(0);
|
retries = defaultRetriesCount.fetchAndAddAcquire(0);
|
||||||
}
|
}
|
||||||
SyncJournalBlacklistRecord record(_item, retries);;
|
SyncJournalBlacklistRecord record(_item, retries);
|
||||||
|
|
||||||
switch( status ) {
|
switch( status ) {
|
||||||
case SyncFileItem::SoftError:
|
case SyncFileItem::SoftError:
|
||||||
@@ -98,9 +97,13 @@ void PropagateItemJob::done(SyncFileItem::Status status, const QString &errorStr
|
|||||||
break;
|
break;
|
||||||
case SyncFileItem::Success:
|
case SyncFileItem::Success:
|
||||||
case SyncFileItem::Restoration:
|
case SyncFileItem::Restoration:
|
||||||
if( _item._blacklistedInDb ) {
|
if( _item._hasBlacklistEntry ) {
|
||||||
// wipe blacklist entry.
|
// wipe blacklist entry.
|
||||||
_propagator->_journal->wipeBlacklistEntry(_item._file);
|
_propagator->_journal->wipeBlacklistEntry(_item._file);
|
||||||
|
// remove a blacklist entry in case the file was moved.
|
||||||
|
if( _item._originalFile != _item._file ) {
|
||||||
|
_propagator->_journal->wipeBlacklistEntry(_item._originalFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SyncFileItem::Conflict:
|
case SyncFileItem::Conflict:
|
||||||
@@ -382,10 +385,10 @@ bool OwncloudPropagator::localFileNameClash( const QString& relFile )
|
|||||||
// returns false.
|
// returns false.
|
||||||
} else {
|
} else {
|
||||||
QString realFileName = QString::fromWCharArray( FindFileData.cFileName );
|
QString realFileName = QString::fromWCharArray( FindFileData.cFileName );
|
||||||
qDebug() << Q_FUNC_INFO << "Real file name is " << realFileName;
|
|
||||||
FindClose(hFind);
|
FindClose(hFind);
|
||||||
|
|
||||||
if( ! file.endsWith(realFileName, Qt::CaseSensitive) ) {
|
if( ! file.endsWith(realFileName, Qt::CaseSensitive) ) {
|
||||||
|
qDebug() << Q_FUNC_INFO << "Detected case clash between" << file << "and" << realFileName;
|
||||||
re = true;
|
re = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ void OwncloudSetupWizard::startWizard()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ocWizard->setProperty("oldLocalFolder", localFolder);
|
||||||
_ocWizard->setProperty("localFolder", localFolder);
|
_ocWizard->setProperty("localFolder", localFolder);
|
||||||
|
|
||||||
// remember the local folder to compare later if it changed, but clean first
|
// remember the local folder to compare later if it changed, but clean first
|
||||||
@@ -401,7 +402,6 @@ void OwncloudSetupWizard::slotAssistantFinished( int result )
|
|||||||
_ocWizard->account()->deleteLater();
|
_ocWizard->account()->deleteLater();
|
||||||
qDebug() << "Rejected the new config, use the old!";
|
qDebug() << "Rejected the new config, use the old!";
|
||||||
} else if( result == QDialog::Accepted ) {
|
} else if( result == QDialog::Accepted ) {
|
||||||
|
|
||||||
Account *newAccount = _ocWizard->account();
|
Account *newAccount = _ocWizard->account();
|
||||||
Account *origAccount = AccountManager::instance()->account();
|
Account *origAccount = AccountManager::instance()->account();
|
||||||
|
|
||||||
@@ -410,6 +410,13 @@ void OwncloudSetupWizard::slotAssistantFinished( int result )
|
|||||||
localFolder.append(QLatin1Char('/'));
|
localFolder.append(QLatin1Char('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Folder *f = folderMan->folderForPath(localFolder);
|
||||||
|
if( f ) {
|
||||||
|
folderMan->setSyncEnabled(false);
|
||||||
|
folderMan->terminateSyncProcess(f->alias());
|
||||||
|
f->journalDb()->close();
|
||||||
|
}
|
||||||
|
|
||||||
bool isInitialSetup = (origAccount == 0);
|
bool isInitialSetup = (origAccount == 0);
|
||||||
|
|
||||||
// check if either the account or the local folder changed, than reinit
|
// check if either the account or the local folder changed, than reinit
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ QString ownCloudTheme::about() const
|
|||||||
"<p>Copyright ownCloud, Inc.</p>"
|
"<p>Copyright ownCloud, Inc.</p>"
|
||||||
"<p>Licensed under the GNU General Public License (GPL) Version 2.0<br/>"
|
"<p>Licensed under the GNU General Public License (GPL) Version 2.0<br/>"
|
||||||
"ownCloud and the ownCloud Logo are registered trademarks of ownCloud, "
|
"ownCloud and the ownCloud Logo are registered trademarks of ownCloud, "
|
||||||
"Inc. in the United States, other countries, or both</p>"
|
"Inc. in the United States, other countries, or both.</p>"
|
||||||
)
|
)
|
||||||
.arg(MIRALL_VERSION_STRING)
|
.arg(MIRALL_VERSION_STRING)
|
||||||
.arg("http://" MIRALL_STRINGIFY(APPLICATION_DOMAIN))
|
.arg("http://" MIRALL_STRINGIFY(APPLICATION_DOMAIN))
|
||||||
|
|||||||
295
src/mirall/ownsql.cpp
Normal file
295
src/mirall/ownsql.cpp
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QString>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include "ownsql.h"
|
||||||
|
#include "utility.h"
|
||||||
|
|
||||||
|
#define SQLITE_SLEEP_TIME_USEC 100000
|
||||||
|
#define SQLITE_REPEAT_COUNT 20
|
||||||
|
|
||||||
|
#define SQLITE_DO(A) if(1) { \
|
||||||
|
_errId = (A); if(_errId != SQLITE_OK) { _error= QString::fromUtf8(sqlite3_errmsg(_db)); \
|
||||||
|
} }
|
||||||
|
|
||||||
|
namespace Mirall {
|
||||||
|
|
||||||
|
SqlDatabase::SqlDatabase()
|
||||||
|
:_db(0),
|
||||||
|
_errId(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SqlDatabase::isOpen()
|
||||||
|
{
|
||||||
|
return _db != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SqlDatabase::open( const QString& filename )
|
||||||
|
{
|
||||||
|
if(isOpen()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int flag = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_NOMUTEX;
|
||||||
|
SQLITE_DO( sqlite3_open_v2(filename.toUtf8().constData(), &_db, flag, 0) );
|
||||||
|
|
||||||
|
if( _errId != SQLITE_OK ) {
|
||||||
|
qDebug() << Q_FUNC_INFO << "Error:" << _error << "for" << filename;
|
||||||
|
close();
|
||||||
|
_db = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_db) {
|
||||||
|
sqlite3_busy_timeout(_db, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return isOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SqlDatabase::error() const
|
||||||
|
{
|
||||||
|
const QString err(_error);
|
||||||
|
// _error.clear();
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SqlDatabase::close()
|
||||||
|
{
|
||||||
|
if( _db ) {
|
||||||
|
SQLITE_DO(sqlite3_close(_db) );
|
||||||
|
_db = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SqlDatabase::transaction()
|
||||||
|
{
|
||||||
|
if( ! _db ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SQLITE_DO(sqlite3_exec(_db, "BEGIN", 0, 0, 0));
|
||||||
|
return _errId == SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SqlDatabase::commit()
|
||||||
|
{
|
||||||
|
if( ! _db ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SQLITE_DO(sqlite3_exec(_db, "COMMIT", 0, 0, 0));
|
||||||
|
return _errId == SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3* SqlDatabase::sqliteDb()
|
||||||
|
{
|
||||||
|
return _db;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================================================== */
|
||||||
|
|
||||||
|
SqlQuery::SqlQuery( SqlDatabase& db )
|
||||||
|
:_db(db.sqliteDb()),
|
||||||
|
_stmt(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SqlQuery::~SqlQuery()
|
||||||
|
{
|
||||||
|
if( _stmt ) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SqlQuery::SqlQuery(const QString& sql, SqlDatabase& db)
|
||||||
|
:_db(db.sqliteDb()),
|
||||||
|
_stmt(0)
|
||||||
|
{
|
||||||
|
prepare(sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SqlQuery::prepare( const QString& sql)
|
||||||
|
{
|
||||||
|
QString s(sql);
|
||||||
|
_sql = s.trimmed();
|
||||||
|
if(_stmt ) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
if(!_sql.isEmpty() ) {
|
||||||
|
int n = 0;
|
||||||
|
int rc;
|
||||||
|
do {
|
||||||
|
rc = sqlite3_prepare_v2(_db, _sql.toUtf8().constData(), -1, &_stmt, 0);
|
||||||
|
if( (rc == SQLITE_BUSY) || (rc == SQLITE_LOCKED) ) {
|
||||||
|
n++;
|
||||||
|
Mirall::Utility::usleep(SQLITE_SLEEP_TIME_USEC);
|
||||||
|
}
|
||||||
|
} while( (n < SQLITE_REPEAT_COUNT) && ((rc == SQLITE_BUSY) || (rc == SQLITE_LOCKED)));
|
||||||
|
_errId = rc;
|
||||||
|
|
||||||
|
if( _errId != SQLITE_OK ) {
|
||||||
|
qDebug() << "Sqlite prepare statement error:" << _error << "in"<<_sql;
|
||||||
|
}
|
||||||
|
// Q_ASSERT(_errId == SQLITE_OK);
|
||||||
|
}
|
||||||
|
return _errId;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SqlQuery::isSelect()
|
||||||
|
{
|
||||||
|
return (!_sql.isEmpty() && _sql.startsWith("SELECT", Qt::CaseInsensitive));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SqlQuery::isPragma()
|
||||||
|
{
|
||||||
|
return (!_sql.isEmpty() && _sql.startsWith("PRAGMA", Qt::CaseInsensitive));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SqlQuery::exec()
|
||||||
|
{
|
||||||
|
// Don't do anything for selects, that is how we use the lib :-|
|
||||||
|
if(_stmt && !isSelect() && !isPragma() ) {
|
||||||
|
int rc, n = 0;
|
||||||
|
do {
|
||||||
|
rc = sqlite3_step(_stmt);
|
||||||
|
if( rc == SQLITE_LOCKED ) {
|
||||||
|
rc = sqlite3_reset(_stmt); /* This will also return SQLITE_LOCKED */
|
||||||
|
n++;
|
||||||
|
Mirall::Utility::usleep(SQLITE_SLEEP_TIME_USEC);
|
||||||
|
} else if( rc == SQLITE_BUSY ) {
|
||||||
|
Mirall::Utility::usleep(SQLITE_SLEEP_TIME_USEC);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
} while( (n < SQLITE_REPEAT_COUNT) && ((rc == SQLITE_BUSY) || (rc == SQLITE_LOCKED)));
|
||||||
|
_errId = rc;
|
||||||
|
|
||||||
|
return (_errId == SQLITE_DONE); // either SQLITE_ROW or SQLITE_DONE
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SqlQuery::next()
|
||||||
|
{
|
||||||
|
SQLITE_DO(sqlite3_step(_stmt));
|
||||||
|
return _errId == SQLITE_ROW;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SqlQuery::bindValue(int pos, const QVariant& value)
|
||||||
|
{
|
||||||
|
int res = -1;
|
||||||
|
if( _stmt ) {
|
||||||
|
switch (value.type()) {
|
||||||
|
case QVariant::Int:
|
||||||
|
case QVariant::Bool:
|
||||||
|
res = sqlite3_bind_int(_stmt, pos, value.toInt());
|
||||||
|
break;
|
||||||
|
case QVariant::Double:
|
||||||
|
res = sqlite3_bind_double(_stmt, pos, value.toDouble());
|
||||||
|
break;
|
||||||
|
case QVariant::UInt:
|
||||||
|
case QVariant::LongLong:
|
||||||
|
res = sqlite3_bind_int64(_stmt, pos, value.toLongLong());
|
||||||
|
break;
|
||||||
|
case QVariant::DateTime: {
|
||||||
|
const QDateTime dateTime = value.toDateTime();
|
||||||
|
const QString str = dateTime.toString(QLatin1String("yyyy-MM-ddThh:mm:ss.zzz"));
|
||||||
|
res = sqlite3_bind_text16(_stmt, pos, str.utf16(),
|
||||||
|
str.size() * sizeof(ushort), SQLITE_TRANSIENT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QVariant::Time: {
|
||||||
|
const QTime time = value.toTime();
|
||||||
|
const QString str = time.toString(QLatin1String("hh:mm:ss.zzz"));
|
||||||
|
res = sqlite3_bind_text16(_stmt, pos, str.utf16(),
|
||||||
|
str.size() * sizeof(ushort), SQLITE_TRANSIENT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QVariant::String: {
|
||||||
|
if( !value.toString().isNull() ) {
|
||||||
|
// lifetime of string == lifetime of its qvariant
|
||||||
|
const QString *str = static_cast<const QString*>(value.constData());
|
||||||
|
res = sqlite3_bind_text16(_stmt, pos, str->utf16(),
|
||||||
|
(str->size()) * sizeof(QChar), SQLITE_TRANSIENT);
|
||||||
|
} else {
|
||||||
|
// unbound value create a null entry.
|
||||||
|
res = SQLITE_OK;
|
||||||
|
}
|
||||||
|
break; }
|
||||||
|
default: {
|
||||||
|
QString str = value.toString();
|
||||||
|
// SQLITE_TRANSIENT makes sure that sqlite buffers the data
|
||||||
|
res = sqlite3_bind_text16(_stmt, pos, str.utf16(),
|
||||||
|
(str.size()) * sizeof(QChar), SQLITE_TRANSIENT);
|
||||||
|
break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (res != SQLITE_OK) {
|
||||||
|
qDebug() << Q_FUNC_INFO << "ERROR" << value.toString() << res;
|
||||||
|
}
|
||||||
|
Q_ASSERT( res == SQLITE_OK );
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SqlQuery::stringValue(int index)
|
||||||
|
{
|
||||||
|
return QString::fromUtf16(static_cast<const ushort*>(sqlite3_column_text16(_stmt, index)));
|
||||||
|
}
|
||||||
|
|
||||||
|
int SqlQuery::intValue(int index)
|
||||||
|
{
|
||||||
|
return sqlite3_column_int(_stmt, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 SqlQuery::int64Value(int index)
|
||||||
|
{
|
||||||
|
return sqlite3_column_int64(_stmt, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray SqlQuery::baValue(int index)
|
||||||
|
{
|
||||||
|
return QByteArray( static_cast<const char*>(sqlite3_column_blob(_stmt, index)),
|
||||||
|
sqlite3_column_bytes(_stmt, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SqlQuery::error() const
|
||||||
|
{
|
||||||
|
return _error;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SqlQuery::lastQuery() const
|
||||||
|
{
|
||||||
|
return _sql;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SqlQuery::numRowsAffected()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SqlQuery::finish()
|
||||||
|
{
|
||||||
|
SQLITE_DO(sqlite3_finalize(_stmt));
|
||||||
|
_stmt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SqlQuery::reset()
|
||||||
|
{
|
||||||
|
SQLITE_DO(sqlite3_reset(_stmt));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Mirall
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user