mirror of
https://github.com/chylex/Nextcloud-Desktop.git
synced 2026-04-03 09:11:33 +02:00
Compare commits
893 Commits
v1.6.1
...
v1.7.0-rc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
1d8900dc19 | ||
|
|
171fd22d91 | ||
|
|
78d50f4033 | ||
|
|
fee18dd457 | ||
|
|
81d3ce8257 | ||
|
|
5213970c3d | ||
|
|
bcc06af904 | ||
|
|
a98242a2b8 | ||
|
|
5f715ca063 | ||
|
|
0ceeff62d6 | ||
|
|
f53a7c0e4a | ||
|
|
41b07d045a | ||
|
|
0d303f1d1f | ||
|
|
b6d97cfffb | ||
|
|
3e982ad34c | ||
|
|
dafd9c308f | ||
|
|
7f836cc01b | ||
|
|
147fa60f81 | ||
|
|
a1b9405e2e | ||
|
|
db02d44c6a | ||
|
|
dff1f77dfa | ||
|
|
1a2fff8ed8 | ||
|
|
52c12b33c3 | ||
|
|
29987ca2aa | ||
|
|
02f971b534 | ||
|
|
479b340d75 | ||
|
|
06c48f58cc | ||
|
|
0ee81a2865 | ||
|
|
e78c251832 | ||
|
|
efbc495f79 | ||
|
|
f8b73eb9d9 | ||
|
|
f25a590af5 | ||
|
|
0539098371 | ||
|
|
788c27bf2f | ||
|
|
a587148c73 | ||
|
|
9acd3a58ee | ||
|
|
449f5adaba | ||
|
|
2380b7af3d | ||
|
|
10989d13e4 | ||
|
|
fe1653ede6 | ||
|
|
b4071cec01 | ||
|
|
b1c842373d | ||
|
|
a3d70b3cf6 | ||
|
|
70912c44de | ||
|
|
98d9f7924d | ||
|
|
172295289e | ||
|
|
8ba08d7e87 | ||
|
|
8915f94931 | ||
|
|
31bf844452 | ||
|
|
0c8b74a025 | ||
|
|
dad8c1c27c | ||
|
|
2e12acdf32 | ||
|
|
d6156dd755 | ||
|
|
2c67a7ca71 | ||
|
|
688b8dcc38 | ||
|
|
280edee1db | ||
|
|
b9ea72f189 | ||
|
|
8f8265b219 | ||
|
|
00ae3c3120 | ||
|
|
1e49f152be | ||
|
|
f72ca4d83e | ||
|
|
5b10a9f3a7 | ||
|
|
d0fb1acebb | ||
|
|
09be4d22ee | ||
|
|
11a64320f0 | ||
|
|
4eac66b84a | ||
|
|
497b7808b6 | ||
|
|
b10c2b5946 | ||
|
|
fa881ba1c7 | ||
|
|
eb1b17e8e4 | ||
|
|
2eec85a97c | ||
|
|
c85b6193d5 | ||
|
|
fc36e7eccf | ||
|
|
0cc2bbf5d9 | ||
|
|
d2669debb9 | ||
|
|
637fb449c6 | ||
|
|
e82b319ee7 | ||
|
|
e9248066df | ||
|
|
819472d366 | ||
|
|
21bbdd6f49 | ||
|
|
a88ac00115 | ||
|
|
30683b38a8 | ||
|
|
45aefeb146 | ||
|
|
580ecbff0c | ||
|
|
db3318886e | ||
|
|
54eb837950 | ||
|
|
0bd73788f4 | ||
|
|
e395282e0e | ||
|
|
1f129d0bcb | ||
|
|
c2ae5e5fd1 | ||
|
|
292a7357bd | ||
|
|
99aa2cdf2a | ||
|
|
0eb9401c62 | ||
|
|
ab14a589c8 | ||
|
|
122fa596b3 | ||
|
|
5406407ed6 | ||
|
|
b72cee2783 | ||
|
|
fe023e2229 | ||
|
|
1dae928a7c | ||
|
|
9b1779bb06 | ||
|
|
97cc05eeea | ||
|
|
20dd3b0a69 | ||
|
|
f348eabf19 | ||
|
|
5870a57002 | ||
|
|
278bc5a8cd | ||
|
|
3c89415df1 | ||
|
|
5981f700f5 | ||
|
|
af5e8ee18c | ||
|
|
52e8343f76 | ||
|
|
a4dbf5942c | ||
|
|
ada1d42ebf | ||
|
|
f27182ae05 | ||
|
|
2fddf05515 | ||
|
|
91d1864840 | ||
|
|
79052ba7c6 | ||
|
|
0edd4d3c02 | ||
|
|
71516c480d | ||
|
|
1304c2c4ab | ||
|
|
a84b7dc27e | ||
|
|
927af0adec | ||
|
|
2dfbc2058f | ||
|
|
79ee6c2f3b | ||
|
|
f59a6862ca | ||
|
|
fa962b7f53 | ||
|
|
71408bab60 | ||
|
|
9e015eb654 | ||
|
|
4ce03e8b61 | ||
|
|
68b7f412b6 | ||
|
|
20011f3a84 | ||
|
|
2d020b5989 | ||
|
|
1909b465dc | ||
|
|
88b7f2e0ee | ||
|
|
531d586460 | ||
|
|
2630a73a1c | ||
|
|
4decd15ca9 | ||
|
|
3a59dd24f3 | ||
|
|
1cf1f6edcb | ||
|
|
5d36a27893 | ||
|
|
da94533647 | ||
|
|
db08d5021e | ||
|
|
69066013c1 | ||
|
|
aef569ee9d | ||
|
|
cf881aa6dc | ||
|
|
a48bf3142c | ||
|
|
33d9f4b882 | ||
|
|
49c40a4b11 | ||
|
|
d1eff0ae24 | ||
|
|
c0131695c5 | ||
|
|
fcbadda40f | ||
|
|
2455faa6fe | ||
|
|
7da8a5e374 | ||
|
|
b3950165c4 | ||
|
|
b8ab859c59 | ||
|
|
99a3cb0eab | ||
|
|
0be4b59cff | ||
|
|
ddfc7c75df | ||
|
|
7618f29657 | ||
|
|
291231c561 | ||
|
|
68792ee9db | ||
|
|
7ce2a93c63 | ||
|
|
4d33773cef | ||
|
|
5d19426930 | ||
|
|
1b51a10b19 | ||
|
|
aab870af32 | ||
|
|
7c70ada423 | ||
|
|
12e2bac16b | ||
|
|
34a27c748a | ||
|
|
a73fbccf8c | ||
|
|
7f1d707d23 | ||
|
|
f1fb36bcb8 | ||
|
|
25c274a0bd | ||
|
|
d4bbd28757 | ||
|
|
98b7248df0 | ||
|
|
0fb0f2c204 | ||
|
|
79d13d9242 | ||
|
|
b6f42a91f4 | ||
|
|
cc5f5cf3a6 | ||
|
|
79f00c2a2a | ||
|
|
e5068e7543 | ||
|
|
858218ac34 | ||
|
|
d69049ce10 | ||
|
|
59a9cc7c12 | ||
|
|
2f34b046d0 | ||
|
|
a73316306d | ||
|
|
928652e4cf | ||
|
|
7950b49cb1 | ||
|
|
f8b1b243c1 | ||
|
|
cc6aa66ab0 | ||
|
|
ea381392a7 | ||
|
|
bb7f63dcfd | ||
|
|
253d65727b | ||
|
|
61138b58bf | ||
|
|
5490063b7e | ||
|
|
d2e1489fe7 | ||
|
|
eb898646bc | ||
|
|
79b547b83b | ||
|
|
2356601bb3 | ||
|
|
9b88c7d3c1 | ||
|
|
302499b483 | ||
|
|
03dc27a327 | ||
|
|
9291ace558 | ||
|
|
15c11ea172 | ||
|
|
cd6950d984 | ||
|
|
de96350bee | ||
|
|
a9f1e165b5 | ||
|
|
c60b433c42 | ||
|
|
933c7e36d1 | ||
|
|
6025b3a91b | ||
|
|
c473428be6 | ||
|
|
e06e5fe55f | ||
|
|
dc8f437b31 | ||
|
|
2219d409a4 | ||
|
|
aabcf80774 | ||
|
|
1cf956ec21 | ||
|
|
315c2eb4ca | ||
|
|
54e2b9345b | ||
|
|
9743fee8f9 | ||
|
|
696f801df0 | ||
|
|
fef0d0b31c | ||
|
|
75101a0319 | ||
|
|
d1a660ce20 | ||
|
|
4356005c5a | ||
|
|
86a00eee3f | ||
|
|
ccf532672b | ||
|
|
6b52e9db34 | ||
|
|
8fdee79505 | ||
|
|
d9de6e68ad | ||
|
|
988fe70771 | ||
|
|
132fac86d7 | ||
|
|
d02175210b | ||
|
|
1dd3d080b8 | ||
|
|
d171431ac7 | ||
|
|
76e0d61b19 | ||
|
|
cc6d83a953 | ||
|
|
617887a0c6 | ||
|
|
e4fe4cb4d3 | ||
|
|
dc0a054d94 | ||
|
|
924d9b985f | ||
|
|
bb3bd6930a | ||
|
|
1245ed6f06 | ||
|
|
01b0ee49de | ||
|
|
2436ef9574 | ||
|
|
94f3a1ab1f | ||
|
|
9c98883bea | ||
|
|
2fb19e25b5 | ||
|
|
6fbbe2d0e4 | ||
|
|
c291eb3db4 | ||
|
|
7f38ce8908 | ||
|
|
1781400340 | ||
|
|
3760f14da8 | ||
|
|
dc18366111 | ||
|
|
936252765a | ||
|
|
b62b87eed3 | ||
|
|
4b716f3ea6 | ||
|
|
ddbe181e48 | ||
|
|
27f9d4523b | ||
|
|
8a7cfbd8de | ||
|
|
463a9a5485 | ||
|
|
ee7fe4a38a | ||
|
|
dccb9def3a | ||
|
|
5c5d57a996 | ||
|
|
de2ce5a0a2 | ||
|
|
7b114e2cae | ||
|
|
25d519fed3 | ||
|
|
8d819956d3 | ||
|
|
4aec783362 | ||
|
|
b494181764 | ||
|
|
9575271fcd | ||
|
|
b6eda9076e | ||
|
|
88072a985a | ||
|
|
c27f151451 | ||
|
|
64a7025522 | ||
|
|
ce2741cebc | ||
|
|
b40b670639 | ||
|
|
3d6b622879 | ||
|
|
4c67a8812a | ||
|
|
4c4d02c0d0 | ||
|
|
c1831f4946 | ||
|
|
4b2c1bacd1 | ||
|
|
3909102436 | ||
|
|
78e50747e4 | ||
|
|
b09498d852 | ||
|
|
7fcf723039 | ||
|
|
d27ab8c6ca | ||
|
|
0350508b65 | ||
|
|
32739cc305 | ||
|
|
f515fe77c4 | ||
|
|
f6d20cbe55 | ||
|
|
8bc0d9acd3 | ||
|
|
73325bcd41 | ||
|
|
1b5bbfdad3 | ||
|
|
fcd211b190 | ||
|
|
55b3eb467f | ||
|
|
192c23bfce | ||
|
|
72e0418e4c | ||
|
|
1544606bf0 | ||
|
|
255330d342 | ||
|
|
ad139e19ab | ||
|
|
4c0891a22e | ||
|
|
8e6e51f9a6 | ||
|
|
faa502163e | ||
|
|
4ff0e7e0a2 | ||
|
|
12459bf07e | ||
|
|
b25ef28e82 | ||
|
|
ef6c82ba00 | ||
|
|
7e009667a2 | ||
|
|
1f1eb933d1 | ||
|
|
aa85e875bd | ||
|
|
1b4c613fa6 | ||
|
|
57ef515def | ||
|
|
59643177af | ||
|
|
e2d5ae1035 | ||
|
|
cd9f2e5ea5 | ||
|
|
600a6d9346 | ||
|
|
0e22864426 | ||
|
|
5306cdc7a1 | ||
|
|
344b98bf13 | ||
|
|
261d7ee688 | ||
|
|
633267c457 | ||
|
|
80f9ed70d3 | ||
|
|
fa8f6f91c4 | ||
|
|
c3f8e099f4 | ||
|
|
6cb8134690 | ||
|
|
95a77e5ccc | ||
|
|
21783ecef7 | ||
|
|
d8a8b53fc9 | ||
|
|
e71ce01f90 | ||
|
|
6827f9977c | ||
|
|
6d24bd0361 | ||
|
|
22c1629dd3 | ||
|
|
bd9d5432f5 | ||
|
|
370ee5c6f6 | ||
|
|
fe2e4d87c5 | ||
|
|
e9c4635f6b | ||
|
|
7337010fd8 | ||
|
|
f06019ab81 | ||
|
|
55567f8dd2 | ||
|
|
2ccfdcb084 | ||
|
|
084d9de4c9 | ||
|
|
41875c2ddb | ||
|
|
4ad9ff4301 | ||
|
|
c7ff1e9b3f | ||
|
|
fe3f751a8a | ||
|
|
996b7166d2 | ||
|
|
839b2fa8fd | ||
|
|
8b1aebcdba | ||
|
|
f4e2041b0b | ||
|
|
24df6f838d | ||
|
|
c313cc02f2 | ||
|
|
4e13c882f8 | ||
|
|
0fe51d826f | ||
|
|
b2976baf9b | ||
|
|
a0a5a49d7b | ||
|
|
9a1781f613 | ||
|
|
f983264b5d | ||
|
|
40cebeedfc | ||
|
|
1f9280c68e | ||
|
|
14ed261606 | ||
|
|
4fb671e7f4 | ||
|
|
aad5c96759 | ||
|
|
72b8da317f | ||
|
|
7f9033f1f1 | ||
|
|
a42e384935 | ||
|
|
9b37357513 | ||
|
|
23269c9a08 | ||
|
|
327f70240c | ||
|
|
0a7642dbe0 | ||
|
|
742b036a07 | ||
|
|
6e00989a9e | ||
|
|
68f0227ca1 | ||
|
|
fe9a2e7ba4 | ||
|
|
a248fc36fe | ||
|
|
e28a7a7ae3 | ||
|
|
b92789825d | ||
|
|
c3b6aecb79 | ||
|
|
4688126f84 | ||
|
|
5a5c03a826 | ||
|
|
f3477877d0 | ||
|
|
7bef588851 | ||
|
|
72a25cf6ee | ||
|
|
74e13f4c70 | ||
|
|
3c09ef6cbf | ||
|
|
68bfcf5d24 | ||
|
|
b2a10de71a | ||
|
|
267b9e5c2f | ||
|
|
55d94bf15a | ||
|
|
629e2a9e1c | ||
|
|
86acdf69d9 | ||
|
|
a6987ad703 | ||
|
|
5642e40bc8 | ||
|
|
50d178feaa | ||
|
|
753aa9132e | ||
|
|
8d71328192 | ||
|
|
cfdfd6a860 | ||
|
|
17b320f7dc | ||
|
|
0c9d57228d | ||
|
|
f1ad82d0ba | ||
|
|
2fb283749c | ||
|
|
5254c9785c | ||
|
|
0f37484b8a | ||
|
|
5a4c023fc9 | ||
|
|
e8afac3a01 | ||
|
|
6284517dc9 | ||
|
|
80c096b6f1 | ||
|
|
f004d5085d | ||
|
|
98e21ae0ad | ||
|
|
00274722ce | ||
|
|
8b93678e3d | ||
|
|
3d0c009719 | ||
|
|
1b3ec955b1 | ||
|
|
208011f6ab | ||
|
|
f84e0010ee | ||
|
|
c97f46d403 | ||
|
|
5356898efc | ||
|
|
1fb52f0d8b | ||
|
|
d4de024f15 | ||
|
|
1d9d88ca85 | ||
|
|
2ca8805cda | ||
|
|
8e5c41e6f3 | ||
|
|
0f7efbc22e | ||
|
|
6b7bd07c97 | ||
|
|
8d85516e72 | ||
|
|
0f4cf74ae0 | ||
|
|
4dfe0fad7d | ||
|
|
2e91ea8093 | ||
|
|
77e3480b2f | ||
|
|
bca1ef42fc | ||
|
|
010ab7119e | ||
|
|
3cb93510ac | ||
|
|
8a88ca6f34 | ||
|
|
81d786733d | ||
|
|
336e74b992 | ||
|
|
beb9300b4e | ||
|
|
74b3e2ce3f | ||
|
|
c35880d4f1 | ||
|
|
ed6e3e4ee2 | ||
|
|
f8bea55b10 | ||
|
|
72cd84e878 | ||
|
|
35b6d09615 | ||
|
|
1ae727e70f | ||
|
|
0e5d0c1170 | ||
|
|
7ff62bc577 | ||
|
|
743c1c2eda | ||
|
|
0e9a08cbbf | ||
|
|
d2445ec72d | ||
|
|
fef713aaed | ||
|
|
c4d73688a6 | ||
|
|
56b721b2eb | ||
|
|
2981b37219 | ||
|
|
cfc2f84d3e | ||
|
|
d8ebebaf12 | ||
|
|
2a5691e575 | ||
|
|
774432066e | ||
|
|
e6c501de8e | ||
|
|
af3fae9c28 | ||
|
|
d5a8661480 | ||
|
|
d3b72940fd | ||
|
|
e8de3e855a | ||
|
|
71338000a4 | ||
|
|
2fdb3cfdfb | ||
|
|
8961e61f60 | ||
|
|
e5191acd73 | ||
|
|
d697969f36 | ||
|
|
51e9c5fd96 | ||
|
|
997504c03c | ||
|
|
0202351a27 | ||
|
|
dde06dfaba | ||
|
|
eb0f074097 | ||
|
|
b6c9b5645c | ||
|
|
a281b36d6f | ||
|
|
7772501cdf | ||
|
|
d1b991e198 | ||
|
|
00f793a841 | ||
|
|
bdb9598227 | ||
|
|
c6deb392fd | ||
|
|
3477ea0eeb | ||
|
|
9dacad99fa | ||
|
|
73e35c66af | ||
|
|
d3b599b727 | ||
|
|
4369151cd8 | ||
|
|
846773efd3 | ||
|
|
bcfa34357b | ||
|
|
e0c2e8ed86 | ||
|
|
b80a3876ab | ||
|
|
26e17f58ef | ||
|
|
45d1567057 | ||
|
|
8aacb3f7ec | ||
|
|
99ee81a489 | ||
|
|
517ffbd783 | ||
|
|
7dd926d4f1 | ||
|
|
cbc7942a00 | ||
|
|
63cd5ef563 | ||
|
|
3806905f5b | ||
|
|
82c254fecf | ||
|
|
2496f23e45 | ||
|
|
86bea9a9af | ||
|
|
4bb1172c84 | ||
|
|
88f26fb548 | ||
|
|
a9f1de84f0 | ||
|
|
367ff79ef1 | ||
|
|
2961c44bbe | ||
|
|
997559dc6d | ||
|
|
79d28bbc35 | ||
|
|
6bc425f981 | ||
|
|
2cdfc16829 | ||
|
|
e63d45cca9 | ||
|
|
553f186b7c | ||
|
|
623dfc0286 | ||
|
|
ffa7f35a87 | ||
|
|
081b7d4aa9 | ||
|
|
9c3c4bac66 | ||
|
|
6ec218ef11 | ||
|
|
ad2eabeb3b | ||
|
|
26c377d05b | ||
|
|
caa75d98be | ||
|
|
3ad9356ca4 | ||
|
|
dd5296f03c | ||
|
|
e673d76f22 | ||
|
|
393eb7bb4d | ||
|
|
2fa5a5b8c3 | ||
|
|
ca63b79ed8 | ||
|
|
f8b097669a | ||
|
|
2f284209d8 | ||
|
|
09881040a3 | ||
|
|
9066ad5790 | ||
|
|
62d0e670dc | ||
|
|
e7d597045b | ||
|
|
eaa3a2eae2 | ||
|
|
21d7d8988a | ||
|
|
e76386be4f | ||
|
|
b3b3ca0e16 | ||
|
|
730e86c4cd | ||
|
|
a92f1cb055 | ||
|
|
a54162e009 | ||
|
|
48864a6921 | ||
|
|
92f07cb60f | ||
|
|
e17243bc1f | ||
|
|
0e45dd7a3d | ||
|
|
65f313f1b4 | ||
|
|
da4958c716 | ||
|
|
653b8494f5 | ||
|
|
6ed6f84f6e | ||
|
|
ff0ba56bc3 | ||
|
|
e795d04f30 | ||
|
|
8d3806b080 | ||
|
|
5597ebe455 | ||
|
|
5f96de32bb | ||
|
|
d2436ce23d | ||
|
|
fbadadc377 | ||
|
|
8de3bda0b1 | ||
|
|
3c4f410a4e | ||
|
|
9c0a21a5fb | ||
|
|
94ddf7e5d8 | ||
|
|
f45dd8e94f | ||
|
|
b735dc07d6 | ||
|
|
68c902e60b | ||
|
|
e19214c3c4 | ||
|
|
4759429702 | ||
|
|
b626589c07 | ||
|
|
02704cdf74 | ||
|
|
4555d4bcbe | ||
|
|
184e58f5e5 | ||
|
|
5c7f3c1642 | ||
|
|
36331512bc | ||
|
|
3e916cfbb9 | ||
|
|
4a9ad14e11 | ||
|
|
f80816d88f | ||
|
|
817f89d586 | ||
|
|
458645101b | ||
|
|
1e306012ec | ||
|
|
db2c198feb | ||
|
|
71a901a24e | ||
|
|
f4ea34e63b | ||
|
|
0d54b88ab2 | ||
|
|
da0bd14bf3 | ||
|
|
6ce746b9ea | ||
|
|
02355696ff | ||
|
|
38254125c9 | ||
|
|
e5b3363ecf | ||
|
|
6c3eb06b65 | ||
|
|
c759e8bb8f | ||
|
|
b83f6c0b3a | ||
|
|
ade92d8ac1 | ||
|
|
08398784e4 | ||
|
|
afea881d90 | ||
|
|
194bba2118 | ||
|
|
a5967e4ecd | ||
|
|
21e22a50c5 | ||
|
|
2f361278d2 | ||
|
|
319cf76417 | ||
|
|
be7b08b50a | ||
|
|
22c01748ce | ||
|
|
02809d5016 | ||
|
|
d21f312936 | ||
|
|
357b041bb4 | ||
|
|
61999a67cd | ||
|
|
8da97a7c6f | ||
|
|
2caa69e0cb | ||
|
|
c5932569f8 | ||
|
|
1921d1a5be | ||
|
|
8745a684ae | ||
|
|
892cd962f8 | ||
|
|
3f543b881d | ||
|
|
4a1d0eb80e | ||
|
|
760ecd71fc | ||
|
|
04f1026cd8 | ||
|
|
b03c4cc62e | ||
|
|
18e9357aaf | ||
|
|
46b8260693 | ||
|
|
d5bd3190d4 | ||
|
|
e497b6d458 | ||
|
|
2e4320ee05 | ||
|
|
3406fcdce4 | ||
|
|
14a5ff6747 | ||
|
|
8dbfcd782b | ||
|
|
abf0f90a13 | ||
|
|
4d5c74c019 | ||
|
|
70ff928381 | ||
|
|
b48ab79a92 | ||
|
|
9a7fbd4f71 | ||
|
|
ef3b4956ad | ||
|
|
fd4642d827 | ||
|
|
6dd248e527 | ||
|
|
7d00c3646a | ||
|
|
e355e12385 | ||
|
|
34b31c0146 | ||
|
|
3934fa019e | ||
|
|
dc53e96f92 | ||
|
|
7fcf6f9f79 | ||
|
|
bd48ab23c3 | ||
|
|
4e28ba73bb | ||
|
|
16cb37ecd0 | ||
|
|
d4d630b2e9 | ||
|
|
2ff27cdd63 | ||
|
|
2f81167164 | ||
|
|
6897c5d41f | ||
|
|
233450d850 | ||
|
|
7428a8fa63 | ||
|
|
18359d7871 | ||
|
|
df12a58e3d | ||
|
|
4b3d124b5a | ||
|
|
51e941e7b5 | ||
|
|
62ea6f316f | ||
|
|
4cb9b3a85b | ||
|
|
806ab8ea46 | ||
|
|
582a8fe7fd | ||
|
|
08ca8b54b1 | ||
|
|
abafbef985 | ||
|
|
06863ca9c6 | ||
|
|
e49b8981dd | ||
|
|
2e91557c28 | ||
|
|
4d4eab8b1c | ||
|
|
4d4ae9374b | ||
|
|
b8e20b412c | ||
|
|
e36f3c5b10 | ||
|
|
8a55f831f4 | ||
|
|
0dcc9be5c1 | ||
|
|
5ee00a8df7 | ||
|
|
1af3d3f18b | ||
|
|
f54248c0a7 | ||
|
|
2911c0e1c4 | ||
|
|
16d35c1489 | ||
|
|
cd82a8585a | ||
|
|
6927fc80c3 | ||
|
|
89a95d6445 | ||
|
|
f9192e27fa | ||
|
|
ba5e955ccb | ||
|
|
fae3e46a59 | ||
|
|
3777074e84 | ||
|
|
5310a3cc1d | ||
|
|
1509c4ffba | ||
|
|
71ea2b582c | ||
|
|
219098c182 | ||
|
|
35b3ddd61f | ||
|
|
a892b79dba | ||
|
|
cd22a1846f | ||
|
|
eadcdab8e7 | ||
|
|
46ffd1c29a |
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -2,3 +2,4 @@
|
||||
.gitignore export-ignore
|
||||
.gitattributes export-ignore
|
||||
.commit-template export-ignore
|
||||
binary/ export-ignore
|
||||
|
||||
150
.gitignore
vendored
150
.gitignore
vendored
@@ -16,3 +16,153 @@ build*
|
||||
cscope.*
|
||||
tags
|
||||
t1.cfg
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
build/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# Roslyn cache directories
|
||||
*.ide/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
#NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Mac OS X specific
|
||||
shell_integration/MacOSX/*.xcworkspace/xcuserdata/
|
||||
**/.DS_Store
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
## TODO: Comment the next line if you want to checkin your
|
||||
## web deploy settings but do note that will include unencrypted
|
||||
## passwords
|
||||
*.pubxml
|
||||
|
||||
# NuGet Packages
|
||||
packages/*
|
||||
*.nupkg
|
||||
## TODO: If the tool you use requires repositories.config
|
||||
## uncomment the next line
|
||||
#!packages/repositories.config
|
||||
|
||||
# Enable "build/" folder in the NuGet Packages folder since
|
||||
# NuGet packages use it for MSBuild targets.
|
||||
# This line needs to be after the ignore of the build folder
|
||||
# (and the packages folder if the line above has been uncommented)
|
||||
!packages/build/
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
|
||||
# Others
|
||||
sql/
|
||||
*.Cache
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -4,3 +4,6 @@
|
||||
[submodule "src/3rdparty/qtmacgoodies"]
|
||||
path = src/3rdparty/qtmacgoodies
|
||||
url = git://github.com/shadone/qtmacgoodies.git
|
||||
[submodule "binary"]
|
||||
path = binary
|
||||
url = git://github.com/owncloud/owncloud-client-binary.git
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
cmake_policy(VERSION 2.8.0)
|
||||
|
||||
project(mirall)
|
||||
set(PACKAGE "mirall")
|
||||
set( CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules )
|
||||
@@ -108,7 +110,10 @@ if(NOT TOKEN_AUTH_ONLY)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
Find_package(Sparkle)
|
||||
if(APPLE)
|
||||
find_package(Sparkle)
|
||||
endif(APPLE)
|
||||
|
||||
if(UNIX)
|
||||
find_package(INotify REQUIRED)
|
||||
else()
|
||||
@@ -118,11 +123,22 @@ find_package(Sphinx)
|
||||
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(test/test_journal.db "${CMAKE_BINARY_DIR}/test/test_journal.db" COPYONLY)
|
||||
|
||||
# Copy that logo, the installer uses it later
|
||||
if(BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||
install(FILES resources/owncloud_logo_blue.png DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/)
|
||||
endif()
|
||||
|
||||
include(OwnCloudCPack.cmake)
|
||||
|
||||
add_definitions(-DUNICODE)
|
||||
@@ -137,7 +153,9 @@ set(TRANSLATIONS ${TRANS_FILES})
|
||||
|
||||
add_subdirectory(csync)
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(shell_integration)
|
||||
add_subdirectory(doc)
|
||||
add_subdirectory(admin)
|
||||
|
||||
if(UNIT_TESTING)
|
||||
include(CTest)
|
||||
@@ -149,4 +167,5 @@ if(BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||
configure_file(sync-exclude.lst ${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/sync-exclude.lst COPYONLY)
|
||||
else()
|
||||
install( FILES sync-exclude.lst DESTINATION ${SYSCONFDIR}/${APPLICATION_SHORTNAME} )
|
||||
configure_file(sync-exclude.lst bin/sync-exclude.lst COPYONLY)
|
||||
endif()
|
||||
|
||||
61
ChangeLog
61
ChangeLog
@@ -1,5 +1,66 @@
|
||||
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
|
||||
* 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
|
||||
* Added a socket based API to provide file management shells with status
|
||||
information about the sync status of files. That is a prerequisite for
|
||||
the overlay icons in the file managers.
|
||||
* 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
|
||||
* OS X: Sparkle update to provide pkg format properly
|
||||
* OS X: Change distribution format from dmg to pkg with new installer.
|
||||
* Win: Fix handling of filenames with trailing dot or space
|
||||
|
||||
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 )
|
||||
* Limit the HTTP buffer size when downloading to limit memory consumption.
|
||||
* Another small mem leak fixed in HTTP Credentials.
|
||||
* Fix local file name clash detection for MacOSX.
|
||||
* Limit maximum wait time to ten seconds in network limiting.
|
||||
* Fix data corruption while trying to resume and the server does
|
||||
not support it.
|
||||
* HTTP Credentials: Read password from legacy place if not found.
|
||||
* Shibboleth: Fix the waiting curser that would not disapear (#1915)
|
||||
* Limit memory usage to avoid mem wasting and crashes
|
||||
* Propagator: Fix crash when logging out during upload (#1957)
|
||||
* Propagator_qnam: Fix signal slot connection (#1963)
|
||||
* Use more elaborated way to detect that the server was reconfigured (#1948)
|
||||
* Setup Wizard: Reconfigure Server also if local path was changed (#1948)
|
||||
|
||||
version 1.6.1 (release 2014-06-26 )
|
||||
* Fix 'precondition failed' bug with broken upload
|
||||
* Fix openSSL problems for windows deployment
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
set( MIRALL_VERSION_MAJOR 1 )
|
||||
set( MIRALL_VERSION_MINOR 6 )
|
||||
set( MIRALL_VERSION_PATCH 1 )
|
||||
set( MIRALL_VERSION_MINOR 7 )
|
||||
set( MIRALL_VERSION_PATCH 0 )
|
||||
set( MIRALL_SOVERSION 0 )
|
||||
|
||||
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||
set( MIRALL_VERSION_SUFFIX "") #e.g. beta1, beta2, rc1
|
||||
set( MIRALL_VERSION_SUFFIX "rc1") #e.g. beta1, beta2, rc1
|
||||
endif( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||
|
||||
if( NOT DEFINED MIRALL_VERSION_BUILD )
|
||||
|
||||
2
admin/CMakeLists.txt
Normal file
2
admin/CMakeLists.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
# traverse into osx subdirectory to install and patch the create-pack script
|
||||
add_subdirectory(osx)
|
||||
3
admin/osx/CMakeLists.txt
Normal file
3
admin/osx/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
configure_file(create_mac_pkg.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/create_mac.sh)
|
||||
configure_file(macosx.pkgproj ${CMAKE_CURRENT_BINARY_DIR}/macosx.pkgproj)
|
||||
74
admin/osx/create_mac_pkg.sh.cmake
Executable file
74
admin/osx/create_mac_pkg.sh.cmake
Executable file
@@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script to create the Mac installer using the packages tool from
|
||||
# http://s.sudre.free.fr/Software/Packages/about.html
|
||||
#
|
||||
|
||||
[ "$#" -lt 2 ] && echo "Usage: create_mac_pkg.sh <CMAKE_INSTALL_DIR> <build dir> <installer sign identity>" && exit
|
||||
|
||||
# the path of installation must be given as parameter
|
||||
if [ -z "$1" ]; then
|
||||
echo "ERROR: Provide the path to CMAKE_INSTALL_DIR to this script as first parameter."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$2" ]; then
|
||||
echo "ERROR: Provide the path to build directory as second parameter."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
install_path="$1"
|
||||
build_path="$2"
|
||||
identity="$3"
|
||||
prjfile=$build_path/admin/osx/macosx.pkgproj
|
||||
|
||||
# The name of the installer package
|
||||
installer="@APPLICATION_NAME@-@MIRALL_VERSION_FULL@@MIRALL_VERSION_SUFFIX@"
|
||||
installer_file="$installer.pkg"
|
||||
installer_file_tar="$installer.pkg.tar"
|
||||
installer_file_tar_bz2="$installer.pkg.tar.bz2"
|
||||
installer_file_tbz="$installer.pkg.tbz"
|
||||
|
||||
# set the installer name to the copied prj config file
|
||||
/usr/local/bin/packagesutil --file $prjfile set project name "$installer"
|
||||
|
||||
# The command line tool of the "Packages" tool, see link above.
|
||||
pkgbuild=/usr/local/bin/packagesbuild
|
||||
|
||||
$pkgbuild -F $install_path $prjfile
|
||||
rc=$?
|
||||
|
||||
if [ $rc == 0 ]; then
|
||||
echo "Successfully created $installer_file"
|
||||
else
|
||||
echo "Failed to create $installer_file"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
# Sign the finished package if desired.
|
||||
if [ ! -z "$identity" ]; then
|
||||
echo "Will try to sign the installer"
|
||||
pushd $install_path
|
||||
productsign --sign "$identity" "$installer_file" "$installer_file.new"
|
||||
mv "$installer_file".new $installer_file
|
||||
popd
|
||||
else
|
||||
echo "No certificate given, will not sign the pkg"
|
||||
fi
|
||||
|
||||
# FIXME: OEMs?
|
||||
# they will need to do their own signing..
|
||||
|
||||
|
||||
# Sparkle wants a tbz, it cannot install raw pkg
|
||||
cd $install_path
|
||||
tar cf "$installer_file_tar" "$installer_file"
|
||||
bzip2 -9 "$installer_file_tar"
|
||||
mv "$installer_file_tar_bz2" "$installer_file_tbz"
|
||||
rc=$?
|
||||
if [ $rc == 0 ]; then
|
||||
echo "Successfully created $installer_file"
|
||||
else
|
||||
echo "Failed to create $installer_file"
|
||||
exit 3
|
||||
fi
|
||||
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 |
337
admin/osx/macdeployqt.py
Executable file
337
admin/osx/macdeployqt.py
Executable file
@@ -0,0 +1,337 @@
|
||||
#!/usr/bin/python
|
||||
# This file is part of ownCloud.
|
||||
# It was inspired in large part by the macdeploy script in Clementine
|
||||
# and Tomahawk
|
||||
#
|
||||
# ownCloud 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.
|
||||
#
|
||||
# ownCLoud 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.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with ownCloud. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import commands
|
||||
import sys
|
||||
from glob import glob
|
||||
|
||||
def QueryQMake(attrib):
|
||||
return subprocess.check_output([qmake_path, '-query', attrib]).rstrip('\n')
|
||||
|
||||
FRAMEWORK_SEARCH_PATH=[
|
||||
'/Library/Frameworks',
|
||||
os.path.join(os.environ['HOME'], 'Library/Frameworks')
|
||||
]
|
||||
|
||||
LIBRARY_SEARCH_PATH=['/usr/local/lib', '.']
|
||||
|
||||
QT_PLUGINS = [
|
||||
'accessible/libqtaccessiblewidgets.dylib',
|
||||
'sqldrivers/libqsqlite.dylib',
|
||||
'platforms/libqcocoa.dylib',
|
||||
'imageformats/libqgif.dylib',
|
||||
'imageformats/libqico.dylib',
|
||||
'imageformats/libqjpeg.dylib',
|
||||
'imageformats/libqsvg.dylib',
|
||||
'imageformats/libqmng.dylib',
|
||||
]
|
||||
|
||||
QT_PLUGINS_SEARCH_PATH=[
|
||||
# os.path.join(os.environ['QTDIR'], 'plugins'),
|
||||
'/usr/local/Cellar/qt/5.2.1/plugins',
|
||||
]
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class CouldNotFindQtPluginErrorFindFrameworkError(Error):
|
||||
pass
|
||||
|
||||
|
||||
class InstallNameToolError(Error):
|
||||
pass
|
||||
|
||||
|
||||
class CouldNotFindQtPluginError(Error):
|
||||
pass
|
||||
|
||||
|
||||
class CouldNotFindScriptPluginError(Error):
|
||||
pass
|
||||
|
||||
class CouldNotFindFrameworkError(Error):
|
||||
pass
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
print 'Usage: %s <bundle.app> <path-to-qmake>' % sys.argv[0]
|
||||
exit()
|
||||
|
||||
def is_exe(fpath):
|
||||
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
|
||||
|
||||
bundle_dir = sys.argv[1]
|
||||
qmake_path = sys.argv[2]
|
||||
|
||||
bundle_name = os.path.basename(bundle_dir).split('.')[0]
|
||||
|
||||
commands = []
|
||||
|
||||
binary_dir = os.path.join(bundle_dir, 'Contents', 'MacOS')
|
||||
frameworks_dir = os.path.join(bundle_dir, 'Contents', 'Frameworks')
|
||||
commands.append(['mkdir', '-p', frameworks_dir])
|
||||
resources_dir = os.path.join(bundle_dir, 'Contents', 'Resources')
|
||||
commands.append(['mkdir', '-p', resources_dir])
|
||||
plugins_dir = os.path.join(bundle_dir, 'Contents', 'PlugIns')
|
||||
binaries = [i for i in glob(os.path.join(bundle_dir, 'Contents', 'MacOS', "*")) if is_exe(i)];
|
||||
|
||||
|
||||
fixed_libraries = []
|
||||
fixed_frameworks = []
|
||||
|
||||
def WriteQtConf():
|
||||
print "Writing qt.conf..."
|
||||
with open(os.path.join(resources_dir, 'qt.conf'), 'w') as f:
|
||||
f.write("[Paths]\nPlugins = PlugIns\n");
|
||||
f.close()
|
||||
|
||||
def GetBrokenLibraries(binary):
|
||||
#print "Checking libs for binary: %s" % binary
|
||||
output = subprocess.Popen(['otool', '-L', binary], stdout=subprocess.PIPE).communicate()[0]
|
||||
broken_libs = {
|
||||
'frameworks': [],
|
||||
'libs': []}
|
||||
for line in [x.split(' ')[0].lstrip() for x in output.split('\n')[1:]]:
|
||||
#print "Checking line: %s" % line
|
||||
if not line: # skip empty lines
|
||||
continue
|
||||
if os.path.basename(binary) == os.path.basename(line):
|
||||
#print "mnope %s-%s" % (os.path.basename(binary), os.path.basename(line))
|
||||
continue
|
||||
if re.match(r'^\s*/System/', line):
|
||||
continue # System framework
|
||||
elif re.match(r'^\s*/usr/lib/', line):
|
||||
#print "unix style system lib"
|
||||
continue # unix style system library
|
||||
elif re.match(r'Breakpad', line):
|
||||
continue # Manually added by cmake.
|
||||
elif re.match(r'^\s*@executable_path', line) or re.match(r'^\s*@loader_path', line):
|
||||
# Potentially already fixed library
|
||||
if '.framework' in line:
|
||||
relative_path = os.path.join(*line.split('/')[3:])
|
||||
if not os.path.exists(os.path.join(frameworks_dir, relative_path)):
|
||||
broken_libs['frameworks'].append(relative_path)
|
||||
else:
|
||||
relative_path = os.path.join(*line.split('/')[1:])
|
||||
#print "RELPATH %s %s" % (relative_path, os.path.join(binary_dir, relative_path))
|
||||
if not os.path.exists(os.path.join(binary_dir, relative_path)):
|
||||
broken_libs['libs'].append(relative_path)
|
||||
elif re.search(r'\w+\.framework', line):
|
||||
broken_libs['frameworks'].append(line)
|
||||
else:
|
||||
broken_libs['libs'].append(line)
|
||||
|
||||
return broken_libs
|
||||
|
||||
def FindFramework(path):
|
||||
search_pathes = FRAMEWORK_SEARCH_PATH
|
||||
search_pathes.insert(0, QueryQMake('QT_INSTALL_LIBS'))
|
||||
for search_path in search_pathes:
|
||||
abs_path = os.path.join(search_path, path)
|
||||
if os.path.exists(abs_path):
|
||||
return abs_path
|
||||
|
||||
raise CouldNotFindFrameworkError(path)
|
||||
|
||||
def FindLibrary(path):
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
search_pathes = LIBRARY_SEARCH_PATH
|
||||
search_pathes.insert(0, QueryQMake('QT_INSTALL_LIBS'))
|
||||
for search_path in search_pathes:
|
||||
abs_path = os.path.join(search_path, path)
|
||||
if os.path.exists(abs_path):
|
||||
return abs_path
|
||||
else: # try harder---look for lib name in library folders
|
||||
newpath = os.path.join(search_path,os.path.basename(path))
|
||||
if os.path.exists(newpath):
|
||||
return newpath
|
||||
|
||||
return ""
|
||||
#raise CouldNotFindFrameworkError(path)
|
||||
|
||||
def FixAllLibraries(broken_libs):
|
||||
for framework in broken_libs['frameworks']:
|
||||
FixFramework(framework)
|
||||
for lib in broken_libs['libs']:
|
||||
FixLibrary(lib)
|
||||
|
||||
def FixFramework(path):
|
||||
if path in fixed_libraries:
|
||||
return
|
||||
else:
|
||||
fixed_libraries.append(path)
|
||||
abs_path = FindFramework(path)
|
||||
broken_libs = GetBrokenLibraries(abs_path)
|
||||
FixAllLibraries(broken_libs)
|
||||
|
||||
new_path = CopyFramework(abs_path)
|
||||
id = os.sep.join(new_path.split(os.sep)[3:])
|
||||
FixFrameworkId(new_path, id)
|
||||
for framework in broken_libs['frameworks']:
|
||||
FixFrameworkInstallPath(framework, new_path)
|
||||
for library in broken_libs['libs']:
|
||||
FixLibraryInstallPath(library, new_path)
|
||||
|
||||
def FixLibrary(path):
|
||||
if path in fixed_libraries or FindSystemLibrary(os.path.basename(path)) is not None:
|
||||
return
|
||||
else:
|
||||
fixed_libraries.append(path)
|
||||
abs_path = FindLibrary(path)
|
||||
if abs_path == "":
|
||||
print "Could not resolve %s, not fixing!" % path
|
||||
return
|
||||
broken_libs = GetBrokenLibraries(abs_path)
|
||||
FixAllLibraries(broken_libs)
|
||||
|
||||
new_path = CopyLibrary(abs_path)
|
||||
FixLibraryId(new_path)
|
||||
for framework in broken_libs['frameworks']:
|
||||
FixFrameworkInstallPath(framework, new_path)
|
||||
for library in broken_libs['libs']:
|
||||
FixLibraryInstallPath(library, new_path)
|
||||
|
||||
def FixPlugin(abs_path, subdir):
|
||||
broken_libs = GetBrokenLibraries(abs_path)
|
||||
FixAllLibraries(broken_libs)
|
||||
|
||||
new_path = CopyPlugin(abs_path, subdir)
|
||||
for framework in broken_libs['frameworks']:
|
||||
FixFrameworkInstallPath(framework, new_path)
|
||||
for library in broken_libs['libs']:
|
||||
FixLibraryInstallPath(library, new_path)
|
||||
|
||||
def FixBinary(path):
|
||||
broken_libs = GetBrokenLibraries(path)
|
||||
FixAllLibraries(broken_libs)
|
||||
for framework in broken_libs['frameworks']:
|
||||
FixFrameworkInstallPath(framework, path)
|
||||
for library in broken_libs['libs']:
|
||||
FixLibraryInstallPath(library, path)
|
||||
|
||||
def CopyLibrary(path):
|
||||
new_path = os.path.join(binary_dir, os.path.basename(path))
|
||||
args = ['ditto', '--arch=x86_64', path, new_path]
|
||||
commands.append(args)
|
||||
args = ['chmod', 'u+w', new_path]
|
||||
commands.append(args)
|
||||
return new_path
|
||||
|
||||
def CopyPlugin(path, subdir):
|
||||
new_path = os.path.join(plugins_dir, subdir, os.path.basename(path))
|
||||
args = ['mkdir', '-p', os.path.dirname(new_path)]
|
||||
commands.append(args)
|
||||
args = ['ditto', '--arch=x86_64', path, new_path]
|
||||
commands.append(args)
|
||||
args = ['chmod', 'u+w', new_path]
|
||||
commands.append(args)
|
||||
return new_path
|
||||
|
||||
def CopyFramework(path):
|
||||
parts = path.split(os.sep)
|
||||
print "CopyFramework:", path
|
||||
for i, part in enumerate(parts):
|
||||
matchObj = re.match(r'(\w+\.framework)', part)
|
||||
if matchObj:
|
||||
full_path = os.path.join(frameworks_dir, *parts[i:-1])
|
||||
framework = matchObj.group(1)
|
||||
break
|
||||
args = ['mkdir', '-p', full_path]
|
||||
commands.append(args)
|
||||
args = ['ditto', '--arch=x86_64', path, full_path]
|
||||
commands.append(args)
|
||||
args = ['chmod', 'u+w', os.path.join(full_path, parts[-1])]
|
||||
commands.append(args)
|
||||
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')
|
||||
if os.path.exists(info_plist):
|
||||
args = ['cp', '-r', info_plist, os.path.join(frameworks_dir, framework, "Resources")]
|
||||
commands.append(args)
|
||||
return os.path.join(full_path, parts[-1])
|
||||
|
||||
def FixId(path, library_name):
|
||||
id = '@executable_path/../Frameworks/%s' % library_name
|
||||
args = ['install_name_tool', '-id', id, path]
|
||||
commands.append(args)
|
||||
|
||||
def FixLibraryId(path):
|
||||
library_name = os.path.basename(path)
|
||||
FixId(path, library_name)
|
||||
|
||||
def FixFrameworkId(path, id):
|
||||
FixId(path, id)
|
||||
|
||||
def FixInstallPath(library_path, library, new_path):
|
||||
args = ['install_name_tool', '-change', library_path, new_path, library]
|
||||
commands.append(args)
|
||||
|
||||
def FindSystemLibrary(library_name):
|
||||
for path in ['/lib', '/usr/lib']:
|
||||
full_path = os.path.join(path, library_name)
|
||||
if os.path.exists(full_path):
|
||||
return full_path
|
||||
return None
|
||||
|
||||
def FixLibraryInstallPath(library_path, library):
|
||||
system_library = FindSystemLibrary(os.path.basename(library_path))
|
||||
if system_library is None:
|
||||
new_path = '@executable_path/../MacOS/%s' % os.path.basename(library_path)
|
||||
FixInstallPath(library_path, library, new_path)
|
||||
else:
|
||||
FixInstallPath(library_path, library, system_library)
|
||||
|
||||
def FixFrameworkInstallPath(library_path, library):
|
||||
parts = library_path.split(os.sep)
|
||||
for i, part in enumerate(parts):
|
||||
if re.match(r'\w+\.framework', part):
|
||||
full_path = os.path.join(*parts[i:])
|
||||
break
|
||||
new_path = '@executable_path/../Frameworks/%s' % full_path
|
||||
FixInstallPath(library_path, library, new_path)
|
||||
|
||||
def FindQtPlugin(name):
|
||||
search_path = QT_PLUGINS_SEARCH_PATH
|
||||
search_path.insert(0, QueryQMake('QT_INSTALL_PLUGINS'))
|
||||
for path in search_path:
|
||||
if os.path.exists(path):
|
||||
if os.path.exists(os.path.join(path, name)):
|
||||
return os.path.join(path, name)
|
||||
raise CouldNotFindQtPluginError(name)
|
||||
|
||||
for binary in binaries:
|
||||
FixBinary(binary)
|
||||
|
||||
for plugin in QT_PLUGINS:
|
||||
FixPlugin(FindQtPlugin(plugin), os.path.dirname(plugin))
|
||||
|
||||
if len(sys.argv) <= 2:
|
||||
print 'Will run %d commands:' % len(commands)
|
||||
for command in commands:
|
||||
print ' '.join(command)
|
||||
|
||||
for command in commands:
|
||||
p = subprocess.Popen(command)
|
||||
os.waitpid(p.pid, 0)
|
||||
|
||||
WriteQtConf()
|
||||
1426
admin/osx/macosx.pkgproj
Normal file
1426
admin/osx/macosx.pkgproj
Normal file
File diff suppressed because it is too large
Load Diff
32
admin/osx/sign_app.sh
Executable file
32
admin/osx/sign_app.sh
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/bin/sh -x
|
||||
|
||||
[ "$#" -lt 2 ] && echo "Usage: sign_app.sh <app> <identity>" && exit
|
||||
|
||||
src_app="$1"
|
||||
identity="$2"
|
||||
|
||||
QT_FMWK_VERSION="5"
|
||||
|
||||
fix_frameworks() {
|
||||
TMP_APP=$1
|
||||
QT_FMWK_PATH=$2
|
||||
QT_FMWKS=$3/Qt*.framework
|
||||
|
||||
echo "Patching Qt frameworks..."
|
||||
for FMWK in $QT_FMWKS; do
|
||||
FMWK_NAME=`basename -s .framework $FMWK`
|
||||
FMWK=`basename $FMWK`
|
||||
FMWK_PATH="${TMP_APP}/Contents/Frameworks/${FMWK}"
|
||||
mkdir -p "${FMWK_PATH}/Versions/${QT_FMWK_VERSION}/Resources/"
|
||||
cp -avf "${QT_FMWK_PATH}/${FMWK}/Contents/Info.plist" "${FMWK_PATH}/Versions/${QT_FMWK_VERSION}/Resources"
|
||||
(cd "${FMWK_PATH}" && ln -sf "Versions/${QT_FMWK_VERSION}/Resources" "Resources")
|
||||
perl -pi -e "s/${FMWK_NAME}_debug/${FMWK_NAME}/" "${FMWK_PATH}/Resources/Info.plist"
|
||||
done
|
||||
}
|
||||
|
||||
fix_frameworks "$src_app" `qmake -query QT_INSTALL_LIBS` "$src_app"/Contents/Frameworks
|
||||
codesign -s "$identity" --force --verbose=4 --deep "$src_app"
|
||||
|
||||
# Just for our debug purposes:
|
||||
spctl -a -t exec -vv $src_app
|
||||
codesign -dv $src_app
|
||||
19
admin/win/download_runtimes.sh
Executable file
19
admin/win/download_runtimes.sh
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/bin/sh -x
|
||||
|
||||
#VS2013
|
||||
base_url=http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3
|
||||
tmp_path=/tmp/.vcredist
|
||||
|
||||
mkdir -p $tmp_path
|
||||
|
||||
copy_cached_file() {
|
||||
file=$1
|
||||
if [ ! -e $tmp_path/$file ]; then
|
||||
wget -O $tmp_path/$file $base_url/$file
|
||||
fi
|
||||
cp -a $tmp_path/$file $PWD
|
||||
}
|
||||
|
||||
copy_cached_file "vcredist_x64.exe"
|
||||
copy_cached_file "vcredist_x86.exe"
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
# Auto-generated - do not modify
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Erakutsi bertsio-berritze oharrak"
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "kill prozesua ez da aurkitu!"
|
||||
StrCpy $PageReinstall_NEW_Field_2 "Desinstalatu instalatu baino lehen"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "Ez desinstalatu"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Dagoeneko Instalatuta"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Hautatu nola nahi duzun ${APPLICATION_NAME} instalatzea."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} dagoeneko instalatuta dago.\nHautatu zer operazio egin nahi duzu eta klikatu Hurrengoa jarraitzeko."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Gehitu/Berrinstalatu osagaiak"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Desinstalatu ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalatu ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Hautatu zer mantenu aukera egin nahi duzun."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Hasierako Menuko Lasterbidea"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Hasierako Menuan ${APPLICATION_NAME}rako Abiarazle bizkorra sortzen."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Mahaigaineko Lasterbidea"
|
||||
@@ -29,14 +32,13 @@ StrCpy $INIT_INSTALLER_RUNNING "Instalatzailea dagoeneko martxan da."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Desinstalatzaile honek administratzaile baimenak behar ditu, saiatu berriro"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Desinstalatzailea dagoeneko martxan da."
|
||||
StrCpy $SectionGroup_Shortcuts "Lasterbideak"
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Show release notes"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Found ${APPLICATION_EXECUTABLE} process(s) which need to be stopped.$\nDo you want the installer to stop these for you?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Killing ${APPLICATION_EXECUTABLE} processes."
|
||||
StrCpy $PageReinstall_NEW_Field_1 "An older version of ${APPLICATION_NAME} is installed on your system. It is recommended that you uninstall the current version before installing. Select the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "A newer version of ${APPLICATION_NAME} is already installed! It is not recommended that you install an older version. If you really want to install this older version, it is better to uninstall the current version first. Select the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.\r\nSelect the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Choose the maintenance option to perform."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Installing ${APPLICATION_NAME} essentials."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status icons for Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing status icons for Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} essentials."
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Leave unchecked to keep the data folder for later use or check to delete the data folder."
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "It does not appear that ${APPLICATION_NAME} is installed in the directory '$INSTDIR'.$\r$\nContinue anyway (not recommended)?"
|
||||
|
||||
@@ -1,44 +1,46 @@
|
||||
# Auto-generated - do not modify
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Mostrar les notes de versió"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "S'ha trobat el(s) procés ${APPLICATION_EXECUTABLE} que s'ha d'aturar.$\nVoleu que l'instal·lador l'aturi?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "S'estan matant els processos ${APPLICATION_EXECUTABLE}."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Procés per matar no trobat!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Una versió anterior de ${APPLICATION_NAME} està instal·lada en el vostre sistema. Es recomana desinstal·lar la versió actual abans d'instal·lar. Seleccioneu l'operació que desitjeu realitzar i feu clic a Següent per continuar."
|
||||
StrCpy $PageReinstall_NEW_Field_2 "Desinstal·lar abans d'instal·lar"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "No instal·lar"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Ja instal·lat"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Trieu la manera com voleu instal·lar ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Una versió més recent de ${APPLICATION_NAME} ja està instal.lada!! No es recomana instal.lar una versió més antiga. Si realment voleu instal.lar una versió més antiga, és millor primer desinstal.lar la versió actual. Seleccioni l'operació que desitjeu realitzar i feu clic a Següent per a continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} ja està instal.lat.↩\nSeleccioneu l'operació que desitjeu realitzar i feu clic a Següent per continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Afegir/Reinstal.lar components"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Desinstal.lar ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstal.lar ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Escolliu l'opció de manteniment per executar-ho."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Instal·lant ${APPLICATION_NAME} essencial."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Accés directe del programa al menú d'inici"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Afegint la drecera per ${APPLICATION_NAME} al menú d'inici."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Drecera a l'escriptori"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Creant les dreceres a l'escriptori"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Drecera d'inici ràpid"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Creant la drecera per l'inici ràpid"
|
||||
StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} essencial."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Drecera ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Drecera a l'escrptori per ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Drecera d'inici ràpid per ${APPLICATION_NAME}."
|
||||
StrCpy $UNINSTALLER_APPDATA_SUBTITLE "Esborra la carpeta de dades de ${APPLICATION_NAME} del vostre equip."
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_1 "Voleu esborrar la carpeta de dades de ${APPLICATION_NAME}?"
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Deixeu-ho sense marcar per mantenir la carpeta de dades per un ús posterior o marqueu-ho per esborrar la carpeta de dades."
|
||||
StrCpy $UNINSTALLER_APPDATA_CHECKBOX "Sí, esborra la carpeta de dades."
|
||||
StrCpy $UNINSTALLER_FILE_Detail "Escrivint el desinstal·lador"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Escrivint les claus del registre de l'instal·lador"
|
||||
StrCpy $UNINSTALLER_FINISHED_Detail "Acabat"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "No sembla que ${APPLICATION_NAME} estigui instal·lat en la carpeta '$INSTDIR'.$\n$\nContinuo igualment (no recomanat)?"
|
||||
StrCpy $UNINSTALL_ABORT "La desinstal·lació s'ha cancel·lat."
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Drecera d'inici ràpid (N/A)"
|
||||
StrCpy $INIT_NO_DESKTOP "Drecera de l'escrpitori (sobreescriu l'existent)"
|
||||
StrCpy $UAC_ERROR_ELEVATE "No es pot elevar, error:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Aquest instal·lador requereix accés d'administrador, intenteu-ho de nou"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "L'instal·lador ja s'està executant."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Aquest desinstal·lador requereix accés d'administrador, intenteu-ho de nou."
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "El desinstal·lador ja s'està executant."
|
||||
StrCpy $SectionGroup_Shortcuts "Dreceres"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Found ${APPLICATION_EXECUTABLE} process(s) which need to be stopped.$\nDo you want the installer to stop these for you?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Killing ${APPLICATION_EXECUTABLE} processes."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "A newer version of ${APPLICATION_NAME} is already installed! It is not recommended that you install an older version. If you really want to install this older version, it is better to uninstall the current version first. Select the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.\r\nSelect the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Add/Reinstall components"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Uninstall ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Uninstall ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Choose the maintenance option to perform."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Installing ${APPLICATION_NAME} essentials."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Start Menu Program Shortcut"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Adding shortcut for ${APPLICATION_NAME} to the Start Menu."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Desktop Shortcut"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Creating Desktop Shortcuts"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Quick Launch Shortcut"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Creating Quick Launch Shortcut"
|
||||
StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} essentials."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME} shortcut."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Desktop shortcut for ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Quick Launch shortcut for ${APPLICATION_NAME}."
|
||||
StrCpy $UNINSTALLER_APPDATA_SUBTITLE "Remove ${APPLICATION_NAME}'s data folder from your computer."
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_1 "Do you want to delete ${APPLICATION_NAME}'s data folder?"
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Leave unchecked to keep the data folder for later use or check to delete the data folder."
|
||||
StrCpy $UNINSTALLER_APPDATA_CHECKBOX "Yes, delete this data folder."
|
||||
StrCpy $UNINSTALLER_FILE_Detail "Writing Uninstaller"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Writing Installer Registry Keys"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "It does not appear that ${APPLICATION_NAME} is installed in the directory '$INSTDIR'.$\r$\nContinue anyway (not recommended)?"
|
||||
StrCpy $UNINSTALL_ABORT "Uninstall aborted by user"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Quick Launch Shortcut (N/A)"
|
||||
StrCpy $INIT_NO_DESKTOP "Desktop Shortcut (overwrites existing)"
|
||||
StrCpy $UAC_ERROR_ELEVATE "Unable to elevate, error:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "This installer requires admin access, try again"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "The installer is already running."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "This uninstaller requires admin access, try again"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "The uninstaller is already running."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status icons for Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing status icons for Windows Explorer"
|
||||
|
||||
@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Odinstalovat ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Odinstalovat ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Vyberte možnost údržby k provedení."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Instalují se náležitosti ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Stavová ikona pro Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instaluji stavovou ikonu pro Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Zástupce v Nabídce Start"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Přidávám zástupce pro ${APPLICATION_NAME} do Nabídky Start."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Zástupce na ploše"
|
||||
|
||||
@@ -6,7 +6,7 @@ StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Het te stoppen proces is niet gev
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Er is een oudere versie van ${APPLICATION_NAME} geïnstalleerd op uw systeem. geadviseerd wordt om de huidige versie te de-installeren voordat de nieuwe versie wordt geïnstalleerd. Selecteer de uit te voeren actie en klik op Verder om door te gaan."
|
||||
StrCpy $PageReinstall_NEW_Field_2 "De-installeren voor installeren"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "Niet de-installeren"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Reeds geinstalleerd"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Al geïnstalleerd"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Kies hoe u ${APPLICATION_NAME} wilt installeren."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Er is al een recentere versie van ${APPLICATION_NAME} geïnstalleerd! Installeren van een oudere versie wordt niet aangeraden. Als u echt de oudere versie wilt installeren, adviseren we de huidige versie eerst te verwijderen. Kies de actie die u wilt uitvoeren en druk op Verder om door te gaan."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is al geïnstalleerd.\nKies de actie die u wilt uitvoeren en druk op Verder om door te gaan."
|
||||
@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "De-installeer ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "De-installeer ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Kies de uit te voeren onderhoudsoptie."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Installeren ${APPLICATION_NAME} basis."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Statuspictogrammen voor Windows Verkenner"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installeren statuspictogrammen voor Windows Verkenner"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Startmenu snelkoppeling"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Toevoegen snelkoppeling voor ${APPLICATION_NAME} aan het Startmenu."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Werkblad snelkoppeling"
|
||||
@@ -27,7 +29,7 @@ StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Werkblad snelkoppeling voor ${APPLICATIO
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Snelstart snelkoppeling voor ${APPLICATION_NAME}."
|
||||
StrCpy $UNINSTALLER_APPDATA_SUBTITLE "Verwijder ${APPLICATION_NAME}'s data map van uw computer."
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_1 "Wilt u de ${APPLICATION_NAME}'s data map verwijderen?"
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Niet aankruisen om de datamap te bewaren of aankruisen om de datamap te verwijderen."
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Niet aankruisen om de datamap te bewaren, wel aankruisen om de datamap te verwijderen."
|
||||
StrCpy $UNINSTALLER_APPDATA_CHECKBOX "Ja, verwijder deze data map."
|
||||
StrCpy $UNINSTALLER_FILE_Detail "Wegschrijven Uninstaller"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Wegschrijven installer Registersleutels"
|
||||
@@ -35,10 +37,10 @@ StrCpy $UNINSTALLER_FINISHED_Detail "Klaar"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Het lijkt er niet op dat ${APPLICATION_NAME} is geïnstalleerd in de map '$INSTDIR'.$\n$\nToch doorgaan (niet aangeraden)?"
|
||||
StrCpy $UNINSTALL_ABORT "De-installatie afgebroken door de gebruiker"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Snelstart snelkoppeling (N/A)"
|
||||
StrCpy $INIT_NO_DESKTOP "Desktop snelkoppeleng (overschrijft huidige)"
|
||||
StrCpy $INIT_NO_DESKTOP "Bureaublad snelkoppeling (overschrijft huidige)"
|
||||
StrCpy $UAC_ERROR_ELEVATE "Kan niet verhogen, fout:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Dit installatieprogramma vereist administrator rechten. Probeer het opnieuw"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Dit installatieprogramma vereist beheerdersrechten. Probeer het opnieuw"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "De Installer is al gestart."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Deze uninstaller vereist administrator toegang, probeer opnieuw"
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Deze uninstaller vereist Beheerderstoegang, probeer opnieuw"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "De uninstaller is al gestart."
|
||||
StrCpy $SectionGroup_Shortcuts "Snelkoppelingen"
|
||||
|
||||
@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Uninstall ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Uninstall ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Choose the maintenance option to perform."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Installing ${APPLICATION_NAME} essentials."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status icons for Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing status icons for Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Start Menu Program Shortcut"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Adding shortcut for ${APPLICATION_NAME} to the Start Menu."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Desktop Shortcut"
|
||||
|
||||
@@ -42,3 +42,5 @@ StrCpy $INIT_INSTALLER_RUNNING "Paigaldaja on juba k
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "See desinstallija vajab admini ligipääsu, proovi uuesti"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "See desinstallija on juba käimas"
|
||||
StrCpy $SectionGroup_Shortcuts "Viidad"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status icons for Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing status icons for Windows Explorer"
|
||||
|
||||
46
admin/win/nsi/l10n/Farsi.nsh
Normal file
46
admin/win/nsi/l10n/Farsi.nsh
Normal file
@@ -0,0 +1,46 @@
|
||||
# Auto-generated - do not modify
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "نمایش پادداشت های انتشار نسخه"
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "پردازش برای از بین بردن یافت نشد!"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "حذف نکن"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "از قبل نصب شده است"
|
||||
StrCpy $PageReinstall_SAME_Field_2 "افزودن/نصب مجدد اجزا"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "میانبر دسکتاپ"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "ایجاد میانبر دسکتاپ"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "میانبر بازکردن سریع"
|
||||
StrCpy $UNINSTALLER_APPDATA_CHECKBOX "بله، این پوشه داده را حذف کن."
|
||||
StrCpy $UNINSTALLER_FILE_Detail "نوشتن حذف کننده"
|
||||
StrCpy $UNINSTALLER_FINISHED_Detail "اتمام"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "نصاب از قبل در حال اجراست."
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "حذف کننده از قبل در حال اجراست."
|
||||
StrCpy $SectionGroup_Shortcuts "میانبرها"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Found ${APPLICATION_EXECUTABLE} process(s) which need to be stopped.$\nDo you want the installer to stop these for you?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Killing ${APPLICATION_EXECUTABLE} processes."
|
||||
StrCpy $PageReinstall_NEW_Field_1 "An older version of ${APPLICATION_NAME} is installed on your system. It is recommended that you uninstall the current version before installing. Select the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_NEW_Field_2 "Uninstall before installing"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Choose how you want to install ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "A newer version of ${APPLICATION_NAME} is already installed! It is not recommended that you install an older version. If you really want to install this older version, it is better to uninstall the current version first. Select the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.\r\nSelect the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Uninstall ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Uninstall ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Choose the maintenance option to perform."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Installing ${APPLICATION_NAME} essentials."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status icons for Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing status icons for Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Start Menu Program Shortcut"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Adding shortcut for ${APPLICATION_NAME} to the Start Menu."
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Creating Quick Launch Shortcut"
|
||||
StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} essentials."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME} shortcut."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Desktop shortcut for ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Quick Launch shortcut for ${APPLICATION_NAME}."
|
||||
StrCpy $UNINSTALLER_APPDATA_SUBTITLE "Remove ${APPLICATION_NAME}'s data folder from your computer."
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_1 "Do you want to delete ${APPLICATION_NAME}'s data folder?"
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Leave unchecked to keep the data folder for later use or check to delete the data folder."
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Writing Installer Registry Keys"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "It does not appear that ${APPLICATION_NAME} is installed in the directory '$INSTDIR'.$\r$\nContinue anyway (not recommended)?"
|
||||
StrCpy $UNINSTALL_ABORT "Uninstall aborted by user"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Quick Launch Shortcut (N/A)"
|
||||
StrCpy $INIT_NO_DESKTOP "Desktop Shortcut (overwrites existing)"
|
||||
StrCpy $UAC_ERROR_ELEVATE "Unable to elevate, error:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "This installer requires admin access, try again"
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "This uninstaller requires admin access, try again"
|
||||
@@ -1,28 +1,39 @@
|
||||
# Auto-generated - do not modify
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Näytä julkaisutiedot"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Havaittiin sovelluksen ${APPLICATION_EXECUTABLE} prosessi (tai prosesseja) jotka pitäisi pysäyttää.\nHaluatko että asennusohjelma pysäyttää nämä puolestasi?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Pysäytetään sovelluksen ${APPLICATION_EXECUTABLE} prosessit."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Tapettavaa prosessia ei löytynyt!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Vanhempi versio sovelluksesta ${APPLICATION_NAME} on jo asennettu. On suositeltavaa että poistat vanhan asennuksen ensin. Valitse mikä toiminto suoritetaan ja napsauta Seuraava jatkaaksesi."
|
||||
StrCpy $PageReinstall_NEW_Field_2 "Poista ennen asentamista"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "Älä poista"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Asennettu jo"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Valitse miten ${APPLICATION_NAME} asennetaan."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Uudempi versio sovelluksesta ${APPLICATION_NAME} on jo asennettu! Vanhan version asennus ei ole suositeltavaa. Jos todella haluat asentaa vanhemman version, kannattaa poistaa nykyisen version asennus ensin. Valitse minkä toimenpiteen haluat suorittaa ja paina Seuraava jatkaaksesi."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} on jo asennettu.\nValitse suoritettava toimenpide ja napsauta Seuraava jatkaaksesi."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Lisää/uudelleenasenna komponentteja"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Poista ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Poista ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Valitse suoritettava huoltotoimenpide."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Asennetaan sovelluksen ${APPLICATION_NAME} välttämättömyyksiä."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Tilakuvakkeet Windows Explorerille"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Asennetaan tilakuvakkeet Windows Explorerille"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Käynnistä-valikon pikakuvake"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Lisätään ${APPLICATION_NAME}-pikakuvake Käynnistä-valikkoon."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Työpöydän pikakuvake"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Luodaan työpöydän pikakuvakkeet"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Pikakäynnistyksen pikakuvake"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Luodaan pikakuvaketta pikakäynnistykseen"
|
||||
StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} välttämättömyydet."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME}-pikakuvake."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Sovelluksen ${APPLICATION_NAME} työpyötäpikakuvake."
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Pikakäynnistyksen pikakuvake sovellukselle ${APPLICATION_NAME}."
|
||||
StrCpy $UNINSTALLER_APPDATA_SUBTITLE "Poista ${APPLICATION_NAME}-datakansio tietokoneelta."
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_1 "Haluatko varmasti poistaa ${APPLICATION_NAME}-datakansion?"
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Jätä valinta ruksimatta säilyttääksesti datakansion myöhempää käyttöä varten tai täytä ruksi jos haluat poistaa datakansion ja siinä olevat tiedostot."
|
||||
StrCpy $UNINSTALLER_APPDATA_CHECKBOX "Kyllä, poista tämä datakansio."
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Kirjoitetaan asennusohjelman rekisteriavaimia"
|
||||
StrCpy $UNINSTALLER_FINISHED_Detail "Valmis"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Vaikuttaa siltä että sovellus ${APPLICATION_NAME} on asennettu kansioon '$INSTDIR'.\n\nHaluatko jatkaa tästä huolimatta (ei suositeltavaa)?"
|
||||
StrCpy $UNINSTALL_ABORT "Poistaminen keskeytettiin käyttäjän toimesta"
|
||||
StrCpy $INIT_NO_DESKTOP "Työpöydän pikakuvake (korvaa nykyinen)"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Tämä asennusohjelma vaatii ylläpitäjän oikeudet, yritä uudelleen."
|
||||
@@ -30,15 +41,6 @@ StrCpy $INIT_INSTALLER_RUNNING "Asennusohjelma on jo k
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Tämä poisto-ohjelma vaatii ylläpitäjän oikeudet, yritä uudelleen."
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Poisto-ohjelma on jo käynnissä."
|
||||
StrCpy $SectionGroup_Shortcuts "Pikakuvakkeet"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Found ${APPLICATION_EXECUTABLE} process(s) which need to be stopped.$\nDo you want the installer to stop these for you?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Killing ${APPLICATION_EXECUTABLE} processes."
|
||||
StrCpy $PageReinstall_NEW_Field_1 "An older version of ${APPLICATION_NAME} is installed on your system. It is recommended that you uninstall the current version before installing. Select the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "A newer version of ${APPLICATION_NAME} is already installed! It is not recommended that you install an older version. If you really want to install this older version, it is better to uninstall the current version first. Select the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Add/Reinstall components"
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Installing ${APPLICATION_NAME} essentials."
|
||||
StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} essentials."
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Leave unchecked to keep the data folder for later use or check to delete the data folder."
|
||||
StrCpy $UNINSTALLER_FILE_Detail "Writing Uninstaller"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "It does not appear that ${APPLICATION_NAME} is installed in the directory '$INSTDIR'.$\r$\nContinue anyway (not recommended)?"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Quick Launch Shortcut (N/A)"
|
||||
StrCpy $UAC_ERROR_ELEVATE "Unable to elevate, error:"
|
||||
|
||||
@@ -42,3 +42,5 @@ StrCpy $INIT_INSTALLER_RUNNING "Une installation est déjà en cours."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Ce désinstallateur requiert les droits administrateur, essayez à nouveau"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Une désinstallation est déjà en cours."
|
||||
StrCpy $SectionGroup_Shortcuts "Raccourcis"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status icons for Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing status icons for Windows Explorer"
|
||||
|
||||
@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Desinstalar ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalar ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Escolla a opción de mantemento a realizar."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Instalando ${APPLICATION_NAME} esenciais."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Iconas de estado para Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instalando as iconas de estado para Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Acceso directo ao programa no menú de inicio"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Engadindo o acceso directo ao ${APPLICATION_NAME} no menú de inicio"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Acceso directo no escritorio"
|
||||
|
||||
@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "${APPLICATION_NAME} entfernen"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "${APPLICATION_NAME} entfernen"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Wählen Sie zur Ausführung die Wartungsoption."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Installiere ${APPLICATION_NAME} Basis."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status-Icons für den Windows-Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installiere Status-Icons für den Windows-Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Installiere Verknüpfung im Programmmenü"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Füge Verknüpfung für ${APPLICATION_NAME} dem Startmenü hinzu."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Desktop-Verknüpfung"
|
||||
|
||||
@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Απεγκατάσταση ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Επιλέξτε την επιλογή συντήρησης που θα πραγματοποιηθεί."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Εγκατάσταση βάσης ${APPLICATION_NAME} σε εξέλιξη."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Εικονίδια κατάστασης για την Εξερεύνηση των Windows"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Εγκατάσταση εικονιδίων κατάστασης στην Εξερεύνηση των Windows"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Συντόμευση στο Αρχικό Μενού"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Προσθήκη συντόμευσης για την ${APPLICATION_NAME} στο Αρχικό Μενού."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Συντόμευση επιφάνειας εργασίας"
|
||||
|
||||
@@ -9,6 +9,13 @@ StrCpy $PageReinstall_SAME_Field_3 "${APPLICATION_NAME} eltávolítása"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "${APPLICATION_NAME} eltávolítása"
|
||||
StrCpy $UNINSTALLER_APPDATA_CHECKBOX "Igen, törölje ezt az adatkönyvtárat."
|
||||
StrCpy $UNINSTALLER_FINISHED_Detail "Befejezve"
|
||||
StrCpy $UNINSTALL_ABORT "Az eltávolítást egy felhasználó megszakította"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Gyorsindító Hivatkozás (N/A)"
|
||||
StrCpy $INIT_NO_DESKTOP "Asztali Hivatkozás (felülírja a meglévőt)"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "A telepítő futtatásához adminisztrátori hozzáférés szükséges, próbáld újra."
|
||||
StrCpy $INIT_INSTALLER_RUNNING "A telepítő már fut."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Az eltávolító futtatásához adminisztrátori hozzáférés szükséges, próbáld újra."
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Az eltávolító már fut."
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Found ${APPLICATION_EXECUTABLE} process(s) which need to be stopped.$\nDo you want the installer to stop these for you?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Killing ${APPLICATION_EXECUTABLE} processes."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Process to kill not found!"
|
||||
@@ -17,6 +24,8 @@ StrCpy $PageReinstall_OLD_Field_1 "A newer version of ${APPLICATION_NAME} is alr
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.\r\nSelect the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Choose the maintenance option to perform."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Installing ${APPLICATION_NAME} essentials."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status icons for Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing status icons for Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Start Menu Program Shortcut"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Adding shortcut for ${APPLICATION_NAME} to the Start Menu."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Desktop Shortcut"
|
||||
@@ -33,12 +42,5 @@ StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Leave unchecked to keep the data folder for
|
||||
StrCpy $UNINSTALLER_FILE_Detail "Writing Uninstaller"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Writing Installer Registry Keys"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "It does not appear that ${APPLICATION_NAME} is installed in the directory '$INSTDIR'.$\r$\nContinue anyway (not recommended)?"
|
||||
StrCpy $UNINSTALL_ABORT "Uninstall aborted by user"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Quick Launch Shortcut (N/A)"
|
||||
StrCpy $INIT_NO_DESKTOP "Desktop Shortcut (overwrites existing)"
|
||||
StrCpy $UAC_ERROR_ELEVATE "Unable to elevate, error:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "This installer requires admin access, try again"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "The installer is already running."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "This uninstaller requires admin access, try again"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "The uninstaller is already running."
|
||||
StrCpy $SectionGroup_Shortcuts "Shortcuts"
|
||||
|
||||
@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Disinstalla ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Disinstalla ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Scegli l'opzione di manutenzione da eseguire."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Installazione degli elementi fondamentali di ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Icone di stato per Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installazione delle icone di stato per Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Scorciatoia di programma menu Start"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Aggiunta della scorciatoia per ${APPLICATION_NAME} al menu Start."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Scorciatoia del desktop"
|
||||
|
||||
@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "${APPLICATION_NAME}
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "${APPLICATION_NAME} をアンインストール"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "実行するには、メンテナンスオプションを選択してください。"
|
||||
StrCpy $SEC_APPLICATION_DETAILS "${APPLICATION_NAME} の重要なパッケージをインストール中"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Windowsエクスプローラの状態アイコン"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Windowsエクスプローラの状態アイコンをインストール中"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "スタートメニューショートカット"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "スタートメニューに${APPLICATION_NAME} のショートカットの追加"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "デスクトップショートカット"
|
||||
|
||||
@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Odinstaluj ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Odinstaluj ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Wybierz sposób utrzymywania."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Instaluje niezbędne pliki ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Ikona statusu dla Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instaluj ikonę statusu dla Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Skrót w Menu Start"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Dodaję skrót ${APPLICATION_NAME} w Menu Start."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Skrót na Pulpicie"
|
||||
|
||||
@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Desinstalar ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalar ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Escolha a opção de manutenção a fazer."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "A instalar o essencial de ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Icons de estado para Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "A instalar icons de estado para Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Atalho do progama no Menu Inicial"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "A adicionar o atalho de ${APPLICATION_NAME} ao Menu Inicial."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Atalho da área de trabalho"
|
||||
|
||||
@@ -6,7 +6,7 @@ StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Processo para eliminar n
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Uma versão mais antiga de ${APPLICATION_NAME} está instalado em seu sistema. É recomendado que você desinstale a versão atual antes de instalar. Selecione a operação que deseja executar e clique em Avançar para continuar."
|
||||
StrCpy $PageReinstall_NEW_Field_2 "Desinstalar antes de instalar"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "Não desinstale"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Já instalado"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Já Instalado"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Escolha como você deseja instalar ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "A versão mais recente do ${APPLICATION_NAME} já está instalado! Não é recomendado que você instale uma versão mais antiga. Se você realmente deseja instalar esta versão mais antiga, é melhor desinstalar a versão atual primeiro. Selecione a operação que deseja executar e clique em Avançar para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${version} já está instalado. \nSelecione a operação que deseja executar e clique em Avançar para continuar."
|
||||
@@ -15,8 +15,10 @@ StrCpy $PageReinstall_SAME_Field_3 "Desinstalar ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalar ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Escolha a opção de realizar manutenção."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Instalando ${APPLICATION_NAME} fundamentos."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Ícones de status para Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instalando os ícones de status para o Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Menu Iniciar Programa Atalho"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Adicionando atalho para ${APPLICATION_NAME} para o Menu Iniciar."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Adicionando atalho para ${APPLICATION_NAME} ao Menu Iniciar."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Atalho Desktop"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Criando Atalhos de Desktop"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Atalho Rápido"
|
||||
@@ -29,13 +31,13 @@ StrCpy $UNINSTALLER_APPDATA_SUBTITLE "Remover ${APPLICATION_NAME} pasta de dado
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_1 "Você quer apagar ${APPLICATION_NAME} 's pasta de dados?"
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Deixe desmarcada para manter a pasta de dados para uso posterior ou cheque para excluir a pasta de dados."
|
||||
StrCpy $UNINSTALLER_APPDATA_CHECKBOX "Sim, excluir essa pasta de dados."
|
||||
StrCpy $UNINSTALLER_FILE_Detail "Escrevendo Desinstalador"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Escrevendo Chaves de Registro do Inslalador"
|
||||
StrCpy $UNINSTALLER_FILE_Detail "Gravando Desinstalador"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Gravando Chaves de Registro do Inslalador"
|
||||
StrCpy $UNINSTALLER_FINISHED_Detail "Finalizado"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Não parece que ${APPLICATION_NAME} está instalado no diretório '$INSTDIR'.$\n$\nContinuar assim mesmo (não recomendado)?"
|
||||
StrCpy $UNINSTALL_ABORT "Desinstalação abortada pelo usuário"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Atalho de Inicialização Rápida (N/A)"
|
||||
StrCpy $INIT_NO_DESKTOP "Atalho Desktop (substituições existente)"
|
||||
StrCpy $INIT_NO_DESKTOP "Atalho Desktop (substitui os existente)"
|
||||
StrCpy $UAC_ERROR_ELEVATE "Incapaz de elevar, erro:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Este programa de instalação requer acesso de administrador, tente novamente"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "O instalador já está em execução."
|
||||
|
||||
@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Удалить ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Удалить ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Выберите опцию обслуживания для исполнения."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Установка зависимостей приложения ${APPLICATION_NAME}"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Значки статуса для проводника Windows"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Установка значков статуса для проводника Windows"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Ярлык в меню Пуск"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Добавление ярлыка ${APPLICATION_NAME} в меню Пуск"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Ярлык на рабочем столе"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Auto-generated - do not modify
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "查看版本日志"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "有 ${APPLICATION_EXECUTABLE} 项进程需要关闭。$\n您想让安装程序关闭这些进程吗?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "杀死${APPLICATION_EXECUTABLE}进程。"
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "未找到要杀死的进程!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "您的系统已经安装${APPLICATION_NAME}较老版本。建议安装前卸载当前版本。选择将要执行的操作,点击下一步继续。"
|
||||
@@ -7,11 +8,15 @@ StrCpy $PageReinstall_NEW_Field_2 "在安装前先卸载"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "不要卸载"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "已经安装"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "选择如何安装${APPLICATION_NAME}。"
|
||||
StrCpy $PageReinstall_SAME_Field_2 "添加/重装组件"
|
||||
StrCpy $PageReinstall_OLD_Field_1 "较新版本的 ${APPLICATION_NAME} 已经安装!安装较旧版本的程序是不推荐的。如果您希望继续安装较旧版本,建议先卸载较新版本。选择您想要执行的操作并点击下一步以继续。"
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} 已经安装。\n请选择想要执行的操作并点击下一步。"
|
||||
StrCpy $PageReinstall_SAME_Field_2 "增加/重装组件"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "卸载${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "卸载${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "选择需要执行的维护选项。"
|
||||
StrCpy $SEC_APPLICATION_DETAILS "安装${APPLICATION_NAME}基本组件。"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "开始菜单程序快捷方式"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "添加 ${APPLICATION_NAME} 快捷方式到开始菜单。"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "桌面快捷方式"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "创建桌面快捷方式"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "快速启动栏快捷方式"
|
||||
@@ -20,25 +25,22 @@ StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME}基本组件。"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME}快捷方式。"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "${APPLICATION_NAME}桌面快捷方式。"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "${APPLICATION_NAME}快速启动栏快捷方式。"
|
||||
StrCpy $UNINSTALLER_APPDATA_SUBTITLE "从电脑中移除 ${APPLICATION_NAME} 数据文件夹。"
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_1 "移除 ${APPLICATION_NAME} 数据文件夹?"
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "选择以删除数据文件夹,不选择以保留数据文件夹内容供后续使用。"
|
||||
StrCpy $UNINSTALLER_APPDATA_CHECKBOX "删除数据文件。"
|
||||
StrCpy $UNINSTALLER_FILE_Detail "覆盖卸载器"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "正在写入注册表"
|
||||
StrCpy $UNINSTALLER_FINISHED_Detail "完成"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "${APPLICATION_NAME} 可能并没有安装在 $INSTDIR。$\n$\n仍然继续吗?(不推荐)"
|
||||
StrCpy $UNINSTALL_ABORT "用户取消了卸载"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "快速启动栏快捷方式(N/A)"
|
||||
StrCpy $INIT_NO_DESKTOP "桌面快捷方式(覆盖)"
|
||||
StrCpy $UAC_ERROR_ELEVATE "无法获得权限,错误:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "安装程序需要管理员权限,请重试"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "安装程序已经运行。"
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "卸载程序需要管理员权限,请重试"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "卸载程序已经运行。"
|
||||
StrCpy $SectionGroup_Shortcuts "快捷方式"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Found ${APPLICATION_EXECUTABLE} process(s) which need to be stopped.$\nDo you want the installer to stop these for you?"
|
||||
StrCpy $PageReinstall_OLD_Field_1 "A newer version of ${APPLICATION_NAME} is already installed! It is not recommended that you install an older version. If you really want to install this older version, it is better to uninstall the current version first. Select the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.\r\nSelect the operation you want to perform and click Next to continue."
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Choose the maintenance option to perform."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Adding shortcut for ${APPLICATION_NAME} to the Start Menu."
|
||||
StrCpy $UNINSTALLER_APPDATA_SUBTITLE "Remove ${APPLICATION_NAME}'s data folder from your computer."
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_1 "Do you want to delete ${APPLICATION_NAME}'s data folder?"
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Leave unchecked to keep the data folder for later use or check to delete the data folder."
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Writing Installer Registry Keys"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "It does not appear that ${APPLICATION_NAME} is installed in the directory '$INSTDIR'.$\r$\nContinue anyway (not recommended)?"
|
||||
StrCpy $UNINSTALL_ABORT "Uninstall aborted by user"
|
||||
StrCpy $UAC_ERROR_ELEVATE "Unable to elevate, error:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "This installer requires admin access, try again"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "The installer is already running."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "This uninstaller requires admin access, try again"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "The uninstaller is already running."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status icons for Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing status icons for Windows Explorer"
|
||||
|
||||
@@ -3,7 +3,7 @@ StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Zobrazi
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Našli sa ${APPLICATION_EXECUTABLE} proces (y), ktoré je potrebné zastavi<76>.$\nChcete, aby ich inštalátor zastavil?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Ukonèujem ${APPLICATION_EXECUTABLE} procesy."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Proces ukonèenia nebol nájdený!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Staršia verzia ${APPLICATION_NAME} je nainštalovaná vo vašom systéme. Odporúèam vám odinštalova<76> aktuálnu verziu pred inštaláciou. Vyberte operáciu, ktorú chcete vykona<6E>, a kliknite na tlaèidlo Ïalej pre pokraèovanie."
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Staršia verzia ${APPLICATION_NAME} je nainštalovaná vo vašom poèítaèi. Odporúèam vám odinštalova<76> aktuálnu verziu pred inštaláciou. Vyberte operáciu, ktorú chcete vykona<6E>, a kliknite na tlaèidlo Ïalej pre pokraèovanie."
|
||||
StrCpy $PageReinstall_NEW_Field_2 "Odinštalova<EFBFBD> pred inštaláciou"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "Neodinštalova<EFBFBD>"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Už je nainštalovaný"
|
||||
@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Odin
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Odinštalova<EFBFBD> ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Vyberte možnos<6F> vykona<6E> údržbu."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Inštalujú sa náležitosti ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Stavová ikona pre Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Inštalujem stavovú ikonu pre Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Zástupca programu v menu Štart"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Prida<EFBFBD> zástupcu pre ${APPLICATION_NAME} do menu Štart."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Zástupca na ploche"
|
||||
|
||||
@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Odstrani ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Odstrani ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Izberite možnost vzdrževanja za izvedbo."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Poteka nameščanje ključnih paketov programa ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Ikona stanja za program Raziskovalec"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Nameščanje ikone stanja za Raziskovalca"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Bližnjica programa v programskem meniju"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Poteka dodajanje bližnjice programa ${APPLICATION_NAME} v programski meni."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Bližnica namizja"
|
||||
|
||||
@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Desinstalar ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalar ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Elija la opcion de mantenimiento a realizar."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Instalando ${APPLICATION_NAME} esenciales."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Íconos de estado para el Explorador de Windows"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instalando íconos de estado para el Explorador de Windows"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Acceso Directo al Programa Menú de Inicio"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Añadiendo accesos directos para ${APPLICATION_NAME} en el Menú de Inicio."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Acceso directo de Escritorio"
|
||||
|
||||
@@ -35,6 +35,8 @@ StrCpy $INIT_UNINSTALLER_RUNNING "El des-instalador ya esta corriendo"
|
||||
StrCpy $SectionGroup_Shortcuts "Accesos Directos"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Found ${APPLICATION_EXECUTABLE} process(s) which need to be stopped.$\nDo you want the installer to stop these for you?"
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.\r\nSelect the operation you want to perform and click Next to continue."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status icons for Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing status icons for Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Quick Launch Shortcut"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Creating Quick Launch Shortcut"
|
||||
StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} essentials."
|
||||
|
||||
@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Avinstallera ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Avinstallera ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Välj underhålls alternativ att utföra."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Installerar ${APPLICATION_NAME} väsentligheter."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Statusikoner för Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installerar statusikoner för Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Start-meny program genväg"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Lägger till genväg för ${APPLICATION_NAME} till Start-menyn."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Skrivbordsgenväg"
|
||||
|
||||
@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "${APPLICATION_NAME} uygulamas
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "${APPLICATION_NAME} uygulamasını kaldır"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Yapmak istediğiniz bakım işlemini seçin."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "${APPLICATION_NAME} gereklilikleri yükleniyor."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Windows Gezgini için durum simgeleri"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Windows Gezgini için durum simgeleri yükleniyor"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Başlat Menüsü Program Kısayolu"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "${APPLICATION_NAME} için Başlat Menüsü'ne kısayol ekleniyor."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Masaüstü Kısayolu"
|
||||
|
||||
@@ -15,6 +15,8 @@ Var PageReinstall_SAME_Field_3
|
||||
Var UNINSTALLER_APPDATA_TITLE
|
||||
Var PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE
|
||||
Var SEC_APPLICATION_DETAILS
|
||||
Var OPTION_SECTION_SC_SHELL_EXT_SECTION
|
||||
Var OPTION_SECTION_SC_SHELL_EXT_DetailPrint
|
||||
Var OPTION_SECTION_SC_START_MENU_SECTION
|
||||
Var OPTION_SECTION_SC_START_MENU_DetailPrint
|
||||
Var OPTION_SECTION_SC_DESKTOP_SECTION
|
||||
|
||||
@@ -23,3 +23,4 @@
|
||||
!insertmacro MUI_LANGUAGE "Slovak"
|
||||
!insertmacro MUI_LANGUAGE "Spanish"
|
||||
!insertmacro MUI_LANGUAGE "Polish"
|
||||
!insertmacro MUI_LANGUAGE "Farsi"
|
||||
|
||||
@@ -85,6 +85,14 @@ msgstr "Choose the maintenance option to perform."
|
||||
msgid "Installing ${APPLICATION_NAME} essentials."
|
||||
msgstr "Installing ${APPLICATION_NAME} essentials."
|
||||
|
||||
#. OPTION_SECTION_SC_SHELL_EXT_SECTION
|
||||
msgid "Status icons for Windows Explorer"
|
||||
msgstr "Status icons for Windows Explorer"
|
||||
|
||||
#. OPTION_SECTION_SC_SHELL_EXT_DetailPrint
|
||||
msgid "Installing status icons for Windows Explorer"
|
||||
msgstr "Installing status icons for Windows Explorer"
|
||||
|
||||
#. OPTION_SECTION_SC_START_MENU_SECTION
|
||||
msgid "Start Menu Program Shortcut"
|
||||
msgstr "Start Menu Program Shortcut"
|
||||
|
||||
1
binary
Submodule
1
binary
Submodule
Submodule binary added at 18d9ac810b
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# Always include srcdir and builddir in include path
|
||||
# This saves typing ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY} in
|
||||
# about every subdir
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# define system dependent compiler flags
|
||||
|
||||
include(CheckCCompilerFlag)
|
||||
@@ -10,10 +14,11 @@ if (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
|
||||
|
||||
# add -Wconversion ?
|
||||
# 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")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute -D_GNU_SOURCE")
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
if (UNIX)
|
||||
# Suffix for Linux
|
||||
SET(LIB_SUFFIX
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# Set system vars
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# This module defines
|
||||
# INOTIFY_INCLUDE_DIR, where to find inotify.h, etc.
|
||||
# INOTIFY_FOUND, If false, do not try to use inotify.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# FIND_PACKAGE_VERSION_CHECK(NAME (DEFAULT_MSG|"Custom failure message"))
|
||||
# This function is intended to be used in FindXXX.cmake modules files.
|
||||
# It handles NAME_FIND_VERSION and NAME_VERSION variables in a Module.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
find_program(PDFLATEX_EXECUTABLE NAMES pdflatex
|
||||
HINTS
|
||||
$ENV{PDFLATEX_DIR}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# - Try to find QtKeychain
|
||||
# Once done this will define
|
||||
# QTKEYCHAIN_FOUND - System has QtKeychain
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# - Try to find QtKeychain
|
||||
# Once done this will define
|
||||
# QTKEYCHAIN_FOUND - System has QtKeychain
|
||||
|
||||
@@ -50,8 +50,18 @@ if (SQLite3_FIND_VERSION AND _SQLITE3_VERSION)
|
||||
set(SQLite3_VERSION _SQLITE3_VERSION)
|
||||
endif (SQLite3_FIND_VERSION AND _SQLITE3_VERSION)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(SQLite3 DEFAULT_MSG SQLITE3_LIBRARIES SQLITE3_INCLUDE_DIRS)
|
||||
if (APPLE OR WIN32)
|
||||
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
|
||||
mark_as_advanced(SQLITE3_INCLUDE_DIRS SQLITE3_LIBRARIES)
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
find_program(SPHINX_EXECUTABLE NAMES sphinx-build
|
||||
HINTS
|
||||
$ENV{SPHINX_DIR}
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
<string>(C) 2014 @APPLICATION_VENDOR@</string>
|
||||
<key>SUShowReleaseNotes</key>
|
||||
<false/>
|
||||
<key>LSMinimumBundleVersion</key>
|
||||
<string>10.7.0</string>
|
||||
<key>SUPublicDSAKeyFile</key>
|
||||
<string>dsa_pub.pem</string>
|
||||
</dict>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# - macro_copy_file(_src _dst)
|
||||
# Copies a file to ${_dst} only if ${_src} is different (newer) than ${_dst}
|
||||
#
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
!define OPTION_LICENSE_AGREEMENT
|
||||
!endif
|
||||
!define OPTION_UAC_PLUGIN_ENHANCED
|
||||
!define OPTION_SECTION_SC_SHELL_EXT
|
||||
!define OPTION_SECTION_SC_START_MENU
|
||||
!define OPTION_SECTION_SC_DESKTOP
|
||||
!define OPTION_SECTION_SC_QUICK_LAUNCH
|
||||
@@ -94,6 +95,8 @@ ReserveFile "${NSISDIR}\Plugins\InstallOptions.dll"
|
||||
!include WordFunc.nsh ;Used by VersionCompare macro function.
|
||||
!include FileFunc.nsh ;Used to read out parameters
|
||||
!include UAC.nsh ;Used by the UAC elevation to install as user or admin.
|
||||
!include Library.nsh ;Used by the COM registration for shell extensions
|
||||
!include x64.nsh ;Used to determine the right arch for the shell extensions
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Memento selections stored in registry.
|
||||
@@ -111,8 +114,8 @@ ReserveFile "${NSISDIR}\Plugins\InstallOptions.dll"
|
||||
!define MUI_HEADERIMAGE
|
||||
!define MUI_HEADERIMAGE_BITMAP ${WIN_SETUP_BITMAP_PATH}/page_header.bmp
|
||||
!define MUI_COMPONENTSPAGE_SMALLDESC
|
||||
!define MUI_FINISHPAGE_LINK "www.${APPLICATION_DOMAIN}"
|
||||
!define MUI_FINISHPAGE_LINK_LOCATION "http://www.${APPLICATION_DOMAIN}"
|
||||
!define MUI_FINISHPAGE_LINK "${APPLICATION_DOMAIN}"
|
||||
!define MUI_FINISHPAGE_LINK_LOCATION "http://${APPLICATION_DOMAIN}"
|
||||
!define MUI_FINISHPAGE_NOREBOOTSUPPORT
|
||||
!ifdef OPTION_FINISHPAGE_RELEASE_NOTES
|
||||
!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
|
||||
@@ -279,6 +282,16 @@ Function EnsureOwncloudShutdown
|
||||
!insertmacro CheckAndConfirmEndProcess "${APPLICATION_EXECUTABLE}"
|
||||
FunctionEnd
|
||||
|
||||
Function InstallRedistributables
|
||||
${If} ${RunningX64}
|
||||
ExecWait '"$OUTDIR\vcredist_x64.exe" /install /quiet'
|
||||
${Else}
|
||||
ExecWait '"$OUTDIR\vcredist_x86.exe" /install /quiet'
|
||||
${EndIf}
|
||||
Delete "$OUTDIR\vcredist_x86.exe"
|
||||
Delete "$OUTDIR\vcredist_x64.exe"
|
||||
FunctionEnd
|
||||
|
||||
##############################################################################
|
||||
# #
|
||||
# RE-INSTALLER FUNCTIONS #
|
||||
@@ -370,14 +383,15 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
|
||||
;Main executable & csync
|
||||
File "${BUILD_PATH}\bin\${APPLICATION_EXECUTABLE}"
|
||||
File "${BUILD_PATH}\bin\${APPLICATION_CMD_EXECUTABLE}"
|
||||
File "${BUILD_PATH}\bin\socketapiclient.exe"
|
||||
File "${BUILD_PATH}\src\lib${APPLICATION_SHORTNAME}sync.dll"
|
||||
File "${BUILD_PATH}\csync\src\libocsync.dll"
|
||||
|
||||
|
||||
File "${BUILD_PATH}\src\mirall_*.qm"
|
||||
; 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\qtbase_*.qm"
|
||||
File "${MING_SHARE}\qt5\translations\qtkeychain_*.qm"
|
||||
|
||||
SetOutPath "$INSTDIR\platforms"
|
||||
@@ -414,15 +428,14 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
|
||||
|
||||
;Qt deps
|
||||
File "${MING_BIN}\libpng16-16.dll"
|
||||
File "${MING_BIN}\icudata51.dll"
|
||||
File "${MING_BIN}\icui18n51.dll"
|
||||
File "${MING_BIN}\icuuc51.dll"
|
||||
File "${MING_BIN}\icudata53.dll"
|
||||
File "${MING_BIN}\icui18n53.dll"
|
||||
File "${MING_BIN}\icuuc53.dll"
|
||||
File "${MING_BIN}\libEGL.dll"
|
||||
File "${MING_BIN}\libGLESv2.dll"
|
||||
File "${MING_BIN}\libjpeg-8.dll"
|
||||
File "${MING_BIN}\libpcre16-0.dll"
|
||||
File "${MING_BIN}\libproxy.dll"
|
||||
File "${MING_BIN}\libqt5keychain.dll"
|
||||
File "${MING_BIN}\libsqlite3-0.dll"
|
||||
File "${MING_BIN}\libcrypto-10.dll"
|
||||
File "${MING_BIN}\libssl-10.dll"
|
||||
@@ -435,9 +448,9 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
|
||||
File "${MING_BIN}\libsqlite3-0.dll"
|
||||
|
||||
;QtKeyChain stuff
|
||||
File "${MING_BIN}\libqtkeychain.dll"
|
||||
File "${MING_BIN}\libqt5keychain.dll"
|
||||
|
||||
; ownCloud plugin
|
||||
;ownCloud plugin
|
||||
File "${MING_BIN}\libintl-8.dll"
|
||||
File "${MING_BIN}\libneon-27.dll"
|
||||
File "${MING_BIN}\libproxy.dll"
|
||||
@@ -449,11 +462,32 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
|
||||
File "${MING_BIN}\libstdc++-6.dll"
|
||||
File "${MING_BIN}\libwinpthread-1.dll"
|
||||
|
||||
; CSync configs
|
||||
;CSync configs
|
||||
File "${SOURCE_PATH}/sync-exclude.lst"
|
||||
|
||||
SectionEnd
|
||||
|
||||
!ifdef OPTION_SECTION_SC_SHELL_EXT
|
||||
${MementoSection} $OPTION_SECTION_SC_SHELL_EXT_SECTION SEC_SHELL_EXT
|
||||
SectionIn 1 2
|
||||
SetDetailsPrint textonly
|
||||
DetailPrint $OPTION_SECTION_SC_SHELL_EXT_DetailPrint
|
||||
File "${BUILD_PATH}\vcredist_x86.exe"
|
||||
File "${BUILD_PATH}\vcredist_x64.exe"
|
||||
Call InstallRedistributables
|
||||
CreateDirectory "$INSTDIR\shellext"
|
||||
${If} ${RunningX64}
|
||||
!define LIBRARY_X64
|
||||
!insertmacro InstallLib DLL NOTSHARED REBOOT_PROTECTED "${SOURCE_PATH}\binary\shell_integration\windows\Release\x64\OCUtil_x64.dll" "$INSTDIR\shellext\OCUtil_x64.dll" "$INSTDIR\shellext"
|
||||
!insertmacro InstallLib REGDLL NOTSHARED REBOOT_PROTECTED "${SOURCE_PATH}\binary\shell_integration\windows\Release\x64\OCOverlays_x64.dll" "$INSTDIR\shellext\OCOverlays_x64.dll" "$INSTDIR\shellext"
|
||||
!undef LIBRARY_X64
|
||||
${Else}
|
||||
!insertmacro InstallLib DLL NOTSHARED REBOOT_PROTECTED "${SOURCE_PATH}\binary\shell_integration\windows\Release\Win32\OCUtil_x86.dll" "$INSTDIR\shellext\OCUtil_x86.dll" "$INSTDIR\shellext"
|
||||
!insertmacro InstallLib REGDLL NOTSHARED REBOOT_PROTECTED "${SOURCE_PATH}\binary\shell_integration\windows\Release\Win32\OCOverlays_x86.dll" "$INSTDIR\shellext\OCOverlays_x86.dll" "$INSTDIR\shellext"
|
||||
${Endif}
|
||||
${MementoSectionEnd}
|
||||
!endif
|
||||
|
||||
SectionGroup $SectionGroup_Shortcuts
|
||||
|
||||
!ifdef OPTION_SECTION_SC_START_MENU
|
||||
@@ -601,6 +635,21 @@ Section Uninstall
|
||||
|
||||
DeleteRegKey HKCR "${APPLICATION_NAME}"
|
||||
|
||||
;Shell extension
|
||||
!ifdef OPTION_SECTION_SC_SHELL_EXT
|
||||
!define LIBRARY_COM
|
||||
!define LIBRARY_SHELL_EXTENSION
|
||||
${If} ${HasSection} SEC_SHELL_EXT
|
||||
!define LIBRARY_X64
|
||||
!insertmacro UnInstallLib DLL NOTSHARED REBOOT_PROTECTED "$INSTDIR/shellext/OCUtil_x64.dll"
|
||||
!insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR/shellext/OCOverlays_x64.dll"
|
||||
!undef LIBRARY_X64
|
||||
${Else}
|
||||
!insertmacro UnInstallLib DLL NOTSHARED REBOOT_PROTECTED "$INSTDIR/shellext/OCUtil_x86.dll"
|
||||
!insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR/shellext/OCOverlays_x86.dll"
|
||||
${EndIf}
|
||||
!endif
|
||||
|
||||
;Start menu shortcut
|
||||
!ifdef OPTION_SECTION_SC_START_MENU
|
||||
SetShellVarContext all
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
include (MacroOptionalFindPackage)
|
||||
include (MacroLogFeature)
|
||||
|
||||
@@ -19,10 +23,11 @@ if( Qt5Core_FOUND )
|
||||
find_package(Qt5PrintSupport REQUIRED)
|
||||
find_package(Qt5Quick REQUIRED)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
if(APPLE)
|
||||
find_package(Qt5MacExtras REQUIRED)
|
||||
endif(APPLE)
|
||||
endif()
|
||||
if(APPLE)
|
||||
find_package(Qt5MacExtras REQUIRED)
|
||||
endif(APPLE)
|
||||
|
||||
else( Qt5Core_FOUND )
|
||||
if(WIN32 OR APPLE)
|
||||
message(FATAL_ERROR "Qt 5 not found, but application depends on Qt5 on Windows and Mac OS X")
|
||||
@@ -147,6 +152,19 @@ if(NOT Qt5Core_FOUND)
|
||||
|
||||
include( ${QT_USE_FILE} )
|
||||
endmacro()
|
||||
|
||||
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()
|
||||
|
||||
if( Qt5Core_DIR )
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# -helper macro to add a "doc" target with CMake build system.
|
||||
# and configure doxy.config.in to doxy.config
|
||||
#
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# (c) 2014 Copyright ownCloud, Inc.
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
|
||||
OUTPUT_VARIABLE GCC_VERSION)
|
||||
@@ -6,9 +10,11 @@ if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
else(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long")
|
||||
endif(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
if(CMAKE_CXX_COMPILER MATCHES "clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
endif(CMAKE_CXX_COMPILER MATCHES "clang")
|
||||
# TODO: handle msvc compilers warnings?
|
||||
|
||||
|
||||
@@ -27,10 +27,6 @@ include(MacroCopyFile)
|
||||
if (NOT WIN32)
|
||||
find_package(Iconv)
|
||||
endif (NOT WIN32)
|
||||
find_package(CMocka)
|
||||
if (CMOCKA_FOUND AND UNIT_TESTING)
|
||||
include(AddCMockaTest)
|
||||
endif (CMOCKA_FOUND AND UNIT_TESTING)
|
||||
|
||||
include(ConfigureChecks.cmake)
|
||||
|
||||
@@ -47,9 +43,13 @@ endif (MEM_NULL_TESTS)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
if (CMOCKA_FOUND AND UNIT_TESTING)
|
||||
add_subdirectory(tests)
|
||||
endif (CMOCKA_FOUND AND UNIT_TESTING)
|
||||
if (UNIT_TESTING)
|
||||
find_package(CMocka)
|
||||
if (CMOCKA_FOUND)
|
||||
include(AddCMockaTest)
|
||||
add_subdirectory(tests)
|
||||
endif (CMOCKA_FOUND)
|
||||
endif (UNIT_TESTING)
|
||||
|
||||
configure_file(config_csync.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config_csync.h)
|
||||
configure_file(config_test.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config_test.h)
|
||||
|
||||
@@ -4,13 +4,6 @@ add_subdirectory(std)
|
||||
add_subdirectory(httpbf)
|
||||
|
||||
# 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
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
@@ -86,8 +79,8 @@ set(csync_HDRS
|
||||
)
|
||||
|
||||
# Statically include sqlite
|
||||
if (CSYNC_STATIC_COMPILE_DIR)
|
||||
list(APPEND csync_SRCS ${CSYNC_STATIC_COMPILE_DIR}/dictionary.c ${CSYNC_STATIC_COMPILE_DIR}/sqlite3.c)
|
||||
if (USE_OUR_OWN_SQLITE3)
|
||||
list(APPEND csync_SRCS ${SQLITE3_SOURCE})
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
@@ -96,10 +89,10 @@ include_directories(
|
||||
)
|
||||
|
||||
add_library(${CSYNC_LIBRARY} SHARED ${csync_SRCS})
|
||||
add_library(${CSYNC_LIBRARY}_static STATIC ${csync_SRCS})
|
||||
#add_library(${CSYNC_LIBRARY}_static STATIC ${csync_SRCS})
|
||||
|
||||
target_link_libraries(${CSYNC_LIBRARY} ${CSYNC_LINK_LIBRARIES})
|
||||
target_link_libraries(${CSYNC_LIBRARY}_static ${CSYNC_LINK_LIBRARIES})
|
||||
#target_link_libraries(${CSYNC_LIBRARY}_static ${CSYNC_LINK_LIBRARIES})
|
||||
|
||||
set_target_properties(
|
||||
${CSYNC_LIBRARY}
|
||||
|
||||
@@ -96,8 +96,6 @@ static int _data_cmp(const void *key, const void *data) {
|
||||
int csync_create(CSYNC **csync, const char *local, const char *remote) {
|
||||
CSYNC *ctx;
|
||||
size_t len = 0;
|
||||
char *home;
|
||||
int rc;
|
||||
|
||||
ctx = c_malloc(sizeof(CSYNC));
|
||||
if (ctx == NULL) {
|
||||
@@ -129,31 +127,6 @@ int csync_create(CSYNC **csync, const char *local, const char *remote) {
|
||||
}
|
||||
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
ctx->options.local_only_mode = false;
|
||||
|
||||
ctx->pwd.uid = getuid();
|
||||
ctx->pwd.euid = geteuid();
|
||||
|
||||
home = csync_get_user_home_dir();
|
||||
if (home == NULL) {
|
||||
SAFE_FREE(ctx->local.uri);
|
||||
SAFE_FREE(ctx->remote.uri);
|
||||
SAFE_FREE(ctx);
|
||||
errno = ENOMEM;
|
||||
ctx->status_code = CSYNC_STATUS_MEMORY_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = asprintf(&ctx->options.config_dir, "%s/%s", home, CSYNC_CONF_DIR);
|
||||
SAFE_FREE(home);
|
||||
if (rc < 0) {
|
||||
SAFE_FREE(ctx->local.uri);
|
||||
SAFE_FREE(ctx->remote.uri);
|
||||
SAFE_FREE(ctx);
|
||||
errno = ENOMEM;
|
||||
ctx->status_code = CSYNC_STATUS_MEMORY_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->local.list = 0;
|
||||
ctx->remote.list = 0;
|
||||
@@ -167,7 +140,6 @@ int csync_create(CSYNC **csync, const char *local, const char *remote) {
|
||||
|
||||
int csync_init(CSYNC *ctx) {
|
||||
int rc;
|
||||
char *config = NULL;
|
||||
|
||||
if (ctx == NULL) {
|
||||
errno = EBADF;
|
||||
@@ -190,12 +162,8 @@ int csync_init(CSYNC *ctx) {
|
||||
|
||||
ctx->local.type = LOCAL_REPLICA;
|
||||
|
||||
if ( !ctx->options.local_only_mode) {
|
||||
owncloud_init(csync_get_userdata(ctx));
|
||||
ctx->remote.type = REMOTE_REPLICA;
|
||||
} else {
|
||||
ctx->remote.type = LOCAL_REPLICA;
|
||||
}
|
||||
owncloud_init(ctx);
|
||||
ctx->remote.type = REMOTE_REPLICA;
|
||||
|
||||
if (c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp) < 0) {
|
||||
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
|
||||
@@ -211,15 +179,12 @@ int csync_init(CSYNC *ctx) {
|
||||
|
||||
ctx->status = CSYNC_STATUS_INIT;
|
||||
|
||||
csync_set_module_property(ctx, "csync_context", ctx);
|
||||
|
||||
/* initialize random generator */
|
||||
srand(time(NULL));
|
||||
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
SAFE_FREE(config);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -234,7 +199,6 @@ int csync_update(CSYNC *ctx) {
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
/* create/load statedb */
|
||||
if (! csync_is_statedb_disabled(ctx)) {
|
||||
rc = asprintf(&ctx->statedb.file, "%s/.csync_journal.db",
|
||||
ctx->local.uri);
|
||||
if (rc < 0) {
|
||||
@@ -248,7 +212,6 @@ int csync_update(CSYNC *ctx) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
@@ -265,9 +228,10 @@ int csync_update(CSYNC *ctx) {
|
||||
|
||||
rc = csync_ftw(ctx, ctx->local.uri, csync_walker, MAX_DEPTH);
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
csync_gettime(&finish);
|
||||
@@ -278,30 +242,33 @@ int csync_update(CSYNC *ctx) {
|
||||
csync_memstat_check();
|
||||
|
||||
/* update detection for remote replica */
|
||||
if( ! ctx->options.local_only_mode ) {
|
||||
csync_gettime(&start);
|
||||
ctx->current = REMOTE_REPLICA;
|
||||
ctx->replica = ctx->remote.type;
|
||||
csync_gettime(&start);
|
||||
ctx->current = REMOTE_REPLICA;
|
||||
ctx->replica = ctx->remote.type;
|
||||
|
||||
rc = csync_ftw(ctx, ctx->remote.uri, csync_walker, MAX_DEPTH);
|
||||
if (rc < 0) {
|
||||
if(ctx->status_code == CSYNC_STATUS_OK)
|
||||
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_UPDATE_ERROR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
csync_gettime(&finish);
|
||||
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
|
||||
"Update detection for remote replica took %.2f seconds "
|
||||
"walking %zu files.",
|
||||
c_secdiff(finish, start), c_rbtree_size(ctx->remote.tree));
|
||||
csync_memstat_check();
|
||||
rc = csync_ftw(ctx, ctx->remote.uri, csync_walker, MAX_DEPTH);
|
||||
if (rc < 0) {
|
||||
if(ctx->status_code == CSYNC_STATUS_OK) {
|
||||
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_UPDATE_ERROR);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
csync_gettime(&finish);
|
||||
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
|
||||
"Update detection for remote replica took %.2f seconds "
|
||||
"walking %zu files.",
|
||||
c_secdiff(finish, start), c_rbtree_size(ctx->remote.tree));
|
||||
csync_memstat_check();
|
||||
|
||||
ctx->status |= CSYNC_STATUS_UPDATE;
|
||||
|
||||
return 0;
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
csync_statedb_close(ctx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int csync_reconcile(CSYNC *ctx) {
|
||||
@@ -317,6 +284,12 @@ int csync_reconcile(CSYNC *ctx) {
|
||||
/* Reconciliation for local replica */
|
||||
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->replica = ctx->local.type;
|
||||
|
||||
@@ -332,7 +305,7 @@ int csync_reconcile(CSYNC *ctx) {
|
||||
if (!CSYNC_STATUS_IS_OK(ctx->status_code)) {
|
||||
ctx->status_code = csync_errno_to_status( errno, CSYNC_STATUS_RECONCILE_ERROR );
|
||||
}
|
||||
return -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Reconciliation for remote replica */
|
||||
@@ -353,11 +326,15 @@ int csync_reconcile(CSYNC *ctx) {
|
||||
if (!CSYNC_STATUS_IS_OK(ctx->status_code)) {
|
||||
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_RECONCILE_ERROR );
|
||||
}
|
||||
return -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctx->status |= CSYNC_STATUS_RECONCILE;
|
||||
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
csync_statedb_close(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -431,14 +408,15 @@ static int _csync_treewalk_visitor(void *obj, void *data) {
|
||||
trav.path = cur->path;
|
||||
trav.size = cur->size;
|
||||
trav.modtime = cur->modtime;
|
||||
trav.uid = cur->uid;
|
||||
trav.gid = cur->gid;
|
||||
trav.mode = cur->mode;
|
||||
trav.type = cur->type;
|
||||
trav.instruction = cur->instruction;
|
||||
trav.rename_path = cur->destpath;
|
||||
trav.etag = cur->etag;
|
||||
trav.file_id = cur->file_id;
|
||||
trav.remotePerm = cur->remotePerm;
|
||||
trav.directDownloadUrl = cur->directDownloadUrl;
|
||||
trav.directDownloadCookies = cur->directDownloadCookies;
|
||||
trav.inode = cur->inode;
|
||||
|
||||
trav.error_status = cur->error_status;
|
||||
@@ -461,7 +439,7 @@ static int _csync_treewalk_visitor(void *obj, void *data) {
|
||||
|
||||
rc = (*visitor)(&trav, twctx->userdata);
|
||||
cur->instruction = trav.instruction;
|
||||
if (trav.etag != cur->etag) {
|
||||
if (trav.etag != cur->etag) { // FIXME It would be nice to have this documented
|
||||
SAFE_FREE(cur->etag);
|
||||
cur->etag = c_strdup(trav.etag);
|
||||
}
|
||||
@@ -560,8 +538,6 @@ static void _tree_destructor(void *data) {
|
||||
* used by csync_commit and csync_destroy */
|
||||
static void _csync_clean_ctx(CSYNC *ctx)
|
||||
{
|
||||
c_list_t * walk;
|
||||
|
||||
/* destroy the rbtrees */
|
||||
if (c_rbtree_size(ctx->local.tree) > 0) {
|
||||
c_rbtree_destroy(ctx->local.tree, _tree_destructor);
|
||||
@@ -573,25 +549,14 @@ static void _csync_clean_ctx(CSYNC *ctx)
|
||||
|
||||
csync_rename_destroy(ctx);
|
||||
|
||||
for (walk = c_list_last(ctx->local.ignored_cleanup); walk != NULL; walk = c_list_prev(walk)) {
|
||||
SAFE_FREE(walk->data);
|
||||
}
|
||||
for (walk = c_list_last(ctx->remote.ignored_cleanup); walk != NULL; walk = c_list_prev(walk)) {
|
||||
SAFE_FREE(walk->data);
|
||||
}
|
||||
|
||||
/* free memory */
|
||||
c_rbtree_free(ctx->local.tree);
|
||||
c_list_free(ctx->local.list);
|
||||
c_list_free(ctx->local.ignored_cleanup);
|
||||
c_rbtree_free(ctx->remote.tree);
|
||||
c_list_free(ctx->remote.list);
|
||||
c_list_free(ctx->remote.ignored_cleanup);
|
||||
|
||||
ctx->remote.list = 0;
|
||||
ctx->local.list = 0;
|
||||
ctx->remote.ignored_cleanup = 0;
|
||||
ctx->local.ignored_cleanup = 0;
|
||||
|
||||
SAFE_FREE(ctx->statedb.file);
|
||||
}
|
||||
@@ -612,7 +577,7 @@ int csync_commit(CSYNC *ctx) {
|
||||
}
|
||||
ctx->statedb.db = NULL;
|
||||
|
||||
rc = csync_vio_commit(ctx);
|
||||
rc = owncloud_commit(ctx);
|
||||
if (rc < 0) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "commit failed: %s",
|
||||
ctx->error_string ? ctx->error_string : "");
|
||||
@@ -671,9 +636,10 @@ int csync_destroy(CSYNC *ctx) {
|
||||
|
||||
SAFE_FREE(ctx->local.uri);
|
||||
SAFE_FREE(ctx->remote.uri);
|
||||
SAFE_FREE(ctx->options.config_dir);
|
||||
SAFE_FREE(ctx->error_string);
|
||||
|
||||
owncloud_destroy(ctx);
|
||||
|
||||
#ifdef WITH_ICONV
|
||||
c_close_iconv();
|
||||
#endif
|
||||
@@ -697,7 +663,7 @@ int csync_add_exclude_list(CSYNC *ctx, const char *path) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return csync_exclude_load(ctx, path);
|
||||
return csync_exclude_load(path, &ctx->excludes);
|
||||
}
|
||||
|
||||
void csync_clear_exclude_list(CSYNC *ctx)
|
||||
@@ -705,70 +671,6 @@ void csync_clear_exclude_list(CSYNC *ctx)
|
||||
csync_exclude_clear(ctx);
|
||||
}
|
||||
|
||||
const char *csync_get_config_dir(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctx->options.config_dir;
|
||||
}
|
||||
|
||||
int csync_set_config_dir(CSYNC *ctx, const char *path) {
|
||||
if (ctx == NULL || path == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SAFE_FREE(ctx->options.config_dir);
|
||||
ctx->options.config_dir = c_strdup(path);
|
||||
if (ctx->options.config_dir == NULL) {
|
||||
ctx->status_code = CSYNC_STATUS_MEMORY_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int csync_enable_statedb(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
if (ctx->status & CSYNC_STATUS_INIT) {
|
||||
fprintf(stderr, "This function must be called before initialization.");
|
||||
ctx->status_code = CSYNC_STATUS_CSYNC_STATUS_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->statedb.disabled = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int csync_disable_statedb(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
if (ctx->status & CSYNC_STATUS_INIT) {
|
||||
fprintf(stderr, "This function must be called before initialization.");
|
||||
ctx->status_code = CSYNC_STATUS_CSYNC_STATUS_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->statedb.disabled = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int csync_is_statedb_disabled(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return ctx->statedb.disabled;
|
||||
}
|
||||
|
||||
int csync_set_auth_callback(CSYNC *ctx, csync_auth_callback cb) {
|
||||
if (ctx == NULL || cb == NULL) {
|
||||
return -1;
|
||||
@@ -784,15 +686,6 @@ int csync_set_auth_callback(CSYNC *ctx, csync_auth_callback cb) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *csync_get_statedb_file(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
return c_strdup(ctx->statedb.file);
|
||||
}
|
||||
|
||||
void *csync_get_userdata(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return NULL;
|
||||
@@ -836,33 +729,6 @@ CSYNC_STATUS csync_get_status(CSYNC *ctx) {
|
||||
return ctx->status_code;
|
||||
}
|
||||
|
||||
int csync_set_local_only(CSYNC *ctx, bool local_only) {
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
if (ctx->status & CSYNC_STATUS_INIT) {
|
||||
fprintf(stderr, "csync_set_local_only: This function must be called before initialization.");
|
||||
ctx->status_code = CSYNC_STATUS_CSYNC_STATUS_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->options.local_only_mode=local_only;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool csync_get_local_only(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
return ctx->options.local_only_mode;
|
||||
}
|
||||
|
||||
const char *csync_get_status_string(CSYNC *ctx)
|
||||
{
|
||||
return csync_vio_get_status_string(ctx);
|
||||
@@ -907,6 +773,8 @@ int csync_abort_requested(CSYNC *ctx)
|
||||
void csync_file_stat_free(csync_file_stat_t *st)
|
||||
{
|
||||
if (st) {
|
||||
SAFE_FREE(st->directDownloadUrl);
|
||||
SAFE_FREE(st->directDownloadCookies);
|
||||
SAFE_FREE(st->etag);
|
||||
SAFE_FREE(st->destpath);
|
||||
SAFE_FREE(st);
|
||||
@@ -915,7 +783,7 @@ void csync_file_stat_free(csync_file_stat_t *st)
|
||||
|
||||
int csync_set_module_property(CSYNC* ctx, const char* key, void* value)
|
||||
{
|
||||
return csync_vio_set_property(ctx, key, value);
|
||||
return owncloud_set_property(ctx, key, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -44,13 +44,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* csync file declarations
|
||||
*/
|
||||
#define CSYNC_CONF_DIR ".ocsync"
|
||||
#define CSYNC_CONF_FILE "ocsync.conf"
|
||||
#define CSYNC_EXCLUDE_FILE "ocsync_exclude.conf"
|
||||
|
||||
/**
|
||||
* Instruction enum. In the file traversal structure, it describes
|
||||
* the csync state of a file.
|
||||
@@ -59,7 +52,7 @@ enum csync_status_codes_e {
|
||||
CSYNC_STATUS_OK = 0,
|
||||
|
||||
CSYNC_STATUS_ERROR = 1024, /* don't use this code,
|
||||
just use in csync_status_ok */
|
||||
*/
|
||||
CSYNC_STATUS_UNSUCCESSFUL,
|
||||
CSYNC_STATUS_NO_LOCK, /* OBSOLETE does not happen anymore */
|
||||
CSYNC_STATUS_STATEDB_LOAD_ERROR,
|
||||
@@ -101,6 +94,7 @@ enum csync_status_codes_e {
|
||||
CSYNC_STATUS_ABORTED,
|
||||
/* Codes for file individual status: */
|
||||
CSYNC_STATUS_INDIVIDUAL_IS_SYMLINK,
|
||||
CSYNC_STATUS_INDIVIDUAL_IS_HARDLINK,
|
||||
CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST,
|
||||
CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS,
|
||||
CYSNC_STATUS_FILE_LOCKED_OR_OPEN
|
||||
@@ -141,23 +135,6 @@ enum csync_ftw_type_e {
|
||||
CSYNC_FTW_TYPE_SKIP
|
||||
};
|
||||
|
||||
enum csync_notify_type_e {
|
||||
CSYNC_NOTIFY_INVALID,
|
||||
CSYNC_NOTIFY_START_SYNC_SEQUENCE,
|
||||
CSYNC_NOTIFY_START_DOWNLOAD,
|
||||
CSYNC_NOTIFY_START_UPLOAD,
|
||||
CSYNC_NOTIFY_PROGRESS,
|
||||
CSYNC_NOTIFY_FINISHED_DOWNLOAD,
|
||||
CSYNC_NOTIFY_FINISHED_UPLOAD,
|
||||
CSYNC_NOTIFY_FINISHED_SYNC_SEQUENCE,
|
||||
CSYNC_NOTIFY_START_DELETE,
|
||||
CSYNC_NOTIFY_END_DELETE,
|
||||
CSYNC_NOTIFY_ERROR,
|
||||
CSYNC_NOTIFY_START_LOCAL_UPDATE,
|
||||
CSYNC_NOTIFY_FINISHED_LOCAL_UPDATE,
|
||||
CSYNC_NOTIFY_START_REMOTE_UPDATE,
|
||||
CSYNC_NOTIFY_FINISHED_REMOTE_UPDATE
|
||||
};
|
||||
|
||||
/**
|
||||
* CSync File Traversal structure.
|
||||
@@ -172,13 +149,6 @@ struct csync_tree_walk_file_s {
|
||||
int64_t size;
|
||||
int64_t inode;
|
||||
time_t modtime;
|
||||
#ifdef _WIN32
|
||||
uint32_t uid;
|
||||
uint32_t gid;
|
||||
#else
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
#endif
|
||||
mode_t mode;
|
||||
enum csync_ftw_type_e type;
|
||||
enum csync_instructions_e instruction;
|
||||
@@ -189,6 +159,9 @@ struct csync_tree_walk_file_s {
|
||||
const char *rename_path;
|
||||
const char *etag;
|
||||
const char *file_id;
|
||||
const char *remotePerm;
|
||||
char *directDownloadUrl;
|
||||
char *directDownloadCookies;
|
||||
struct {
|
||||
int64_t size;
|
||||
time_t modtime;
|
||||
@@ -214,14 +187,9 @@ typedef void (*csync_log_callback) (int verbosity,
|
||||
const char *buffer,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Check internal csync status.
|
||||
*
|
||||
* @param csync The context to check.
|
||||
*
|
||||
* @return true if status is error free, false for error states.
|
||||
*/
|
||||
bool csync_status_ok(CSYNC *ctx);
|
||||
typedef void (*csync_update_callback) (bool local,
|
||||
const char *dirUrl,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Allocate a csync context.
|
||||
@@ -333,62 +301,6 @@ int csync_add_exclude_list(CSYNC *ctx, const char *path);
|
||||
*/
|
||||
void csync_clear_exclude_list(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Get the config directory.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*
|
||||
* @return The path of the config directory or NULL on error.
|
||||
*/
|
||||
const char *csync_get_config_dir(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Change the config directory.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*
|
||||
* @param path The path to the new config directory.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
*/
|
||||
int csync_set_config_dir(CSYNC *ctx, const char *path);
|
||||
|
||||
/**
|
||||
* @brief Remove the complete config directory.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
*/
|
||||
int csync_remove_config_dir(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Enable the usage of the statedb. It is enabled by default.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
*/
|
||||
int csync_enable_statedb(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Disable the usage of the statedb. It is enabled by default.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
*/
|
||||
int csync_disable_statedb(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Check if the statedb usage is enabled.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*
|
||||
* @return 1 if it is enabled, 0 if it is disabled.
|
||||
*/
|
||||
int csync_is_statedb_disabled(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Get the userdata saved in the context.
|
||||
*
|
||||
@@ -481,31 +393,6 @@ void *csync_get_log_userdata(void);
|
||||
*/
|
||||
int csync_set_log_userdata(void *data);
|
||||
|
||||
/**
|
||||
* @brief Get the path of the statedb file used.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*
|
||||
* @return The path to the statedb file, NULL if an error occured.
|
||||
*/
|
||||
const char *csync_get_statedb_file(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Flag to tell csync that only a local run is intended. Call before csync_init
|
||||
*
|
||||
* @param local_only Bool flag to indicate local only mode.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occured.
|
||||
*/
|
||||
int csync_set_local_only( CSYNC *ctx, bool local_only );
|
||||
|
||||
/**
|
||||
* @brief Retrieve the flag to tell csync that only a local run is intended.
|
||||
*
|
||||
* @return 1: stay local only, 0: local and remote mode
|
||||
*/
|
||||
bool csync_get_local_only( CSYNC *ctx );
|
||||
|
||||
/* Used for special modes or debugging */
|
||||
CSYNC_STATUS csync_get_status(CSYNC *ctx);
|
||||
|
||||
|
||||
@@ -20,12 +20,18 @@
|
||||
|
||||
#include "config_csync.h"
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "c_private.h"
|
||||
|
||||
#include "csync_private.h"
|
||||
#include "csync_exclude.h"
|
||||
@@ -34,28 +40,31 @@
|
||||
#define CSYNC_LOG_CATEGORY_NAME "csync.exclude"
|
||||
#include "csync_log.h"
|
||||
|
||||
static int _csync_exclude_add(CSYNC *ctx, const char *string) {
|
||||
#ifndef NDEBUG
|
||||
static
|
||||
#endif
|
||||
int _csync_exclude_add(c_strlist_t **inList, const char *string) {
|
||||
c_strlist_t *list;
|
||||
|
||||
if (ctx->excludes == NULL) {
|
||||
ctx->excludes = c_strlist_new(32);
|
||||
if (ctx->excludes == NULL) {
|
||||
if (*inList == NULL) {
|
||||
*inList = c_strlist_new(32);
|
||||
if (*inList == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->excludes->count == ctx->excludes->size) {
|
||||
list = c_strlist_expand(ctx->excludes, 2 * ctx->excludes->size);
|
||||
if ((*inList)->count == (*inList)->size) {
|
||||
list = c_strlist_expand(*inList, 2 * (*inList)->size);
|
||||
if (list == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ctx->excludes = list;
|
||||
*inList = list;
|
||||
}
|
||||
|
||||
return c_strlist_add(ctx->excludes, string);
|
||||
return c_strlist_add(*inList, string);
|
||||
}
|
||||
|
||||
int csync_exclude_load(CSYNC *ctx, const char *fname) {
|
||||
int csync_exclude_load(const char *fname, c_strlist_t **list) {
|
||||
int fd = -1;
|
||||
int i = 0;
|
||||
int rc = -1;
|
||||
@@ -64,7 +73,7 @@ int csync_exclude_load(CSYNC *ctx, const char *fname) {
|
||||
char *entry = NULL;
|
||||
mbchar_t *w_fname;
|
||||
|
||||
if (ctx == NULL || fname == NULL) {
|
||||
if (fname == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -113,7 +122,7 @@ int csync_exclude_load(CSYNC *ctx, const char *fname) {
|
||||
buf[i] = '\0';
|
||||
if (*entry != '#') {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Adding entry: %s", entry);
|
||||
rc = _csync_exclude_add(ctx, entry);
|
||||
rc = _csync_exclude_add(list, entry);
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
@@ -139,6 +148,49 @@ void csync_exclude_destroy(CSYNC *ctx) {
|
||||
}
|
||||
|
||||
CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype) {
|
||||
|
||||
CSYNC_EXCLUDE_TYPE match = CSYNC_NOT_EXCLUDED;
|
||||
|
||||
match = csync_excluded_no_ctx( ctx->excludes, path, filetype );
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
// See http://support.microsoft.com/kb/74496
|
||||
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) {
|
||||
size_t i = 0;
|
||||
const char *p = NULL;
|
||||
char *bname = NULL;
|
||||
@@ -184,6 +236,27 @@ CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Windows cannot sync files ending in spaces (#2176). It also cannot
|
||||
// distinguish files ending in '.' from files without an ending,
|
||||
// as '.' is a separator that is not stored internally, so let's
|
||||
// not allow to sync those to avoid file loss/ambiguities (#416)
|
||||
size_t blen = strlen(bname);
|
||||
if (blen > 1 && (bname[blen-1]== ' ' || bname[blen-1]== '.' )) {
|
||||
match = CSYNC_FILE_EXCLUDE_INVALID_CHAR;
|
||||
SAFE_FREE(bname);
|
||||
SAFE_FREE(dname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (csync_is_windows_reserved_word(bname)) {
|
||||
match = CSYNC_FILE_EXCLUDE_INVALID_CHAR;
|
||||
SAFE_FREE(bname);
|
||||
SAFE_FREE(dname);
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = csync_fnmatch(".owncloudsync.log*", bname, 0);
|
||||
if (rc == 0) {
|
||||
match = CSYNC_FILE_SILENTLY_EXCLUDED;
|
||||
@@ -202,7 +275,10 @@ CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype) {
|
||||
}
|
||||
|
||||
if (getenv("CSYNC_CONFLICT_FILE_USERNAME")) {
|
||||
asprintf(&conflict, "*_conflict_%s-*", getenv("CSYNC_CONFLICT_FILE_USERNAME"));
|
||||
rc = asprintf(&conflict, "*_conflict_%s-*", getenv("CSYNC_CONFLICT_FILE_USERNAME"));
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
rc = csync_fnmatch(conflict, path, 0);
|
||||
if (rc == 0) {
|
||||
match = CSYNC_FILE_SILENTLY_EXCLUDED;
|
||||
@@ -217,14 +293,14 @@ CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype) {
|
||||
SAFE_FREE(bname);
|
||||
SAFE_FREE(dname);
|
||||
|
||||
if (ctx->excludes == NULL) {
|
||||
if( ! excludes ) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Loop over all exclude patterns and evaluate the given path */
|
||||
for (i = 0; match == CSYNC_NOT_EXCLUDED && i < ctx->excludes->count; i++) {
|
||||
for (i = 0; match == CSYNC_NOT_EXCLUDED && i < excludes->count; i++) {
|
||||
bool match_dirs_only = false;
|
||||
char *pattern_stored = c_strdup(ctx->excludes->vector[i]);
|
||||
char *pattern_stored = c_strdup(excludes->vector[i]);
|
||||
char* pattern = pattern_stored;
|
||||
|
||||
type = CSYNC_FILE_EXCLUDE_LIST;
|
||||
@@ -304,6 +380,7 @@ CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype) {
|
||||
SAFE_FREE(dname);
|
||||
}
|
||||
|
||||
|
||||
out:
|
||||
|
||||
return match;
|
||||
|
||||
@@ -29,6 +29,11 @@ enum csync_exclude_type_e {
|
||||
CSYNC_FILE_EXCLUDE_INVALID_CHAR
|
||||
};
|
||||
typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE;
|
||||
|
||||
#ifdef NDEBUG
|
||||
int _csync_exclude_add(c_strlist_t **inList, const char *string);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Load exclude list
|
||||
*
|
||||
@@ -37,7 +42,7 @@ typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE;
|
||||
*
|
||||
* @return 0 on success, -1 if an error occured with errno set.
|
||||
*/
|
||||
int csync_exclude_load(CSYNC *ctx, const char *fname);
|
||||
int csync_exclude_load(const char *fname, c_strlist_t **list);
|
||||
|
||||
/**
|
||||
* @brief Clear the exclude list in memory.
|
||||
@@ -65,6 +70,22 @@ void csync_exclude_destroy(CSYNC *ctx);
|
||||
*/
|
||||
CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype);
|
||||
|
||||
/**
|
||||
* @brief csync_excluded_no_ctx
|
||||
* @param excludes
|
||||
* @param path
|
||||
* @param filetype
|
||||
* @return
|
||||
*/
|
||||
CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype);
|
||||
#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: */
|
||||
|
||||
@@ -47,52 +47,6 @@
|
||||
#include "csync_macros.h"
|
||||
#include "csync_log.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
char *csync_get_user_home_dir(void) {
|
||||
wchar_t tmp[MAX_PATH];
|
||||
char *szPath = NULL;
|
||||
|
||||
if( SHGetFolderPathW( NULL,
|
||||
CSIDL_PROFILE|CSIDL_FLAG_CREATE,
|
||||
NULL,
|
||||
0,
|
||||
tmp) == S_OK ) {
|
||||
szPath = c_utf8_from_locale(tmp);
|
||||
return szPath;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else /* ************* !WIN32 ************ */
|
||||
|
||||
#ifndef NSS_BUFLEN_PASSWD
|
||||
#define NSS_BUFLEN_PASSWD 4096
|
||||
#endif /* NSS_BUFLEN_PASSWD */
|
||||
|
||||
char *csync_get_user_home_dir(void) {
|
||||
const char *envp;
|
||||
struct passwd pwd;
|
||||
struct passwd *pwdbuf;
|
||||
char buf[NSS_BUFLEN_PASSWD];
|
||||
int rc;
|
||||
|
||||
envp = getenv("HOME");
|
||||
if (envp != NULL && envp[0] != '\0') {
|
||||
return c_strdup(envp);
|
||||
}
|
||||
|
||||
/* Still nothing found, read the password file */
|
||||
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
|
||||
if (rc != 0) {
|
||||
return c_strdup(pwd.pw_dir);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* ************* WIN32 ************ */
|
||||
|
||||
#ifdef HAVE_FNMATCH
|
||||
#include <fnmatch.h>
|
||||
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
|
||||
#endif
|
||||
|
||||
char *csync_get_user_home_dir(void);
|
||||
|
||||
int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags);
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,79 +20,12 @@
|
||||
*/
|
||||
|
||||
#include "csync_owncloud.h"
|
||||
#include "csync_owncloud_private.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
/*
|
||||
* free the fetchCtx
|
||||
*/
|
||||
static void free_fetchCtx( struct listdir_context *ctx )
|
||||
{
|
||||
struct resource *newres, *res;
|
||||
if( ! ctx ) return;
|
||||
newres = ctx->list;
|
||||
res = newres;
|
||||
#include "csync_private.h"
|
||||
|
||||
ctx->ref--;
|
||||
if (ctx->ref > 0) return;
|
||||
|
||||
SAFE_FREE(ctx->target);
|
||||
|
||||
while( res ) {
|
||||
SAFE_FREE(res->uri);
|
||||
SAFE_FREE(res->name);
|
||||
SAFE_FREE(res->md5);
|
||||
memset( res->file_id, 0, FILE_ID_BUF_SIZE+1 );
|
||||
|
||||
newres = res->next;
|
||||
SAFE_FREE(res);
|
||||
res = newres;
|
||||
}
|
||||
SAFE_FREE(ctx);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* local variables.
|
||||
*/
|
||||
|
||||
struct dav_session_s dav_session; /* The DAV Session, initialised in dav_connect */
|
||||
int _connected = 0; /* flag to indicate if a connection exists, ie.
|
||||
the dav_session is valid */
|
||||
|
||||
|
||||
void *_userdata;
|
||||
long long chunked_total_size = 0;
|
||||
long long chunked_done = 0;
|
||||
|
||||
struct listdir_context *propfind_cache = 0;
|
||||
|
||||
bool is_first_propfind = true;
|
||||
|
||||
|
||||
csync_vio_file_stat_t _stat_cache;
|
||||
/* id cache, cache the ETag: header of a GET request */
|
||||
struct { char *uri; char *id; } _id_cache = { NULL, NULL };
|
||||
|
||||
static void clean_caches() {
|
||||
clear_propfind_recursive_cache();
|
||||
|
||||
free_fetchCtx(propfind_cache);
|
||||
propfind_cache = NULL;
|
||||
|
||||
SAFE_FREE(_stat_cache.name);
|
||||
SAFE_FREE(_stat_cache.etag );
|
||||
memset( _stat_cache.file_id, 0, FILE_ID_BUF_SIZE+1 );
|
||||
|
||||
SAFE_FREE(_id_cache.uri);
|
||||
SAFE_FREE(_id_cache.id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define PUT_BUFFER_SIZE 1024*5
|
||||
|
||||
char _buffer[PUT_BUFFER_SIZE];
|
||||
|
||||
/*
|
||||
* helper method to build up a user text for SSL problems, called from the
|
||||
@@ -116,7 +49,7 @@ static void addSSLWarning( char *ptr, const char *warn, int len )
|
||||
* it to the csync callback to ask the user.
|
||||
*/
|
||||
#define LEN 4096
|
||||
static int verify_sslcert(void *userdata, int failures,
|
||||
static int ssl_callback_by_neon(void *userdata, int failures,
|
||||
const ne_ssl_certificate *certificate)
|
||||
{
|
||||
char problem[LEN];
|
||||
@@ -124,8 +57,8 @@ static int verify_sslcert(void *userdata, int failures,
|
||||
int ret = -1;
|
||||
const ne_ssl_certificate *cert = certificate;
|
||||
csync_auth_callback authcb = NULL;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
|
||||
(void) userdata;
|
||||
memset( problem, 0, LEN );
|
||||
|
||||
while( cert ) {
|
||||
@@ -161,14 +94,14 @@ static int verify_sslcert(void *userdata, int failures,
|
||||
}
|
||||
addSSLWarning( problem, "Do you want to accept the certificate chain anyway?\nAnswer yes to do so and take the risk: ", LEN );
|
||||
|
||||
if( dav_session.csync_ctx ) {
|
||||
authcb = csync_get_auth_callback( dav_session.csync_ctx );
|
||||
if( ctx->csync_ctx ) {
|
||||
authcb = csync_get_auth_callback( ctx->csync_ctx );
|
||||
}
|
||||
if( authcb ){
|
||||
/* call the csync callback */
|
||||
DEBUG_WEBDAV("Call the csync callback for SSL problems");
|
||||
memset( buf, 0, NE_ABUFSIZ );
|
||||
(*authcb) ( problem, buf, NE_ABUFSIZ-1, 1, 0, _userdata );
|
||||
(*authcb) ( problem, buf, NE_ABUFSIZ-1, 1, 0, csync_get_userdata(ctx->csync_ctx) );
|
||||
if( buf[0] == 'y' || buf[0] == 'Y') {
|
||||
ret = 0;
|
||||
} else {
|
||||
@@ -177,48 +110,46 @@ static int verify_sslcert(void *userdata, int failures,
|
||||
}
|
||||
}
|
||||
DEBUG_WEBDAV("## VERIFY_SSL CERT: %d", ret );
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Authentication callback. Is set by ne_set_server_auth to be called
|
||||
* from the neon lib to authenticate a request.
|
||||
*/
|
||||
static int ne_auth( void *userdata, const char *realm, int attempt,
|
||||
static int authentication_callback_by_neon( void *userdata, const char *realm, int attempt,
|
||||
char *username, char *password)
|
||||
{
|
||||
char buf[NE_ABUFSIZ];
|
||||
csync_auth_callback authcb = NULL;
|
||||
int re = attempt;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
|
||||
(void) userdata;
|
||||
(void) realm;
|
||||
|
||||
/* DEBUG_WEBDAV( "Authentication required %s", realm ); */
|
||||
if( username && password ) {
|
||||
DEBUG_WEBDAV( "Authentication required %s", username );
|
||||
if( dav_session.user ) {
|
||||
if( ctx->dav_session.user ) {
|
||||
/* allow user without password */
|
||||
if( strlen( dav_session.user ) < NE_ABUFSIZ ) {
|
||||
strcpy( username, dav_session.user );
|
||||
if( strlen( ctx->dav_session.user ) < NE_ABUFSIZ ) {
|
||||
strcpy( username, ctx->dav_session.user );
|
||||
}
|
||||
if( dav_session.pwd && strlen( dav_session.pwd ) < NE_ABUFSIZ ) {
|
||||
strcpy( password, dav_session.pwd );
|
||||
if( ctx->dav_session.pwd && strlen( ctx->dav_session.pwd ) < NE_ABUFSIZ ) {
|
||||
strcpy( password, ctx->dav_session.pwd );
|
||||
}
|
||||
} else {
|
||||
if( dav_session.csync_ctx ) {
|
||||
authcb = csync_get_auth_callback( dav_session.csync_ctx );
|
||||
}
|
||||
authcb = csync_get_auth_callback( ctx->csync_ctx );
|
||||
if( authcb != NULL ){
|
||||
/* call the csync callback */
|
||||
DEBUG_WEBDAV("Call the csync callback for %s", realm );
|
||||
memset( buf, 0, NE_ABUFSIZ );
|
||||
(*authcb) ("Enter your username: ", buf, NE_ABUFSIZ-1, 1, 0, _userdata );
|
||||
(*authcb) ("Enter your username: ", buf, NE_ABUFSIZ-1, 1, 0, csync_get_userdata(ctx->csync_ctx) );
|
||||
if( strlen(buf) < NE_ABUFSIZ ) {
|
||||
strcpy( username, buf );
|
||||
}
|
||||
memset( buf, 0, NE_ABUFSIZ );
|
||||
(*authcb) ("Enter your password: ", buf, NE_ABUFSIZ-1, 0, 0, _userdata );
|
||||
(*authcb) ("Enter your password: ", buf, NE_ABUFSIZ-1, 0, 0, csync_get_userdata(ctx->csync_ctx) );
|
||||
if( strlen(buf) < NE_ABUFSIZ) {
|
||||
strcpy( password, buf );
|
||||
}
|
||||
@@ -235,15 +166,15 @@ static int ne_auth( void *userdata, const char *realm, int attempt,
|
||||
* from the neon lib to authenticate against a proxy. The data to authenticate
|
||||
* against comes from mirall throught vio_module_init function.
|
||||
*/
|
||||
static int ne_proxy_auth( void *userdata, const char *realm, int attempt,
|
||||
static int proxy_authentication_callback_by_neon( void *userdata, const char *realm, int attempt,
|
||||
char *username, char *password)
|
||||
{
|
||||
(void) userdata;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
(void) realm;
|
||||
if( dav_session.proxy_user && strlen( dav_session.proxy_user ) < NE_ABUFSIZ) {
|
||||
strcpy( username, dav_session.proxy_user );
|
||||
if( dav_session.proxy_pwd && strlen( dav_session.proxy_pwd ) < NE_ABUFSIZ) {
|
||||
strcpy( password, dav_session.proxy_pwd );
|
||||
if( ctx->dav_session.proxy_user && strlen( ctx->dav_session.proxy_user ) < NE_ABUFSIZ) {
|
||||
strcpy( username, ctx->dav_session.proxy_user );
|
||||
if( ctx->dav_session.proxy_pwd && strlen( ctx->dav_session.proxy_pwd ) < NE_ABUFSIZ) {
|
||||
strcpy( password, ctx->dav_session.proxy_pwd );
|
||||
}
|
||||
}
|
||||
/* NTLM needs several attempts */
|
||||
@@ -251,42 +182,42 @@ static int ne_proxy_auth( void *userdata, const char *realm, int attempt,
|
||||
}
|
||||
|
||||
/* Configure the proxy depending on the variables */
|
||||
static int configureProxy( ne_session *session )
|
||||
static int configureProxy( csync_owncloud_ctx_t *ctx, ne_session *session )
|
||||
{
|
||||
int port = 8080;
|
||||
int re = -1;
|
||||
|
||||
if( ! session ) return -1;
|
||||
if( ! dav_session.proxy_type ) return 0; /* Go by NoProxy per default */
|
||||
if( ! ctx->dav_session.proxy_type ) return 0; /* Go by NoProxy per default */
|
||||
|
||||
if( dav_session.proxy_port > 0 ) {
|
||||
port = dav_session.proxy_port;
|
||||
if( ctx->dav_session.proxy_port > 0 ) {
|
||||
port = ctx->dav_session.proxy_port;
|
||||
}
|
||||
|
||||
if( c_streq(dav_session.proxy_type, "NoProxy" )) {
|
||||
if( c_streq(ctx->dav_session.proxy_type, "NoProxy" )) {
|
||||
DEBUG_WEBDAV("No proxy configured.");
|
||||
re = 0;
|
||||
} else if( c_streq(dav_session.proxy_type, "DefaultProxy") ||
|
||||
c_streq(dav_session.proxy_type, "HttpProxy") ||
|
||||
c_streq(dav_session.proxy_type, "HttpCachingProxy") ||
|
||||
c_streq(dav_session.proxy_type, "Socks5Proxy")) {
|
||||
} else if( c_streq(ctx->dav_session.proxy_type, "DefaultProxy") ||
|
||||
c_streq(ctx->dav_session.proxy_type, "HttpProxy") ||
|
||||
c_streq(ctx->dav_session.proxy_type, "HttpCachingProxy") ||
|
||||
c_streq(ctx->dav_session.proxy_type, "Socks5Proxy")) {
|
||||
|
||||
if( dav_session.proxy_host ) {
|
||||
DEBUG_WEBDAV("%s at %s:%d", dav_session.proxy_type, dav_session.proxy_host, port );
|
||||
if (c_streq(dav_session.proxy_type, "Socks5Proxy")) {
|
||||
ne_session_socks_proxy(session, NE_SOCK_SOCKSV5, dav_session.proxy_host, port,
|
||||
dav_session.proxy_user, dav_session.proxy_pwd);
|
||||
if( ctx->dav_session.proxy_host ) {
|
||||
DEBUG_WEBDAV("%s at %s:%d", ctx->dav_session.proxy_type, ctx->dav_session.proxy_host, port );
|
||||
if (c_streq(ctx->dav_session.proxy_type, "Socks5Proxy")) {
|
||||
ne_session_socks_proxy(session, NE_SOCK_SOCKSV5, ctx->dav_session.proxy_host, port,
|
||||
ctx->dav_session.proxy_user, ctx->dav_session.proxy_pwd);
|
||||
} else {
|
||||
ne_session_proxy(session, dav_session.proxy_host, port );
|
||||
ne_session_proxy(session, ctx->dav_session.proxy_host, port );
|
||||
}
|
||||
re = 2;
|
||||
} else {
|
||||
DEBUG_WEBDAV("%s requested but no proxy host defined.", dav_session.proxy_type );
|
||||
DEBUG_WEBDAV("%s requested but no proxy host defined.", ctx->dav_session.proxy_type );
|
||||
/* we used to try ne_system_session_proxy here, but we should rather err out
|
||||
to behave exactly like the caller. */
|
||||
}
|
||||
} else {
|
||||
DEBUG_WEBDAV( "Unsupported Proxy: %s", dav_session.proxy_type );
|
||||
DEBUG_WEBDAV( "Unsupported Proxy: %s", ctx->dav_session.proxy_type );
|
||||
}
|
||||
|
||||
return re;
|
||||
@@ -303,9 +234,9 @@ static void post_request_hook(ne_request *req, void *userdata, const ne_status *
|
||||
const char *sc = NULL;
|
||||
char *key = NULL;
|
||||
|
||||
(void) userdata;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
|
||||
if (dav_session.session_key)
|
||||
if (ctx->dav_session.session_key)
|
||||
return; /* We already have a session cookie, and we should ignore other ones */
|
||||
|
||||
if(!(status && req)) return;
|
||||
@@ -373,8 +304,8 @@ static void post_request_hook(ne_request *req, void *userdata, const ne_status *
|
||||
}
|
||||
if( key ) {
|
||||
DEBUG_WEBDAV("----> Session-key: %s", key);
|
||||
SAFE_FREE(dav_session.session_key);
|
||||
dav_session.session_key = key;
|
||||
SAFE_FREE(ctx->dav_session.session_key);
|
||||
ctx->dav_session.session_key = key;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,13 +316,14 @@ static void post_request_hook(ne_request *req, void *userdata, const ne_status *
|
||||
static void request_created_hook(ne_request *req, void *userdata,
|
||||
const char *method, const char *requri)
|
||||
{
|
||||
(void) userdata;
|
||||
// FIXME Can possibly be merged with pre_send_hook
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t *) userdata;
|
||||
(void) method;
|
||||
(void) requri;
|
||||
|
||||
if( !req ) return;
|
||||
|
||||
if(dav_session.proxy_type) {
|
||||
if(ctx->dav_session.proxy_type) {
|
||||
/* required for NTLM */
|
||||
ne_add_request_header(req, "Proxy-Connection", "Keep-Alive");
|
||||
}
|
||||
@@ -404,12 +336,12 @@ static void request_created_hook(ne_request *req, void *userdata,
|
||||
static void pre_send_hook(ne_request *req, void *userdata,
|
||||
ne_buffer *header)
|
||||
{
|
||||
(void) userdata;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t *) userdata;
|
||||
|
||||
if( !req ) return;
|
||||
|
||||
if(dav_session.session_key) {
|
||||
ne_buffer_concat(header, "Cookie: ", dav_session.session_key, "\r\n", NULL);
|
||||
if(ctx->dav_session.session_key) {
|
||||
ne_buffer_concat(header, "Cookie: ", ctx->dav_session.session_key, "\r\n", NULL);
|
||||
} else {
|
||||
DEBUG_WEBDAV("csync pre_send_hook We don't have a Auth Cookie (session_key), this is wrong!");
|
||||
}
|
||||
@@ -419,16 +351,15 @@ static int post_send_hook(ne_request *req, void *userdata,
|
||||
const ne_status *status)
|
||||
{
|
||||
const char *location;
|
||||
|
||||
(void) userdata;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t *) userdata;
|
||||
(void) status;
|
||||
|
||||
location = ne_get_response_header(req, "Location");
|
||||
|
||||
if( !location ) return NE_OK;
|
||||
|
||||
if( dav_session.redir_callback ) {
|
||||
if( dav_session.redir_callback( dav_session.csync_ctx, location ) ) {
|
||||
if( ctx->dav_session.redir_callback ) {
|
||||
if( ctx->dav_session.redir_callback( ctx->csync_ctx, location ) ) {
|
||||
return NE_REDIRECT;
|
||||
} else {
|
||||
return NE_RETRY;
|
||||
@@ -438,37 +369,12 @@ static int post_send_hook(ne_request *req, void *userdata,
|
||||
return NE_REDIRECT;
|
||||
}
|
||||
|
||||
// as per http://sourceforge.net/p/predef/wiki/OperatingSystems/
|
||||
// extend as required
|
||||
static const char* get_platform() {
|
||||
#if defined (_WIN32)
|
||||
return "Windows";
|
||||
#elif defined(__APPLE__)
|
||||
return "Macintosh";
|
||||
#elif defined(__gnu_linux__)
|
||||
return "Linux";
|
||||
#elif defined(__DragonFly__)
|
||||
/* might also define __FreeBSD__ */
|
||||
return "DragonFlyBSD";
|
||||
#elif defined(__FreeBSD__)
|
||||
return "FreeBSD";
|
||||
#elif defined(__NetBSD__)
|
||||
return "NetBSD";
|
||||
#elif defined(__OpenBSD__)
|
||||
return "OpenBSD";
|
||||
#elif defined(sun) || defined(__sun)
|
||||
return "Solaris";
|
||||
#else
|
||||
return "Unknown OS";
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Connect to a DAV server
|
||||
* This function sets the flag _connected if the connection is established
|
||||
* and returns if the flag is set, so calling it frequently is save.
|
||||
*/
|
||||
static int dav_connect(const char *base_url) {
|
||||
static int dav_connect(csync_owncloud_ctx_t *ctx, const char *base_url) {
|
||||
int useSSL = 0;
|
||||
int rc;
|
||||
char protocol[6] = {'\0'};
|
||||
@@ -479,11 +385,14 @@ static int dav_connect(const char *base_url) {
|
||||
unsigned int port = 0;
|
||||
int proxystate = -1;
|
||||
|
||||
if (_connected) {
|
||||
if (ctx->_connected) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = c_parse_uri( base_url, &scheme, &dav_session.user, &dav_session.pwd, &host, &port, &path );
|
||||
rc = c_parse_uri( base_url, &scheme,
|
||||
&ctx->dav_session.user,
|
||||
&ctx->dav_session.pwd,
|
||||
&host, &port, &path );
|
||||
if( rc < 0 ) {
|
||||
DEBUG_WEBDAV("Failed to parse uri %s", base_url );
|
||||
goto out;
|
||||
@@ -505,29 +414,31 @@ static int dav_connect(const char *base_url) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
DEBUG_WEBDAV("* user %s", dav_session.user ? dav_session.user : "");
|
||||
DEBUG_WEBDAV("* user %s", ctx->dav_session.user ? ctx->dav_session.user : "");
|
||||
|
||||
if (port == 0) {
|
||||
port = ne_uri_defaultport(protocol);
|
||||
}
|
||||
|
||||
dav_session.ctx = ne_session_create( protocol, host, port);
|
||||
ctx->dav_session.ctx = ne_session_create( protocol, host, port);
|
||||
|
||||
if (dav_session.ctx == NULL) {
|
||||
if (ctx->dav_session.ctx == NULL) {
|
||||
DEBUG_WEBDAV("Session create with protocol %s failed", protocol );
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dav_session.read_timeout != 0) {
|
||||
ne_set_read_timeout(dav_session.ctx, dav_session.read_timeout);
|
||||
DEBUG_WEBDAV("Timeout set to %u seconds", dav_session.read_timeout );
|
||||
if (ctx->dav_session.read_timeout != 0) {
|
||||
ne_set_read_timeout(ctx->dav_session.ctx, ctx->dav_session.read_timeout);
|
||||
DEBUG_WEBDAV("Timeout set to %u seconds", ctx->dav_session.read_timeout );
|
||||
}
|
||||
// Should never take more than some seconds, 30 is really a max.
|
||||
ne_set_connect_timeout(ctx->dav_session.ctx, 30);
|
||||
|
||||
snprintf( uaBuf, sizeof(uaBuf), "Mozilla/5.0 (%s) csyncoC/%s",
|
||||
get_platform(), CSYNC_STRINGIFY( LIBCSYNC_VERSION ));
|
||||
ne_set_useragent( dav_session.ctx, uaBuf);
|
||||
ne_set_server_auth(dav_session.ctx, ne_auth, 0 );
|
||||
csync_owncloud_get_platform(), CSYNC_STRINGIFY( LIBCSYNC_VERSION ));
|
||||
ne_set_useragent( ctx->dav_session.ctx, uaBuf);
|
||||
ne_set_server_auth(ctx->dav_session.ctx, authentication_callback_by_neon, ctx);
|
||||
|
||||
if( useSSL ) {
|
||||
if (!ne_has_support(NE_FEATURE_SSL)) {
|
||||
@@ -536,28 +447,28 @@ static int dav_connect(const char *base_url) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ne_ssl_trust_default_ca( dav_session.ctx );
|
||||
ne_ssl_set_verify( dav_session.ctx, verify_sslcert, 0 );
|
||||
ne_ssl_trust_default_ca( ctx->dav_session.ctx );
|
||||
ne_ssl_set_verify( ctx->dav_session.ctx, ssl_callback_by_neon, ctx);
|
||||
}
|
||||
|
||||
/* Hook called when a request is created. It sets the proxy connection header. */
|
||||
ne_hook_create_request( dav_session.ctx, request_created_hook, NULL );
|
||||
ne_hook_create_request( ctx->dav_session.ctx, request_created_hook, ctx );
|
||||
/* Hook called after response headers are read. It gets the Session ID. */
|
||||
ne_hook_post_headers( dav_session.ctx, post_request_hook, NULL );
|
||||
ne_hook_post_headers( ctx->dav_session.ctx, post_request_hook, ctx );
|
||||
/* Hook called before a request is sent. It sets the cookies. */
|
||||
ne_hook_pre_send( dav_session.ctx, pre_send_hook, NULL );
|
||||
ne_hook_pre_send( ctx->dav_session.ctx, pre_send_hook, ctx );
|
||||
/* Hook called after request is dispatched. Used for handling possible redirections. */
|
||||
ne_hook_post_send( dav_session.ctx, post_send_hook, NULL );
|
||||
ne_hook_post_send( ctx->dav_session.ctx, post_send_hook, ctx );
|
||||
|
||||
/* Proxy support */
|
||||
proxystate = configureProxy( dav_session.ctx );
|
||||
proxystate = configureProxy( ctx, ctx->dav_session.ctx );
|
||||
if( proxystate < 0 ) {
|
||||
DEBUG_WEBDAV("Error: Proxy-Configuration failed.");
|
||||
} else if( proxystate > 0 ) {
|
||||
ne_set_proxy_auth( dav_session.ctx, ne_proxy_auth, 0 );
|
||||
ne_set_proxy_auth( ctx->dav_session.ctx, proxy_authentication_callback_by_neon, ctx );
|
||||
}
|
||||
|
||||
_connected = 1;
|
||||
ctx->_connected = 1;
|
||||
rc = 0;
|
||||
out:
|
||||
SAFE_FREE(path);
|
||||
@@ -573,24 +484,16 @@ out:
|
||||
* and fills a resource struct and stores it to the result list which
|
||||
* is stored in the listdir_context.
|
||||
*/
|
||||
static void results(void *userdata,
|
||||
static void propfind_results_callback(void *userdata,
|
||||
const ne_uri *uri,
|
||||
const ne_prop_result_set *set)
|
||||
{
|
||||
struct listdir_context *fetchCtx = userdata;
|
||||
struct resource *newres = 0;
|
||||
const char *clength, *modtime = NULL;
|
||||
const char *resourcetype = NULL;
|
||||
const char *md5sum = NULL;
|
||||
const char *file_id = NULL;
|
||||
const ne_status *status = NULL;
|
||||
char *path = ne_path_unescape( uri->path );
|
||||
|
||||
(void) status;
|
||||
if( ! fetchCtx ) {
|
||||
DEBUG_WEBDAV("No valid fetchContext");
|
||||
return;
|
||||
}
|
||||
|
||||
if( ! fetchCtx->target ) {
|
||||
DEBUG_WEBDAV("error: target must not be zero!" );
|
||||
@@ -599,37 +502,9 @@ static void results(void *userdata,
|
||||
|
||||
/* Fill the resource structure with the data about the file */
|
||||
newres = c_malloc(sizeof(struct resource));
|
||||
ZERO_STRUCTP(newres);
|
||||
newres->uri = path; /* no need to strdup because ne_path_unescape already allocates */
|
||||
newres->name = c_basename( path );
|
||||
|
||||
modtime = ne_propset_value( set, &ls_props[0] );
|
||||
clength = ne_propset_value( set, &ls_props[1] );
|
||||
resourcetype = ne_propset_value( set, &ls_props[2] );
|
||||
md5sum = ne_propset_value( set, &ls_props[3] );
|
||||
file_id = ne_propset_value( set, &ls_props[4] );
|
||||
|
||||
newres->type = resr_normal;
|
||||
if( clength == NULL && resourcetype && strncmp( resourcetype, "<DAV:collection>", 16 ) == 0) {
|
||||
newres->type = resr_collection;
|
||||
}
|
||||
|
||||
if (modtime) {
|
||||
newres->modtime = oc_httpdate_parse(modtime);
|
||||
}
|
||||
|
||||
/* DEBUG_WEBDAV("Parsing Modtime: %s -> %llu", modtime, (unsigned long long) newres->modtime ); */
|
||||
newres->size = 0;
|
||||
if (clength) {
|
||||
newres->size = atoll(clength);
|
||||
/* DEBUG_WEBDAV("Parsed File size for %s from %s: %lld", newres->name, clength, (long long)newres->size ); */
|
||||
}
|
||||
|
||||
if( md5sum ) {
|
||||
newres->md5 = csync_normalize_etag(md5sum);
|
||||
}
|
||||
|
||||
csync_vio_set_file_id(newres->file_id, file_id);
|
||||
fill_webdav_properties_into_resource(newres, set);
|
||||
|
||||
/* prepend the new resource to the result list */
|
||||
newres->next = fetchCtx->list;
|
||||
@@ -643,7 +518,7 @@ static void results(void *userdata,
|
||||
/*
|
||||
* fetches a resource list from the WebDAV server. This is equivalent to list dir.
|
||||
*/
|
||||
static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
||||
static struct listdir_context *fetch_resource_list(csync_owncloud_ctx_t *ctx, const char *uri, int depth)
|
||||
{
|
||||
struct listdir_context *fetchCtx;
|
||||
int ret = 0;
|
||||
@@ -657,15 +532,20 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
||||
|
||||
/* The old legacy one-level PROPFIND cache. Also gets filled
|
||||
by the recursive cache if 'infinity' did not suceed. */
|
||||
if (propfind_cache) {
|
||||
if (c_streq(curi, propfind_cache->target)) {
|
||||
if (ctx->propfind_cache) {
|
||||
if (c_streq(curi, ctx->propfind_cache->target)) {
|
||||
DEBUG_WEBDAV("fetch_resource_list Using simple PROPFIND cache %s", curi);
|
||||
propfind_cache->ref++;
|
||||
ctx->propfind_cache->ref++;
|
||||
SAFE_FREE(curi);
|
||||
return propfind_cache;
|
||||
return ctx->propfind_cache;
|
||||
}
|
||||
}
|
||||
|
||||
if( ctx->csync_ctx->callbacks.update_callback ) {
|
||||
ctx->csync_ctx->callbacks.update_callback(false, curi,
|
||||
ctx->csync_ctx->callbacks.update_callback_userdata);
|
||||
}
|
||||
|
||||
fetchCtx = c_malloc( sizeof( struct listdir_context ));
|
||||
if (!fetchCtx) {
|
||||
errno = ENOMEM;
|
||||
@@ -678,10 +558,10 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
||||
fetchCtx->ref = 1;
|
||||
|
||||
/* do a propfind request and parse the results in the results function, set as callback */
|
||||
hdl = ne_propfind_create(dav_session.ctx, curi, depth);
|
||||
hdl = ne_propfind_create(ctx->dav_session.ctx, curi, depth);
|
||||
|
||||
if(hdl) {
|
||||
ret = ne_propfind_named(hdl, ls_props, results, fetchCtx);
|
||||
ret = ne_propfind_named(hdl, ls_props, propfind_results_callback, fetchCtx);
|
||||
request = ne_propfind_get_request( hdl );
|
||||
req_status = ne_get_status( request );
|
||||
}
|
||||
@@ -694,14 +574,14 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
||||
DEBUG_WEBDAV("ERROR: Request failed: status %d (%s)", req_status->code,
|
||||
req_status->reason_phrase);
|
||||
ret = NE_CONNECT;
|
||||
set_error_message(req_status->reason_phrase);
|
||||
set_error_message(ctx, req_status->reason_phrase);
|
||||
}
|
||||
DEBUG_WEBDAV("Simple propfind result code %d.", req_status ? req_status->code : -1);
|
||||
} else {
|
||||
if( ret == NE_ERROR && req_status->code == 404) {
|
||||
errno = ENOENT;
|
||||
} else {
|
||||
set_errno_from_neon_errcode(ret);
|
||||
set_errno_from_neon_errcode(ctx, ret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -716,18 +596,18 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
||||
DEBUG_WEBDAV("ERROR: Content type of propfind request not XML: %s.",
|
||||
content_type ? content_type: "<empty>");
|
||||
errno = ERRNO_WRONG_CONTENT;
|
||||
set_error_message("Server error: PROPFIND reply is not XML formatted!");
|
||||
set_error_message(ctx, "Server error: PROPFIND reply is not XML formatted!");
|
||||
ret = NE_CONNECT;
|
||||
}
|
||||
}
|
||||
|
||||
if( ret != NE_OK ) {
|
||||
const char *err = NULL;
|
||||
set_errno_from_neon_errcode(ret);
|
||||
set_errno_from_neon_errcode(ctx, ret);
|
||||
|
||||
err = ne_get_error( dav_session.ctx );
|
||||
err = ne_get_error( ctx->dav_session.ctx );
|
||||
if(err) {
|
||||
set_error_message(err);
|
||||
set_error_message(ctx, err);
|
||||
}
|
||||
DEBUG_WEBDAV("WRN: propfind named failed with %d, request error: %s", ret, err ? err : "<nil>");
|
||||
}
|
||||
@@ -740,19 +620,19 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free_fetchCtx(propfind_cache);
|
||||
propfind_cache = fetchCtx;
|
||||
propfind_cache->ref++;
|
||||
free_fetchCtx(ctx->propfind_cache);
|
||||
ctx->propfind_cache = fetchCtx;
|
||||
ctx->propfind_cache->ref++;
|
||||
return fetchCtx;
|
||||
}
|
||||
|
||||
static struct listdir_context *fetch_resource_list_attempts(const char *uri, int depth)
|
||||
static struct listdir_context *fetch_resource_list_attempts(csync_owncloud_ctx_t *ctx, const char *uri, int depth)
|
||||
{
|
||||
int i;
|
||||
|
||||
struct listdir_context *fetchCtx = NULL;
|
||||
for(i = 0; i < 10; ++i) {
|
||||
fetchCtx = fetch_resource_list(uri, depth);
|
||||
fetchCtx = fetch_resource_list(ctx, uri, depth);
|
||||
if(fetchCtx) break;
|
||||
/* only loop in case the content is not XML formatted. Otherwise for every
|
||||
* non successful stat (for non existing directories) its tried 10 times. */
|
||||
@@ -764,165 +644,39 @@ static struct listdir_context *fetch_resource_list_attempts(const char *uri, int
|
||||
return fetchCtx;
|
||||
}
|
||||
|
||||
static void fill_stat_cache( csync_vio_file_stat_t *lfs ) {
|
||||
|
||||
if( _stat_cache.name ) SAFE_FREE(_stat_cache.name);
|
||||
if( _stat_cache.etag ) SAFE_FREE(_stat_cache.etag );
|
||||
|
||||
if( !lfs) return;
|
||||
|
||||
_stat_cache.name = c_strdup(lfs->name);
|
||||
_stat_cache.mtime = lfs->mtime;
|
||||
_stat_cache.fields = lfs->fields;
|
||||
_stat_cache.type = lfs->type;
|
||||
_stat_cache.size = lfs->size;
|
||||
csync_vio_file_stat_set_file_id(&_stat_cache, lfs->file_id);
|
||||
|
||||
if( lfs->etag ) {
|
||||
_stat_cache.etag = c_strdup(lfs->etag);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* file functions
|
||||
*/
|
||||
int owncloud_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
/* get props:
|
||||
* modtime
|
||||
* creattime
|
||||
* size
|
||||
*/
|
||||
csync_vio_file_stat_t *lfs = NULL;
|
||||
struct listdir_context *fetchCtx = NULL;
|
||||
char *decodedUri = NULL;
|
||||
int len = 0;
|
||||
errno = 0;
|
||||
|
||||
buf->name = c_basename(uri);
|
||||
|
||||
if (buf->name == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( _stat_cache.name && strcmp( buf->name, _stat_cache.name ) == 0 ) {
|
||||
buf->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS;
|
||||
buf->fields = _stat_cache.fields;
|
||||
buf->type = _stat_cache.type;
|
||||
buf->mtime = _stat_cache.mtime;
|
||||
buf->size = _stat_cache.size;
|
||||
buf->mode = _stat_perms( _stat_cache.type );
|
||||
buf->etag = NULL;
|
||||
if( _stat_cache.etag ) {
|
||||
buf->etag = c_strdup( _stat_cache.etag );
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG;
|
||||
}
|
||||
csync_vio_file_stat_set_file_id( buf, _stat_cache.file_id );
|
||||
return 0;
|
||||
}
|
||||
DEBUG_WEBDAV("owncloud_stat => Could not find in stat cache %s", uri);
|
||||
|
||||
/* fetch data via a propfind call. */
|
||||
/* fetchCtx = fetch_resource_list( uri, NE_DEPTH_ONE); */
|
||||
fetchCtx = fetch_resource_list_attempts( uri, NE_DEPTH_ONE);
|
||||
DEBUG_WEBDAV("=> Errno after fetch resource list for %s: %d", uri, errno);
|
||||
if (!fetchCtx) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( fetchCtx ) {
|
||||
struct resource *res = fetchCtx->list;
|
||||
while( res ) {
|
||||
/* remove trailing slashes */
|
||||
len = strlen(res->uri);
|
||||
while( len > 0 && res->uri[len-1] == '/' ) --len;
|
||||
decodedUri = ne_path_unescape( fetchCtx->target ); /* allocates memory */
|
||||
|
||||
/* Only do the comparaison of the part of the string without the trailing
|
||||
slashes, and make sure decodedUri is not too large */
|
||||
if( strncmp(res->uri, decodedUri, len ) == 0 && decodedUri[len] == '\0') {
|
||||
SAFE_FREE( decodedUri );
|
||||
break;
|
||||
}
|
||||
res = res->next;
|
||||
SAFE_FREE( decodedUri );
|
||||
}
|
||||
if( res ) {
|
||||
DEBUG_WEBDAV("Working on file %s", res->name );
|
||||
} else {
|
||||
DEBUG_WEBDAV("ERROR: Result struct not valid!");
|
||||
}
|
||||
|
||||
lfs = resourceToFileStat( res );
|
||||
if( lfs ) {
|
||||
buf->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG;
|
||||
|
||||
buf->fields = lfs->fields;
|
||||
buf->type = lfs->type;
|
||||
buf->mtime = lfs->mtime;
|
||||
buf->size = lfs->size;
|
||||
buf->mode = _stat_perms( lfs->type );
|
||||
buf->etag = NULL;
|
||||
if( lfs->etag ) {
|
||||
buf->etag = c_strdup( lfs->etag );
|
||||
}
|
||||
csync_vio_file_stat_set_file_id( buf, lfs->file_id );
|
||||
|
||||
/* fill the static stat buf as input for the stat function */
|
||||
csync_vio_file_stat_destroy( lfs );
|
||||
}
|
||||
|
||||
free_fetchCtx( fetchCtx );
|
||||
}
|
||||
DEBUG_WEBDAV("STAT result from propfind: %s, mtime: %llu", buf->name ? buf->name:"NULL",
|
||||
(unsigned long long) buf->mtime );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* directory functions
|
||||
*/
|
||||
csync_vio_handle_t *owncloud_opendir(const char *uri) {
|
||||
csync_vio_handle_t *owncloud_opendir(CSYNC *ctx, const char *uri) {
|
||||
struct listdir_context *fetchCtx = NULL;
|
||||
char *curi = NULL;
|
||||
|
||||
DEBUG_WEBDAV("opendir method called on %s", uri );
|
||||
|
||||
if (dav_connect( uri ) < 0) {
|
||||
if (dav_connect( ctx->owncloud_context, uri ) < 0) {
|
||||
DEBUG_WEBDAV("connection failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
curi = _cleanPath( uri );
|
||||
if (is_first_propfind && !dav_session.no_recursive_propfind) {
|
||||
is_first_propfind = false;
|
||||
if (ctx->owncloud_context->is_first_propfind && !ctx->owncloud_context->dav_session.no_recursive_propfind) {
|
||||
ctx->owncloud_context->is_first_propfind = false;
|
||||
// Try to fill it
|
||||
fill_recursive_propfind_cache(uri, curi);
|
||||
fill_recursive_propfind_cache(ctx->owncloud_context, uri, curi);
|
||||
}
|
||||
if (propfind_recursive_cache) {
|
||||
if (ctx->owncloud_context->propfind_recursive_cache) {
|
||||
// Try to fetch from recursive cache (if we have one)
|
||||
fetchCtx = get_listdir_context_from_recursive_cache(curi);
|
||||
fetchCtx = get_listdir_context_from_recursive_cache(ctx->owncloud_context, curi);
|
||||
}
|
||||
SAFE_FREE(curi);
|
||||
is_first_propfind = false;
|
||||
ctx->owncloud_context->is_first_propfind = false;
|
||||
if (fetchCtx) {
|
||||
return fetchCtx;
|
||||
}
|
||||
|
||||
/* fetchCtx = fetch_resource_list( uri, NE_DEPTH_ONE ); */
|
||||
fetchCtx = fetch_resource_list_attempts( uri, NE_DEPTH_ONE);
|
||||
fetchCtx = fetch_resource_list_attempts( ctx->owncloud_context, uri, NE_DEPTH_ONE);
|
||||
if( !fetchCtx ) {
|
||||
/* errno is set properly in fetch_resource_list */
|
||||
DEBUG_WEBDAV("Errno set to %d", errno);
|
||||
@@ -935,17 +689,16 @@ csync_vio_handle_t *owncloud_opendir(const char *uri) {
|
||||
/* no freeing of curi because its part of the fetchCtx and gets freed later */
|
||||
}
|
||||
|
||||
int owncloud_closedir(csync_vio_handle_t *dhandle) {
|
||||
|
||||
int owncloud_closedir(CSYNC *ctx, csync_vio_handle_t *dhandle) {
|
||||
struct listdir_context *fetchCtx = dhandle;
|
||||
|
||||
free_fetchCtx(fetchCtx);
|
||||
|
||||
(void)ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
csync_vio_file_stat_t *owncloud_readdir(csync_vio_handle_t *dhandle) {
|
||||
csync_vio_file_stat_t *owncloud_readdir(CSYNC *ctx, csync_vio_handle_t *dhandle) {
|
||||
struct listdir_context *fetchCtx = dhandle;
|
||||
(void)ctx;
|
||||
|
||||
// DEBUG_WEBDAV("owncloud_readdir" );
|
||||
// DEBUG_WEBDAV("owncloud_readdir %s ", fetchCtx->target);
|
||||
@@ -971,8 +724,10 @@ csync_vio_file_stat_t *owncloud_readdir(csync_vio_handle_t *dhandle) {
|
||||
*/
|
||||
escaped_path = ne_path_escape( currResource->uri );
|
||||
if (ne_path_compare(fetchCtx->target, escaped_path) != 0) {
|
||||
csync_vio_file_stat_t* lfs = resourceToFileStat(currResource);
|
||||
fill_stat_cache(lfs);
|
||||
// Convert the resource for the caller
|
||||
csync_vio_file_stat_t* lfs = csync_vio_file_stat_new();
|
||||
resourceToFileStat(lfs, currResource);
|
||||
|
||||
SAFE_FREE( escaped_path );
|
||||
return lfs;
|
||||
}
|
||||
@@ -984,39 +739,56 @@ csync_vio_file_stat_t *owncloud_readdir(csync_vio_handle_t *dhandle) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *owncloud_error_string(void)
|
||||
char *owncloud_error_string(CSYNC* ctx)
|
||||
{
|
||||
return dav_session.error_string;
|
||||
return ctx->owncloud_context->dav_session.error_string;
|
||||
}
|
||||
|
||||
int owncloud_commit(void) {
|
||||
int owncloud_commit(CSYNC* ctx) {
|
||||
if (!ctx->owncloud_context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
clean_caches();
|
||||
clear_propfind_recursive_cache(ctx->owncloud_context);
|
||||
|
||||
if( dav_session.ctx ) {
|
||||
ne_forget_auth(dav_session.ctx);
|
||||
ne_session_destroy( dav_session.ctx );
|
||||
}
|
||||
free_fetchCtx(ctx->owncloud_context->propfind_cache);
|
||||
ctx->owncloud_context->propfind_cache = NULL;
|
||||
|
||||
if( ctx->owncloud_context->dav_session.ctx ) {
|
||||
ne_forget_auth(ctx->owncloud_context->dav_session.ctx);
|
||||
ne_session_destroy(ctx->owncloud_context->dav_session.ctx );
|
||||
ctx->owncloud_context->dav_session.ctx = 0;
|
||||
}
|
||||
|
||||
ctx->owncloud_context->is_first_propfind = true;
|
||||
ctx->owncloud_context->dav_session.no_recursive_propfind = true;
|
||||
/* DEBUG_WEBDAV( "********** vio_module_shutdown" ); */
|
||||
|
||||
dav_session.ctx = 0;
|
||||
ctx->owncloud_context->dav_session.ctx = 0;
|
||||
|
||||
// ne_sock_exit();
|
||||
_connected = 0; /* triggers dav_connect to go through the whole neon setup */
|
||||
ctx->owncloud_context->_connected = 0; /* triggers dav_connect to go through the whole neon setup */
|
||||
|
||||
SAFE_FREE( dav_session.user );
|
||||
SAFE_FREE( dav_session.pwd );
|
||||
SAFE_FREE( dav_session.session_key);
|
||||
SAFE_FREE( dav_session.error_string );
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.user );
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.pwd );
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.session_key);
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.error_string );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int owncloud_set_property(const char *key, void *data) {
|
||||
void owncloud_destroy(CSYNC* ctx)
|
||||
{
|
||||
owncloud_commit(ctx);
|
||||
SAFE_FREE(ctx->owncloud_context);
|
||||
ctx->owncloud_context = 0;
|
||||
}
|
||||
|
||||
int owncloud_set_property(CSYNC* ctx, const char *key, void *data) {
|
||||
#define READ_STRING_PROPERTY(P) \
|
||||
if (c_streq(key, #P)) { \
|
||||
SAFE_FREE(dav_session.P); \
|
||||
dav_session.P = c_strdup((const char*)data); \
|
||||
SAFE_FREE(ctx->owncloud_context->dav_session.P); \
|
||||
ctx->owncloud_context->dav_session.P = c_strdup((const char*)data); \
|
||||
return 0; \
|
||||
}
|
||||
READ_STRING_PROPERTY(session_key)
|
||||
@@ -1027,48 +799,43 @@ int owncloud_set_property(const char *key, void *data) {
|
||||
#undef READ_STRING_PROPERTY
|
||||
|
||||
if (c_streq(key, "proxy_port")) {
|
||||
dav_session.proxy_port = *(int*)(data);
|
||||
ctx->owncloud_context->dav_session.proxy_port = *(int*)(data);
|
||||
return 0;
|
||||
}
|
||||
if (c_streq(key, "read_timeout") || c_streq(key, "timeout")) {
|
||||
dav_session.read_timeout = *(int*)(data);
|
||||
return 0;
|
||||
}
|
||||
if( c_streq(key, "csync_context")) {
|
||||
dav_session.csync_ctx = data;
|
||||
ctx->owncloud_context->dav_session.read_timeout = *(int*)(data);
|
||||
return 0;
|
||||
}
|
||||
if( c_streq(key, "get_dav_session")) {
|
||||
/* Give the ne_session to the caller */
|
||||
*(ne_session**)data = dav_session.ctx;
|
||||
*(ne_session**)data = ctx->owncloud_context->dav_session.ctx;
|
||||
return 0;
|
||||
}
|
||||
if( c_streq(key, "no_recursive_propfind")) {
|
||||
dav_session.no_recursive_propfind = *(bool*)(data);
|
||||
ctx->owncloud_context->dav_session.no_recursive_propfind = *(bool*)(data);
|
||||
return 0;
|
||||
}
|
||||
if( c_streq(key, "redirect_callback")) {
|
||||
if (data) {
|
||||
csync_owncloud_redirect_callback_t* cb_wrapper = data;
|
||||
|
||||
dav_session.redir_callback = *cb_wrapper;
|
||||
ctx->owncloud_context->dav_session.redir_callback = *cb_wrapper;
|
||||
} else {
|
||||
dav_session.redir_callback = NULL;
|
||||
ctx->owncloud_context->dav_session.redir_callback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void owncloud_init(void *userdata) {
|
||||
void owncloud_init(CSYNC* ctx) {
|
||||
|
||||
_userdata = userdata;
|
||||
_connected = 0; /* triggers dav_connect to go through the whole neon setup */
|
||||
|
||||
memset(&dav_session, 0, sizeof(dav_session));
|
||||
ctx->owncloud_context = c_malloc( sizeof( struct csync_owncloud_ctx_s ));
|
||||
ctx->owncloud_context->csync_ctx = ctx; // back reference
|
||||
ctx->owncloud_context->is_first_propfind = true;
|
||||
|
||||
/* Disable it, Mirall can enable it for the first sync (= no DB)*/
|
||||
dav_session.no_recursive_propfind = true;
|
||||
ctx->owncloud_context->dav_session.no_recursive_propfind = true;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et cindent: */
|
||||
|
||||
@@ -21,159 +21,18 @@
|
||||
#ifndef CSYNC_OWNCLOUD_H
|
||||
#define CSYNC_OWNCLOUD_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "config_csync.h"
|
||||
#ifdef NEON_WITH_LFS /* Switch on LFS in libneon. Never remove the NE_LFS! */
|
||||
#define NE_LFS
|
||||
#endif
|
||||
|
||||
#include <neon/ne_basic.h>
|
||||
#include <neon/ne_socket.h>
|
||||
#include <neon/ne_session.h>
|
||||
#include <neon/ne_request.h>
|
||||
#include <neon/ne_props.h>
|
||||
#include <neon/ne_auth.h>
|
||||
#include <neon/ne_dates.h>
|
||||
#include <neon/ne_compress.h>
|
||||
#include <neon/ne_redirect.h>
|
||||
|
||||
|
||||
#include "c_rbtree.h"
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "csync.h"
|
||||
#include "csync_misc.h"
|
||||
#include "csync_macros.h"
|
||||
#include "c_private.h"
|
||||
#include "httpbf.h"
|
||||
|
||||
#include "vio/csync_vio_file_stat.h"
|
||||
#include "vio/csync_vio.h"
|
||||
|
||||
#include "csync_log.h"
|
||||
|
||||
|
||||
#define DEBUG_WEBDAV(...) csync_log( 9, "oc_module", __VA_ARGS__);
|
||||
|
||||
enum resource_type {
|
||||
resr_normal = 0,
|
||||
resr_collection,
|
||||
resr_reference,
|
||||
resr_error
|
||||
};
|
||||
|
||||
/* Struct to store data for each resource found during an opendir operation.
|
||||
* It represents a single file entry.
|
||||
*/
|
||||
|
||||
typedef struct resource {
|
||||
char *uri; /* The complete uri */
|
||||
char *name; /* The filename only */
|
||||
|
||||
enum resource_type type;
|
||||
int64_t size;
|
||||
time_t modtime;
|
||||
char* md5;
|
||||
char file_id[FILE_ID_BUF_SIZE+1];
|
||||
|
||||
struct resource *next;
|
||||
} resource;
|
||||
|
||||
/* Struct to hold the context of a WebDAV PropFind operation to fetch
|
||||
* a directory listing from the server.
|
||||
*/
|
||||
struct listdir_context {
|
||||
struct resource *list; /* The list of result resources */
|
||||
struct resource *currResource; /* A pointer to the current resource */
|
||||
char *target; /* Request-URI of the PROPFIND */
|
||||
unsigned int result_count; /* number of elements stored in list */
|
||||
int ref; /* reference count, only destroy when it reaches 0 */
|
||||
};
|
||||
|
||||
|
||||
/* Our cache, key is a char* */
|
||||
extern c_rbtree_t *propfind_recursive_cache;
|
||||
/* Values are propfind_recursive_element: */
|
||||
struct propfind_recursive_element {
|
||||
struct resource *self;
|
||||
struct resource *children;
|
||||
struct propfind_recursive_element *parent;
|
||||
};
|
||||
typedef struct propfind_recursive_element propfind_recursive_element_t;
|
||||
void clear_propfind_recursive_cache(void);
|
||||
struct listdir_context *get_listdir_context_from_recursive_cache(const char *curi);
|
||||
void fill_recursive_propfind_cache(const char *uri, const char *curi);
|
||||
struct listdir_context *get_listdir_context_from_cache(const char *curi);
|
||||
void fetch_resource_list_recursive(const char *uri, const char *curi);
|
||||
|
||||
typedef int (*csync_owncloud_redirect_callback_t)(CSYNC* ctx, const char* uri);
|
||||
|
||||
/* Struct with the WebDAV session */
|
||||
struct dav_session_s {
|
||||
ne_session *ctx;
|
||||
char *user;
|
||||
char *pwd;
|
||||
|
||||
char *proxy_type;
|
||||
char *proxy_host;
|
||||
int proxy_port;
|
||||
char *proxy_user;
|
||||
char *proxy_pwd;
|
||||
|
||||
char *session_key;
|
||||
|
||||
char *error_string;
|
||||
|
||||
int read_timeout;
|
||||
|
||||
CSYNC *csync_ctx;
|
||||
|
||||
bool no_recursive_propfind;
|
||||
|
||||
csync_owncloud_redirect_callback_t redir_callback;
|
||||
};
|
||||
extern struct dav_session_s dav_session;
|
||||
|
||||
/* The list of properties that is fetched in PropFind on a collection */
|
||||
static const ne_propname ls_props[] = {
|
||||
{ "DAV:", "getlastmodified" },
|
||||
{ "DAV:", "getcontentlength" },
|
||||
{ "DAV:", "resourcetype" },
|
||||
{ "DAV:", "getetag"},
|
||||
{ "http://owncloud.org/ns", "id"},
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
void set_errno_from_http_errcode( int err );
|
||||
void set_error_message( const char *msg );
|
||||
void set_errno_from_neon_errcode( int neon_code );
|
||||
int http_result_code_from_session(void);
|
||||
void set_errno_from_session(void);
|
||||
|
||||
time_t oc_httpdate_parse( const char *date );
|
||||
|
||||
char *_cleanPath( const char* uri );
|
||||
|
||||
int _stat_perms( int type );
|
||||
csync_vio_file_stat_t *resourceToFileStat( struct resource *res );
|
||||
|
||||
// Public API from vio
|
||||
csync_vio_handle_t *owncloud_opendir(const char *uri);
|
||||
csync_vio_file_stat_t *owncloud_readdir(csync_vio_handle_t *dhandle);
|
||||
int owncloud_closedir(csync_vio_handle_t *dhandle);
|
||||
int owncloud_stat(const char *uri, csync_vio_file_stat_t *buf);
|
||||
int owncloud_commit(void);
|
||||
char *owncloud_error_string(void);
|
||||
void owncloud_init(void *userdata);
|
||||
int owncloud_set_property(const char *key, void *data);
|
||||
// Public API used by csync
|
||||
csync_vio_handle_t *owncloud_opendir(CSYNC* ctx, const char *uri);
|
||||
csync_vio_file_stat_t *owncloud_readdir(CSYNC* ctx, csync_vio_handle_t *dhandle);
|
||||
int owncloud_closedir(CSYNC* ctx, csync_vio_handle_t *dhandle);
|
||||
int owncloud_commit(CSYNC* ctx);
|
||||
void owncloud_destroy(CSYNC* ctx);
|
||||
char *owncloud_error_string(CSYNC* ctx);
|
||||
void owncloud_init(CSYNC* ctx);
|
||||
int owncloud_set_property(CSYNC* ctx, const char *key, void *data);
|
||||
|
||||
#endif /* CSYNC_OWNCLOUD_H */
|
||||
|
||||
201
csync/src/csync_owncloud_private.h
Normal file
201
csync/src/csync_owncloud_private.h
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2011 by Andreas Schneider <asn@cryptomilk.org>
|
||||
* Copyright (c) 2012 by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef CSYNC_OWNCLOUD_PRIVATE_H
|
||||
#define CSYNC_OWNCLOUD_PRIVATE_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "config_csync.h"
|
||||
#ifdef NEON_WITH_LFS /* Switch on LFS in libneon. Never remove the NE_LFS! */
|
||||
#define NE_LFS
|
||||
#endif
|
||||
|
||||
#include <neon/ne_basic.h>
|
||||
#include <neon/ne_socket.h>
|
||||
#include <neon/ne_session.h>
|
||||
#include <neon/ne_request.h>
|
||||
#include <neon/ne_props.h>
|
||||
#include <neon/ne_auth.h>
|
||||
#include <neon/ne_dates.h>
|
||||
#include <neon/ne_compress.h>
|
||||
#include <neon/ne_redirect.h>
|
||||
|
||||
|
||||
#include "c_rbtree.h"
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "csync.h"
|
||||
#include "csync_misc.h"
|
||||
#include "csync_macros.h"
|
||||
#include "c_private.h"
|
||||
#include "httpbf.h"
|
||||
|
||||
#include "vio/csync_vio_file_stat.h"
|
||||
#include "vio/csync_vio.h"
|
||||
|
||||
#include "csync_log.h"
|
||||
|
||||
#include "csync_owncloud.h"
|
||||
|
||||
|
||||
#define DEBUG_WEBDAV(...) csync_log( 9, "oc_module", __VA_ARGS__);
|
||||
|
||||
typedef int (*csync_owncloud_redirect_callback_t)(CSYNC* ctx, const char* uri);
|
||||
|
||||
/* Struct with the WebDAV session */
|
||||
struct dav_session_s {
|
||||
ne_session *ctx;
|
||||
char *user;
|
||||
char *pwd;
|
||||
|
||||
char *proxy_type;
|
||||
char *proxy_host;
|
||||
int proxy_port;
|
||||
char *proxy_user;
|
||||
char *proxy_pwd;
|
||||
|
||||
char *session_key;
|
||||
|
||||
char *error_string;
|
||||
|
||||
int read_timeout;
|
||||
|
||||
bool no_recursive_propfind;
|
||||
|
||||
csync_owncloud_redirect_callback_t redir_callback;
|
||||
};
|
||||
|
||||
struct csync_owncloud_ctx_s {
|
||||
CSYNC *csync_ctx;
|
||||
|
||||
// For the PROPFIND results
|
||||
bool is_first_propfind;
|
||||
struct listdir_context *propfind_cache;
|
||||
c_rbtree_t *propfind_recursive_cache;
|
||||
int propfind_recursive_cache_depth;
|
||||
int propfind_recursive_cache_file_count;
|
||||
int propfind_recursive_cache_folder_count;
|
||||
|
||||
// For the WebDAV connection
|
||||
struct dav_session_s dav_session; /* The DAV Session, initialised in dav_connect */
|
||||
int _connected; /* flag to indicate if a connection exists, ie.
|
||||
the dav_session is valid */
|
||||
};
|
||||
typedef struct csync_owncloud_ctx_s csync_owncloud_ctx_t;
|
||||
//typedef csync_owncloud_ctx_t* csync_owncloud_ctx_p;
|
||||
|
||||
enum resource_type {
|
||||
resr_normal = 0,
|
||||
resr_collection,
|
||||
resr_reference,
|
||||
resr_error
|
||||
};
|
||||
|
||||
/* The list of properties that is fetched in PropFind on a collection */
|
||||
static const ne_propname ls_props[] = {
|
||||
{ "DAV:", "getlastmodified" },
|
||||
{ "DAV:", "getcontentlength" },
|
||||
{ "DAV:", "resourcetype" },
|
||||
{ "DAV:", "getetag"},
|
||||
{ "http://owncloud.org/ns", "id"},
|
||||
{ "http://owncloud.org/ns", "dDU"},
|
||||
{ "http://owncloud.org/ns", "dDC"},
|
||||
{ "http://owncloud.org/ns", "permissions"},
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* Struct to store data for each resource found during an opendir operation.
|
||||
* It represents a single file entry.
|
||||
*/
|
||||
typedef struct resource {
|
||||
char *uri; /* The complete uri */
|
||||
char *name; /* The filename only */
|
||||
|
||||
enum resource_type type;
|
||||
int64_t size;
|
||||
time_t modtime;
|
||||
char* md5;
|
||||
char file_id[FILE_ID_BUF_SIZE+1];
|
||||
// Those two are optional from the server. We can use those URL to download the file directly
|
||||
// without going through the ownCloud instance.
|
||||
char *directDownloadUrl;
|
||||
char *directDownloadCookies;
|
||||
// See https://github.com/owncloud/core/issues/8322
|
||||
char remotePerm[REMOTE_PERM_BUF_SIZE+1];
|
||||
|
||||
struct resource *next;
|
||||
} resource;
|
||||
|
||||
/* Struct to hold the context of a WebDAV PropFind operation to fetch
|
||||
* a directory listing from the server.
|
||||
*/
|
||||
struct listdir_context {
|
||||
struct resource *list; /* The list of result resources */
|
||||
struct resource *currResource; /* A pointer to the current resource */
|
||||
char *target; /* Request-URI of the PROPFIND */
|
||||
unsigned int result_count; /* number of elements stored in list */
|
||||
int ref; /* reference count, only destroy when it reaches 0 */
|
||||
};
|
||||
|
||||
|
||||
/* Values are propfind_recursive_element: */
|
||||
struct propfind_recursive_element {
|
||||
struct resource *self;
|
||||
struct resource *children;
|
||||
struct propfind_recursive_element *parent;
|
||||
};
|
||||
typedef struct propfind_recursive_element propfind_recursive_element_t;
|
||||
|
||||
void clear_propfind_recursive_cache(csync_owncloud_ctx_t *ctx);
|
||||
struct listdir_context *get_listdir_context_from_recursive_cache(csync_owncloud_ctx_t *ctx, const char *curi);
|
||||
void fill_recursive_propfind_cache(csync_owncloud_ctx_t *ctx, const char *uri, const char *curi);
|
||||
struct listdir_context *get_listdir_context_from_cache(csync_owncloud_ctx_t *ctx, const char *curi);
|
||||
void fetch_resource_list_recursive(csync_owncloud_ctx_t *ctx, const char *uri, const char *curi);
|
||||
|
||||
void set_errno_from_http_errcode( int err );
|
||||
void set_error_message( csync_owncloud_ctx_t *ctx, const char *msg );
|
||||
void set_errno_from_neon_errcode(csync_owncloud_ctx_t *ctx, int neon_code );
|
||||
int http_result_code_from_session(csync_owncloud_ctx_t *ctx);
|
||||
void set_errno_from_session(csync_owncloud_ctx_t *ctx);
|
||||
|
||||
time_t oc_httpdate_parse( const char *date );
|
||||
|
||||
char *_cleanPath( const char* uri );
|
||||
|
||||
void fill_webdav_properties_into_resource(struct resource* newres, const ne_prop_result_set *set);
|
||||
|
||||
void resourceToFileStat( csync_vio_file_stat_t *lfs, struct resource *res );
|
||||
void resource_free(struct resource* o);
|
||||
struct resource* resource_dup(struct resource* o);
|
||||
void free_fetchCtx( struct listdir_context *ctx );
|
||||
|
||||
const char* csync_owncloud_get_platform(void);
|
||||
|
||||
#endif // CSYNC_OWNCLOUD_PRIVATE_H
|
||||
@@ -20,42 +20,7 @@
|
||||
*/
|
||||
|
||||
#include "csync_owncloud.h"
|
||||
|
||||
c_rbtree_t *propfind_recursive_cache = NULL;
|
||||
int propfind_recursive_cache_depth = 0;
|
||||
int propfind_recursive_cache_file_count = 0;
|
||||
int propfind_recursive_cache_folder_count = 0;
|
||||
|
||||
|
||||
static struct resource* resource_dup(struct resource* o) {
|
||||
struct resource *r = c_malloc (sizeof( struct resource ));
|
||||
ZERO_STRUCTP(r);
|
||||
|
||||
r->uri = c_strdup(o->uri);
|
||||
r->name = c_strdup(o->name);
|
||||
r->type = o->type;
|
||||
r->size = o->size;
|
||||
r->modtime = o->modtime;
|
||||
if( o->md5 ) {
|
||||
r->md5 = c_strdup(o->md5);
|
||||
}
|
||||
r->next = o->next;
|
||||
csync_vio_set_file_id(r->file_id, o->file_id);
|
||||
|
||||
return r;
|
||||
}
|
||||
static void resource_free(struct resource* o) {
|
||||
struct resource* old = NULL;
|
||||
while (o)
|
||||
{
|
||||
old = o;
|
||||
o = o->next;
|
||||
SAFE_FREE(old->uri);
|
||||
SAFE_FREE(old->name);
|
||||
SAFE_FREE(old->md5);
|
||||
SAFE_FREE(old);
|
||||
}
|
||||
}
|
||||
#include "csync_owncloud_private.h"
|
||||
|
||||
static void _tree_destructor(void *data) {
|
||||
propfind_recursive_element_t *element = data;
|
||||
@@ -64,31 +29,34 @@ static void _tree_destructor(void *data) {
|
||||
SAFE_FREE(element);
|
||||
}
|
||||
|
||||
void clear_propfind_recursive_cache(void)
|
||||
void clear_propfind_recursive_cache(csync_owncloud_ctx_t *ctx)
|
||||
{
|
||||
if (propfind_recursive_cache) {
|
||||
if (ctx->propfind_recursive_cache) {
|
||||
DEBUG_WEBDAV("clear_propfind_recursive_cache Invalidating..");
|
||||
c_rbtree_destroy(propfind_recursive_cache, _tree_destructor);
|
||||
propfind_recursive_cache = NULL;
|
||||
c_rbtree_destroy(ctx->propfind_recursive_cache, _tree_destructor);
|
||||
ctx->propfind_recursive_cache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct listdir_context *get_listdir_context_from_recursive_cache(const char *curi)
|
||||
struct listdir_context *get_listdir_context_from_recursive_cache(csync_owncloud_ctx_t *ctx, const char *curi)
|
||||
{
|
||||
propfind_recursive_element_t *element = NULL;
|
||||
struct listdir_context *fetchCtx = NULL;
|
||||
struct resource *iterator, *r;
|
||||
|
||||
if (!propfind_recursive_cache) {
|
||||
if (!ctx->propfind_recursive_cache) {
|
||||
DEBUG_WEBDAV("get_listdir_context_from_recursive_cache No cache");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
element = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache, curi));
|
||||
element = c_rbtree_node_data(c_rbtree_find(ctx->propfind_recursive_cache, curi));
|
||||
if (!element) {
|
||||
DEBUG_WEBDAV("get_listdir_context_from_recursive_cache No element %s in cache found", curi);
|
||||
return NULL;
|
||||
}
|
||||
if( ctx->csync_ctx->callbacks.update_callback ) {
|
||||
ctx->csync_ctx->callbacks.update_callback(false, curi, ctx->csync_ctx->callbacks.update_callback_userdata);
|
||||
}
|
||||
|
||||
/* Out of the element, create a listdir_context.. if we could be sure that it is immutable, we could ref instead.. need to investigate */
|
||||
fetchCtx = c_malloc( sizeof( struct listdir_context ));
|
||||
@@ -128,84 +96,62 @@ static int _data_cmp(const void *a, const void *b) {
|
||||
const propfind_recursive_element_t *elementB = b;
|
||||
return ne_path_compare(elementA->self->uri, elementB->self->uri);
|
||||
}
|
||||
static void propfind_results_recursive(void *userdata,
|
||||
static void propfind_results_recursive_callback(void *userdata,
|
||||
const ne_uri *uri,
|
||||
const ne_prop_result_set *set)
|
||||
{
|
||||
struct resource *newres = 0;
|
||||
const char *clength, *modtime, *file_id = NULL;
|
||||
const char *resourcetype = NULL;
|
||||
const char *md5sum = NULL;
|
||||
|
||||
const ne_status *status = NULL;
|
||||
char *path = ne_path_unescape( uri->path );
|
||||
char *parentPath;
|
||||
char *propfindRootUri = (char*) userdata;
|
||||
propfind_recursive_element_t *element = NULL;
|
||||
propfind_recursive_element_t *pElement = NULL;
|
||||
int depth = 0;
|
||||
csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;
|
||||
|
||||
|
||||
(void) status;
|
||||
(void) propfindRootUri;
|
||||
|
||||
if (!propfind_recursive_cache) {
|
||||
c_rbtree_create(&propfind_recursive_cache, _key_cmp, _data_cmp);
|
||||
if (!ctx->propfind_recursive_cache) {
|
||||
c_rbtree_create(&ctx->propfind_recursive_cache, _key_cmp, _data_cmp);
|
||||
}
|
||||
|
||||
/* Fill the resource structure with the data about the file */
|
||||
newres = c_malloc(sizeof(struct resource));
|
||||
ZERO_STRUCTP(newres);
|
||||
|
||||
newres->uri = path; /* no need to strdup because ne_path_unescape already allocates */
|
||||
newres->name = c_basename( path );
|
||||
fill_webdav_properties_into_resource(newres, set);
|
||||
|
||||
modtime = ne_propset_value( set, &ls_props[0] );
|
||||
clength = ne_propset_value( set, &ls_props[1] );
|
||||
resourcetype = ne_propset_value( set, &ls_props[2] );
|
||||
md5sum = ne_propset_value( set, &ls_props[3] );
|
||||
file_id = ne_propset_value( set, &ls_props[4] );
|
||||
|
||||
newres->type = resr_normal;
|
||||
if( resourcetype && strncmp( resourcetype, "<DAV:collection>", 16 ) == 0) {
|
||||
newres->type = resr_collection;
|
||||
propfind_recursive_cache_folder_count++;
|
||||
if( newres->type == resr_collection) {
|
||||
ctx->propfind_recursive_cache_folder_count++;
|
||||
} else {
|
||||
/* DEBUG_WEBDAV("propfind_results_recursive %s [%d]", newres->uri, newres->type); */
|
||||
propfind_recursive_cache_file_count++;
|
||||
ctx->propfind_recursive_cache_file_count++;
|
||||
}
|
||||
|
||||
if (modtime) {
|
||||
newres->modtime = oc_httpdate_parse(modtime);
|
||||
}
|
||||
|
||||
/* DEBUG_WEBDAV("Parsing Modtime: %s -> %llu", modtime, (unsigned long long) newres->modtime ); */
|
||||
newres->size = 0;
|
||||
if (clength) {
|
||||
newres->size = atoll(clength);
|
||||
/* DEBUG_WEBDAV("Parsed File size for %s from %s: %lld", newres->name, clength, (long long)newres->size ); */
|
||||
}
|
||||
|
||||
if( md5sum ) {
|
||||
newres->md5 = csync_normalize_etag(md5sum);
|
||||
}
|
||||
|
||||
csync_vio_set_file_id(newres->file_id, file_id);
|
||||
/*
|
||||
DEBUG_WEBDAV("propfind_results_recursive %s [%s] %s", newres->uri, newres->type == resr_collection ? "collection" : "file", newres->md5);
|
||||
*/
|
||||
|
||||
/* Create new item in rb tree */
|
||||
if (newres->type == resr_collection) {
|
||||
DEBUG_WEBDAV("propfind_results_recursive %s is a folder", newres->uri);
|
||||
/* Check if in rb tree */
|
||||
element = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache,uri->path));
|
||||
element = c_rbtree_node_data(c_rbtree_find(ctx->propfind_recursive_cache,uri->path));
|
||||
/* If not, create a new item and insert it */
|
||||
if (!element) {
|
||||
element = c_malloc(sizeof(propfind_recursive_element_t));
|
||||
element->self = resource_dup(newres);
|
||||
element->self->next = 0;
|
||||
element->children = NULL;
|
||||
element->parent = NULL;
|
||||
c_rbtree_insert(propfind_recursive_cache, element);
|
||||
c_rbtree_insert(ctx->propfind_recursive_cache, element);
|
||||
/* DEBUG_WEBDAV("results_recursive Added collection %s", newres->uri); */
|
||||
|
||||
// We do this here and in get_listdir_context_from_recursive_cache because
|
||||
// a recursive PROPFIND might take some time but we still want to
|
||||
// be informed. Later when get_listdir_context_from_recursive_cache is
|
||||
// called the DB queries might be the problem causing slowness, so do it again there then.
|
||||
if( ctx->csync_ctx->callbacks.update_callback ) {
|
||||
ctx->csync_ctx->callbacks.update_callback(false, path, ctx->csync_ctx->callbacks.update_callback_userdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +160,7 @@ static void propfind_results_recursive(void *userdata,
|
||||
if (parentPath) {
|
||||
propfind_recursive_element_t *parentElement = NULL;
|
||||
|
||||
parentElement = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache,parentPath));
|
||||
parentElement = c_rbtree_node_data(c_rbtree_find(ctx->propfind_recursive_cache,parentPath));
|
||||
free(parentPath);
|
||||
|
||||
if (parentElement) {
|
||||
@@ -230,9 +176,9 @@ static void propfind_results_recursive(void *userdata,
|
||||
depth++;
|
||||
pElement = pElement->parent;
|
||||
}
|
||||
if (depth > propfind_recursive_cache_depth) {
|
||||
if (depth > ctx->propfind_recursive_cache_depth) {
|
||||
DEBUG_WEBDAV("propfind_results_recursive %s new maximum tree depth %d", newres->uri, depth);
|
||||
propfind_recursive_cache_depth = depth;
|
||||
ctx->propfind_recursive_cache_depth = depth;
|
||||
}
|
||||
|
||||
/* DEBUG_WEBDAV("results_recursive Added child %s to collection %s", newres->uri, element->self->uri); */
|
||||
@@ -244,7 +190,7 @@ static void propfind_results_recursive(void *userdata,
|
||||
newres = NULL;
|
||||
}
|
||||
|
||||
void fetch_resource_list_recursive(const char *uri, const char *curi)
|
||||
void fetch_resource_list_recursive(csync_owncloud_ctx_t *ctx, const char *uri, const char *curi)
|
||||
{
|
||||
int ret = 0;
|
||||
ne_propfind_handler *hdl = NULL;
|
||||
@@ -254,12 +200,15 @@ void fetch_resource_list_recursive(const char *uri, const char *curi)
|
||||
int depth = NE_DEPTH_INFINITE;
|
||||
|
||||
DEBUG_WEBDAV("fetch_resource_list_recursive Starting recursive propfind %s %s", uri, curi);
|
||||
if( ctx->csync_ctx->callbacks.update_callback ) {
|
||||
ctx->csync_ctx->callbacks.update_callback(false, curi, ctx->csync_ctx->callbacks.update_callback_userdata);
|
||||
}
|
||||
|
||||
/* do a propfind request and parse the results in the results function, set as callback */
|
||||
hdl = ne_propfind_create(dav_session.ctx, curi, depth);
|
||||
hdl = ne_propfind_create(ctx->dav_session.ctx, curi, depth);
|
||||
|
||||
if(hdl) {
|
||||
ret = ne_propfind_named(hdl, ls_props, propfind_results_recursive, (void*)curi);
|
||||
ret = ne_propfind_named(hdl, ls_props, propfind_results_recursive_callback, ctx);
|
||||
request = ne_propfind_get_request( hdl );
|
||||
req_status = ne_get_status( request );
|
||||
}
|
||||
@@ -271,14 +220,14 @@ void fetch_resource_list_recursive(const char *uri, const char *curi)
|
||||
DEBUG_WEBDAV("ERROR: Request failed: status %d (%s)", req_status->code,
|
||||
req_status->reason_phrase);
|
||||
ret = NE_CONNECT;
|
||||
set_error_message(req_status->reason_phrase);
|
||||
set_error_message(ctx, req_status->reason_phrase);
|
||||
}
|
||||
DEBUG_WEBDAV("Recursive propfind result code %d.", req_status ? req_status->code : 0);
|
||||
} else {
|
||||
if( ret == NE_ERROR && req_status->code == 404) {
|
||||
errno = ENOENT;
|
||||
} else {
|
||||
set_errno_from_neon_errcode(ret);
|
||||
set_errno_from_neon_errcode(ctx, ret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,7 +242,7 @@ void fetch_resource_list_recursive(const char *uri, const char *curi)
|
||||
DEBUG_WEBDAV("ERROR: Content type of propfind request not XML: %s.",
|
||||
content_type ? content_type: "<empty>");
|
||||
errno = ERRNO_WRONG_CONTENT;
|
||||
set_error_message("Server error: PROPFIND reply is not XML formatted!");
|
||||
set_error_message(ctx, "Server error: PROPFIND reply is not XML formatted!");
|
||||
ret = NE_CONNECT;
|
||||
}
|
||||
}
|
||||
@@ -301,7 +250,7 @@ void fetch_resource_list_recursive(const char *uri, const char *curi)
|
||||
if( ret != NE_OK ) {
|
||||
const char *err = NULL;
|
||||
|
||||
err = ne_get_error( dav_session.ctx );
|
||||
err = ne_get_error( ctx->dav_session.ctx );
|
||||
DEBUG_WEBDAV("WRN: propfind named failed with %d, request error: %s", ret, err ? err : "<nil>");
|
||||
}
|
||||
|
||||
@@ -316,22 +265,21 @@ void fetch_resource_list_recursive(const char *uri, const char *curi)
|
||||
}
|
||||
|
||||
/* Called by owncloud_opendir()->fetch_resource_list() to fill the cache */
|
||||
extern struct listdir_context *propfind_cache;
|
||||
void fill_recursive_propfind_cache(const char *uri, const char *curi) {
|
||||
fetch_resource_list_recursive(uri, curi);
|
||||
void fill_recursive_propfind_cache(csync_owncloud_ctx_t *ctx, const char *uri, const char *curi) {
|
||||
fetch_resource_list_recursive(ctx, uri, curi);
|
||||
|
||||
if (propfind_recursive_cache_depth <= 2) {
|
||||
if (ctx->propfind_recursive_cache_depth <= 2) {
|
||||
DEBUG_WEBDAV("fill_recursive_propfind_cache %s Server maybe did not give us an 'infinity' depth result", curi);
|
||||
/* transform the cache to the normal cache in propfind_cache */
|
||||
propfind_cache = get_listdir_context_from_recursive_cache(curi);
|
||||
ctx->propfind_cache = get_listdir_context_from_recursive_cache(ctx, curi);
|
||||
/* clear the cache, it is bogus since the server returned only results for Depth 1 */
|
||||
clear_propfind_recursive_cache();
|
||||
clear_propfind_recursive_cache(ctx);
|
||||
} else {
|
||||
DEBUG_WEBDAV("fill_recursive_propfind_cache %s We received %d elements deep for 'infinity' depth (%d folders, %d files)",
|
||||
curi,
|
||||
propfind_recursive_cache_depth,
|
||||
propfind_recursive_cache_folder_count,
|
||||
propfind_recursive_cache_file_count);
|
||||
ctx->propfind_recursive_cache_depth,
|
||||
ctx->propfind_recursive_cache_folder_count,
|
||||
ctx->propfind_recursive_cache_file_count);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,13 +20,15 @@
|
||||
*/
|
||||
|
||||
#include "csync_owncloud.h"
|
||||
#include "csync_owncloud_private.h"
|
||||
|
||||
#include "csync_misc.h"
|
||||
|
||||
void set_error_message( const char *msg )
|
||||
void set_error_message( csync_owncloud_ctx_t *ctx, const char *msg )
|
||||
{
|
||||
SAFE_FREE(dav_session.error_string);
|
||||
SAFE_FREE(ctx->dav_session.error_string);
|
||||
if( msg )
|
||||
dav_session.error_string = c_strdup(msg);
|
||||
ctx->dav_session.error_string = c_strdup(msg);
|
||||
}
|
||||
|
||||
void set_errno_from_http_errcode( int err ) {
|
||||
@@ -104,12 +106,12 @@ void set_errno_from_http_errcode( int err ) {
|
||||
errno = new_errno;
|
||||
}
|
||||
|
||||
int http_result_code_from_session() {
|
||||
const char *p = ne_get_error( dav_session.ctx );
|
||||
int http_result_code_from_session(csync_owncloud_ctx_t *ctx) {
|
||||
const char *p = ne_get_error( ctx->dav_session.ctx );
|
||||
char *q;
|
||||
int err;
|
||||
|
||||
set_error_message(p); /* remember the error message */
|
||||
set_error_message(ctx, p); /* remember the error message */
|
||||
|
||||
err = strtol(p, &q, 10);
|
||||
if (p == q) {
|
||||
@@ -118,8 +120,8 @@ int http_result_code_from_session() {
|
||||
return err;
|
||||
}
|
||||
|
||||
void set_errno_from_session() {
|
||||
int err = http_result_code_from_session();
|
||||
void set_errno_from_session(csync_owncloud_ctx_t *ctx) {
|
||||
int err = http_result_code_from_session(ctx);
|
||||
|
||||
if( err == EIO || err == ERRNO_ERROR_STRING) {
|
||||
errno = err;
|
||||
@@ -128,7 +130,7 @@ void set_errno_from_session() {
|
||||
}
|
||||
}
|
||||
|
||||
void set_errno_from_neon_errcode( int neon_code ) {
|
||||
void set_errno_from_neon_errcode(csync_owncloud_ctx_t *ctx, int neon_code ) {
|
||||
|
||||
if( neon_code != NE_OK ) {
|
||||
DEBUG_WEBDAV("Neon error code was %d", neon_code);
|
||||
@@ -137,7 +139,7 @@ void set_errno_from_neon_errcode( int neon_code ) {
|
||||
switch(neon_code) {
|
||||
case NE_OK: /* Success, but still the possiblity of problems */
|
||||
case NE_ERROR: /* Generic error; use ne_get_error(session) for message */
|
||||
set_errno_from_session(); /* Something wrong with http communication */
|
||||
set_errno_from_session(ctx); /* Something wrong with http communication */
|
||||
break;
|
||||
case NE_LOOKUP: /* Server or proxy hostname lookup failed */
|
||||
errno = ERRNO_LOOKUP_ERROR;
|
||||
@@ -279,19 +281,9 @@ time_t oc_httpdate_parse( const char *date ) {
|
||||
/*
|
||||
* helper: convert a resource struct to file_stat struct.
|
||||
*/
|
||||
csync_vio_file_stat_t *resourceToFileStat( struct resource *res )
|
||||
void resourceToFileStat(csync_vio_file_stat_t *lfs, struct resource *res )
|
||||
{
|
||||
csync_vio_file_stat_t *lfs = NULL;
|
||||
|
||||
if( ! res ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lfs = c_malloc(sizeof(csync_vio_file_stat_t));
|
||||
if (lfs == NULL) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
ZERO_STRUCTP(lfs);
|
||||
|
||||
lfs->name = c_strdup( res->name );
|
||||
|
||||
@@ -312,30 +304,179 @@ csync_vio_file_stat_t *resourceToFileStat( struct resource *res )
|
||||
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
|
||||
if( res->md5 ) {
|
||||
lfs->etag = c_strdup(res->md5);
|
||||
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG;
|
||||
}
|
||||
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG;
|
||||
|
||||
csync_vio_file_stat_set_file_id(lfs, res->file_id);
|
||||
|
||||
return lfs;
|
||||
}
|
||||
|
||||
/* WebDAV does not deliver permissions. Set a default here. */
|
||||
int _stat_perms( int type ) {
|
||||
int ret = 0;
|
||||
|
||||
if( type == CSYNC_VIO_FILE_TYPE_DIRECTORY ) {
|
||||
/* DEBUG_WEBDAV("Setting mode in stat (dir)"); */
|
||||
/* directory permissions */
|
||||
ret = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR /* directory, rwx for user */
|
||||
| S_IRGRP | S_IXGRP /* rx for group */
|
||||
| S_IROTH | S_IXOTH; /* rx for others */
|
||||
} else {
|
||||
/* regualar file permissions */
|
||||
/* DEBUG_WEBDAV("Setting mode in stat (file)"); */
|
||||
ret = S_IFREG | S_IRUSR | S_IWUSR /* regular file, user read & write */
|
||||
| S_IRGRP /* group read perm */
|
||||
| S_IROTH; /* others read perm */
|
||||
if (res->directDownloadUrl) {
|
||||
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADURL;
|
||||
lfs->directDownloadUrl = c_strdup(res->directDownloadUrl);
|
||||
}
|
||||
if (res->directDownloadCookies) {
|
||||
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADCOOKIES;
|
||||
lfs->directDownloadCookies = c_strdup(res->directDownloadCookies);
|
||||
}
|
||||
if (strlen(res->remotePerm) > 0) {
|
||||
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERM;
|
||||
strncpy(lfs->remotePerm, res->remotePerm, sizeof(lfs->remotePerm));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void fill_webdav_properties_into_resource(struct resource* newres, const ne_prop_result_set *set)
|
||||
{
|
||||
const char *clength, *modtime, *file_id = NULL;
|
||||
const char *directDownloadUrl = NULL;
|
||||
const char *directDownloadCookies = NULL;
|
||||
const char *resourcetype = NULL;
|
||||
const char *etag = NULL;
|
||||
const char *perm = NULL;
|
||||
|
||||
modtime = ne_propset_value( set, &ls_props[0] );
|
||||
clength = ne_propset_value( set, &ls_props[1] );
|
||||
resourcetype = ne_propset_value( set, &ls_props[2] );
|
||||
etag = ne_propset_value( set, &ls_props[3] );
|
||||
file_id = ne_propset_value( set, &ls_props[4] );
|
||||
directDownloadUrl = ne_propset_value( set, &ls_props[5] );
|
||||
directDownloadCookies = ne_propset_value( set, &ls_props[6] );
|
||||
|
||||
// permission flags: Defined in https://github.com/owncloud/core/issues/8322
|
||||
perm = ne_propset_value( set, &ls_props[7] );
|
||||
|
||||
if( resourcetype && strncmp( resourcetype, "<DAV:collection>", 16 ) == 0) {
|
||||
newres->type = resr_collection;
|
||||
} else {
|
||||
newres->type = resr_normal;
|
||||
}
|
||||
|
||||
if (modtime) {
|
||||
newres->modtime = oc_httpdate_parse(modtime);
|
||||
}
|
||||
|
||||
/* DEBUG_WEBDAV("Parsing Modtime: %s -> %llu", modtime, (unsigned long long) newres->modtime ); */
|
||||
newres->size = 0;
|
||||
if (clength) {
|
||||
newres->size = atoll(clength);
|
||||
/* DEBUG_WEBDAV("Parsed File size for %s from %s: %lld", newres->name, clength, (long long)newres->size ); */
|
||||
}
|
||||
|
||||
if( etag ) {
|
||||
newres->md5 = csync_normalize_etag(etag);
|
||||
}
|
||||
|
||||
csync_vio_set_file_id(newres->file_id, file_id);
|
||||
/*
|
||||
DEBUG_WEBDAV("propfind_results_recursive %s [%s] %s", newres->uri, newres->type == resr_collection ? "collection" : "file", newres->md5);
|
||||
*/
|
||||
|
||||
if (directDownloadUrl) {
|
||||
newres->directDownloadUrl = c_strdup(directDownloadUrl);
|
||||
}
|
||||
if (directDownloadCookies) {
|
||||
newres->directDownloadCookies = c_strdup(directDownloadCookies);
|
||||
}
|
||||
if (perm && !perm[0]) {
|
||||
// special meaning for our code: server returned permissions but are empty
|
||||
// meaning only reading is allowed for this resource
|
||||
newres->remotePerm[0] = ' ';
|
||||
// see _csync_detect_update()
|
||||
} else if (perm && strlen(perm) < sizeof(newres->remotePerm)) {
|
||||
strncpy(newres->remotePerm, perm, sizeof(newres->remotePerm));
|
||||
} else {
|
||||
// old server, keep newres->remotePerm empty
|
||||
}
|
||||
}
|
||||
|
||||
struct resource* resource_dup(struct resource* o) {
|
||||
struct resource *r = c_malloc (sizeof( struct resource ));
|
||||
ZERO_STRUCTP(r);
|
||||
|
||||
r->uri = c_strdup(o->uri);
|
||||
r->name = c_strdup(o->name);
|
||||
r->type = o->type;
|
||||
r->size = o->size;
|
||||
r->modtime = o->modtime;
|
||||
if( o->md5 ) {
|
||||
r->md5 = c_strdup(o->md5);
|
||||
}
|
||||
if (o->directDownloadUrl) {
|
||||
r->directDownloadUrl = c_strdup(o->directDownloadUrl);
|
||||
}
|
||||
if (o->directDownloadCookies) {
|
||||
r->directDownloadCookies = c_strdup(o->directDownloadCookies);
|
||||
}
|
||||
if (o->remotePerm) {
|
||||
strncpy(r->remotePerm, o->remotePerm, sizeof(r->remotePerm));
|
||||
}
|
||||
r->next = o->next;
|
||||
csync_vio_set_file_id(r->file_id, o->file_id);
|
||||
|
||||
return r;
|
||||
}
|
||||
void resource_free(struct resource* o) {
|
||||
struct resource* old = NULL;
|
||||
while (o)
|
||||
{
|
||||
old = o;
|
||||
o = o->next;
|
||||
SAFE_FREE(old->uri);
|
||||
SAFE_FREE(old->name);
|
||||
SAFE_FREE(old->md5);
|
||||
SAFE_FREE(old->directDownloadUrl);
|
||||
SAFE_FREE(old->directDownloadCookies);
|
||||
SAFE_FREE(old);
|
||||
}
|
||||
}
|
||||
|
||||
void free_fetchCtx( struct listdir_context *ctx )
|
||||
{
|
||||
struct resource *newres, *res;
|
||||
if( ! ctx ) return;
|
||||
newres = ctx->list;
|
||||
res = newres;
|
||||
|
||||
ctx->ref--;
|
||||
if (ctx->ref > 0) return;
|
||||
|
||||
SAFE_FREE(ctx->target);
|
||||
|
||||
while( res ) {
|
||||
SAFE_FREE(res->uri);
|
||||
SAFE_FREE(res->name);
|
||||
SAFE_FREE(res->md5);
|
||||
memset( res->file_id, 0, FILE_ID_BUF_SIZE+1 );
|
||||
SAFE_FREE(res->directDownloadUrl);
|
||||
SAFE_FREE(res->directDownloadCookies);
|
||||
|
||||
newres = res->next;
|
||||
SAFE_FREE(res);
|
||||
res = newres;
|
||||
}
|
||||
SAFE_FREE(ctx);
|
||||
}
|
||||
|
||||
|
||||
// as per http://sourceforge.net/p/predef/wiki/OperatingSystems/
|
||||
// extend as required
|
||||
const char* csync_owncloud_get_platform() {
|
||||
#if defined (_WIN32)
|
||||
return "Windows";
|
||||
#elif defined(__APPLE__)
|
||||
return "Macintosh";
|
||||
#elif defined(__gnu_linux__)
|
||||
return "Linux";
|
||||
#elif defined(__DragonFly__)
|
||||
/* might also define __FreeBSD__ */
|
||||
return "DragonFlyBSD";
|
||||
#elif defined(__FreeBSD__)
|
||||
return "FreeBSD";
|
||||
#elif defined(__NetBSD__)
|
||||
return "NetBSD";
|
||||
#elif defined(__OpenBSD__)
|
||||
return "OpenBSD";
|
||||
#elif defined(sun) || defined(__sun)
|
||||
return "Solaris";
|
||||
#else
|
||||
return "Unknown OS";
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -61,18 +61,6 @@
|
||||
*/
|
||||
#define MAX_DEPTH 50
|
||||
|
||||
/**
|
||||
* Maximum time difference between two replicas in seconds
|
||||
*/
|
||||
#define MAX_TIME_DIFFERENCE 10
|
||||
|
||||
/**
|
||||
* Maximum size of a buffer for transfer
|
||||
*/
|
||||
#ifndef MAX_XFER_BUF_SIZE
|
||||
#define MAX_XFER_BUF_SIZE (16 * 1024)
|
||||
#endif
|
||||
|
||||
#define CSYNC_STATUS_INIT 1 << 0
|
||||
#define CSYNC_STATUS_UPDATE 1 << 1
|
||||
#define CSYNC_STATUS_RECONCILE 1 << 2
|
||||
@@ -90,6 +78,8 @@ enum csync_replica_e {
|
||||
|
||||
typedef struct csync_file_stat_s csync_file_stat_t;
|
||||
|
||||
struct csync_owncloud_ctx_s; // csync_owncloud.c
|
||||
|
||||
/**
|
||||
* @brief csync public structure
|
||||
*/
|
||||
@@ -97,6 +87,8 @@ struct csync_s {
|
||||
struct {
|
||||
csync_auth_callback auth_function;
|
||||
void *userdata;
|
||||
csync_update_callback update_callback;
|
||||
void *update_callback_userdata;
|
||||
} callbacks;
|
||||
c_strlist_t *excludes;
|
||||
|
||||
@@ -104,11 +96,12 @@ struct csync_s {
|
||||
char *file;
|
||||
sqlite3 *db;
|
||||
int exists;
|
||||
int disabled;
|
||||
|
||||
sqlite3_stmt* by_hash_stmt;
|
||||
sqlite3_stmt* by_fileid_stmt;
|
||||
sqlite3_stmt* by_inode_stmt;
|
||||
|
||||
int lastReturnValue;
|
||||
} statedb;
|
||||
|
||||
struct {
|
||||
@@ -116,7 +109,6 @@ struct csync_s {
|
||||
c_rbtree_t *tree;
|
||||
c_list_t *list;
|
||||
enum csync_replica_e type;
|
||||
c_list_t *ignored_cleanup;
|
||||
} local;
|
||||
|
||||
struct {
|
||||
@@ -125,23 +117,13 @@ struct csync_s {
|
||||
c_list_t *list;
|
||||
enum csync_replica_e type;
|
||||
int read_from_db;
|
||||
c_list_t *ignored_cleanup;
|
||||
} remote;
|
||||
|
||||
struct {
|
||||
int sync_symbolic_links;
|
||||
char *config_dir;
|
||||
bool local_only_mode;
|
||||
int timeout;
|
||||
#if defined(HAVE_ICONV) && defined(WITH_ICONV)
|
||||
iconv_t iconv_cd;
|
||||
#endif
|
||||
} options;
|
||||
|
||||
struct {
|
||||
uid_t uid;
|
||||
uid_t euid;
|
||||
} pwd;
|
||||
iconv_t iconv_cd;
|
||||
} options;
|
||||
#endif
|
||||
|
||||
/* replica we are currently walking */
|
||||
enum csync_replica_e current;
|
||||
@@ -162,6 +144,12 @@ struct csync_s {
|
||||
volatile int abort;
|
||||
void *rename_info;
|
||||
int read_from_db_disabled;
|
||||
|
||||
struct csync_owncloud_ctx_s *owncloud_context;
|
||||
|
||||
/* hooks for checking the white list */
|
||||
void *checkSelectiveSyncBlackListData;
|
||||
int (*checkSelectiveSyncBlackListHook)(void*, const char*);
|
||||
};
|
||||
|
||||
|
||||
@@ -174,17 +162,20 @@ struct csync_file_stat_s {
|
||||
int64_t size; /* u64 */
|
||||
size_t pathlen; /* u64 */
|
||||
uint64_t inode; /* u64 */
|
||||
uid_t uid; /* u32 */
|
||||
gid_t gid; /* u32 */
|
||||
mode_t mode; /* u32 */
|
||||
int nlink; /* u32 */
|
||||
int type; /* u32 */
|
||||
int child_modified;/*bool*/
|
||||
int should_update_etag; /*bool */
|
||||
int has_ignored_files; /*bool: specify that a directory, or child directory contains ignored files */
|
||||
|
||||
char *destpath; /* for renames */
|
||||
const char *etag;
|
||||
char file_id[FILE_ID_BUF_SIZE+1]; /* the ownCloud file id is fixed width of 21 byte. */
|
||||
char *directDownloadUrl;
|
||||
char *directDownloadCookies;
|
||||
char remotePerm[REMOTE_PERM_BUF_SIZE+1];
|
||||
|
||||
CSYNC_STATUS error_status;
|
||||
|
||||
enum csync_instructions_e instruction; /* u32 */
|
||||
|
||||
@@ -134,6 +134,15 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) {
|
||||
break;
|
||||
/* file has been removed on the opposite replica */
|
||||
case CSYNC_INSTRUCTION_NONE:
|
||||
if (cur->has_ignored_files) {
|
||||
/* Do not remove a directory that has ignored files */
|
||||
break;
|
||||
}
|
||||
if (cur->child_modified) {
|
||||
/* re-create directory that has modified contents */
|
||||
cur->instruction = CSYNC_INSTRUCTION_NEW;
|
||||
break;
|
||||
}
|
||||
cur->instruction = CSYNC_INSTRUCTION_REMOVE;
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_EVAL_RENAME:
|
||||
@@ -184,6 +193,7 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) {
|
||||
csync_vio_set_file_id( other->file_id, cur->file_id );
|
||||
}
|
||||
other->inode = cur->inode;
|
||||
other->should_update_etag = true;
|
||||
cur->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
} else if (other->instruction == CSYNC_INSTRUCTION_REMOVE) {
|
||||
other->instruction = CSYNC_INSTRUCTION_RENAME;
|
||||
@@ -193,6 +203,7 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) {
|
||||
csync_vio_set_file_id( other->file_id, cur->file_id );
|
||||
}
|
||||
other->inode = cur->inode;
|
||||
other->should_update_etag = true;
|
||||
cur->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
} else if (other->instruction == CSYNC_INSTRUCTION_NEW) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "OOOO=> NEW detected in other tree!");
|
||||
|
||||
@@ -50,6 +50,22 @@
|
||||
|
||||
#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) {
|
||||
ctx->statedb.exists = val;
|
||||
}
|
||||
@@ -58,28 +74,6 @@ int csync_get_statedb_exists(CSYNC *ctx) {
|
||||
return ctx->statedb.exists;
|
||||
}
|
||||
|
||||
/* Set the hide attribute in win32. That makes it invisible in normal explorers */
|
||||
static void _csync_win32_hide_file( const char *file ) {
|
||||
#ifdef _WIN32
|
||||
mbchar_t *fileName;
|
||||
DWORD dwAttrs;
|
||||
|
||||
if( !file ) return;
|
||||
|
||||
fileName = c_utf8_to_locale( file );
|
||||
dwAttrs = GetFileAttributesW(fileName);
|
||||
|
||||
if (dwAttrs != INVALID_FILE_ATTRIBUTES) {
|
||||
if (!(dwAttrs & FILE_ATTRIBUTE_HIDDEN)) {
|
||||
SetFileAttributesW(fileName, dwAttrs | FILE_ATTRIBUTE_HIDDEN );
|
||||
}
|
||||
}
|
||||
c_free_locale_string(fileName);
|
||||
#else
|
||||
(void) file;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int _csync_check_db_integrity(sqlite3 *db) {
|
||||
c_strlist_t *result = NULL;
|
||||
int rc = -1;
|
||||
@@ -95,85 +89,12 @@ static int _csync_check_db_integrity(sqlite3 *db) {
|
||||
c_strlist_destroy(result);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
if( sqlite3_threadsafe() == 0 ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "* WARNING: SQLite module is not threadsafe!");
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
c_free_locale_string(wstatedb);
|
||||
|
||||
/* create database */
|
||||
rc = sqlite3_open(statedb, &db);
|
||||
if (rc == SQLITE_OK) {
|
||||
sqlite3_close(db);
|
||||
_csync_win32_hide_file(statedb);
|
||||
return 1;
|
||||
}
|
||||
sqlite3_close(db);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "sqlite3_open failed: %s %s", sqlite3_errmsg(db), statedb);
|
||||
return -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int _csync_statedb_is_empty(sqlite3 *db) {
|
||||
@@ -201,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 rc = -1;
|
||||
int check_rc = -1;
|
||||
c_strlist_t *result = NULL;
|
||||
sqlite3 *db = NULL;
|
||||
|
||||
@@ -209,19 +129,15 @@ int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* csync_statedb_check tries to open the statedb and creates it in case
|
||||
* its not there.
|
||||
*/
|
||||
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;
|
||||
if (ctx->statedb.db) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "ERR: DB already open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Open or create the temporary database */
|
||||
if (sqlite3_open(statedb, &db) != SQLITE_OK) {
|
||||
ctx->statedb.lastReturnValue = SQLITE_OK;
|
||||
|
||||
/* Openthe database */
|
||||
if (sqlite_open(statedb, &db) != SQLITE_OK) {
|
||||
const char *errmsg= sqlite3_errmsg(ctx->statedb.db);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "ERR: Failed to sqlite3 open statedb - bail out: %s.",
|
||||
errmsg ? errmsg : "<no sqlite3 errormsg>");
|
||||
@@ -230,25 +146,45 @@ int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* If check_rc == 1 the database is new and empty as a result. */
|
||||
if ((check_rc == 1) || _csync_statedb_is_empty(db)) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "statedb doesn't exist");
|
||||
if (_csync_check_db_integrity(db) != 0) {
|
||||
const char *errmsg= sqlite3_errmsg(db);
|
||||
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);
|
||||
} else {
|
||||
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 */
|
||||
result = csync_statedb_query(db, "PRAGMA synchronous = FULL;");
|
||||
result = csync_statedb_query(db, "PRAGMA synchronous = NORMAL;");
|
||||
c_strlist_destroy(result);
|
||||
result = csync_statedb_query(db, "PRAGMA case_sensitive_like = ON;");
|
||||
c_strlist_destroy(result);
|
||||
|
||||
/* set a busy handler with 5 seconds timeout */
|
||||
sqlite3_busy_timeout(db, 5000);
|
||||
|
||||
#ifndef NDEBUG
|
||||
sqlite3_profile(db, sqlite_profile, 0 );
|
||||
#endif
|
||||
*pdb = db;
|
||||
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "Success");
|
||||
|
||||
return 0;
|
||||
out:
|
||||
sqlite3_close(db);
|
||||
@@ -263,22 +199,25 @@ int csync_statedb_close(CSYNC *ctx) {
|
||||
}
|
||||
|
||||
/* 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 ) {
|
||||
rc = sqlite3_finalize(ctx->statedb.by_fileid_stmt);
|
||||
sqlite3_finalize(ctx->statedb.by_fileid_stmt);
|
||||
ctx->statedb.by_fileid_stmt = NULL;
|
||||
}
|
||||
|
||||
if( ctx->statedb.by_inode_stmt ) {
|
||||
rc = sqlite3_finalize(ctx->statedb.by_inode_stmt);
|
||||
if( ctx->statedb.by_hash_stmt ) {
|
||||
sqlite3_finalize(ctx->statedb.by_hash_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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -300,7 +239,7 @@ static int _csync_file_stat_from_metadata_table( csync_file_stat_t **st, sqlite3
|
||||
|
||||
column_count = sqlite3_column_count(stmt);
|
||||
|
||||
rc = sqlite3_step(stmt);
|
||||
SQLITE_BUSY_HANDLED( sqlite3_step(stmt) );
|
||||
|
||||
if( rc == SQLITE_ROW ) {
|
||||
if(column_count > 7) {
|
||||
@@ -322,8 +261,6 @@ static int _csync_file_stat_from_metadata_table( csync_file_stat_t **st, sqlite3
|
||||
name = (const char*) sqlite3_column_text(stmt, 2);
|
||||
memcpy((*st)->path, (len ? name : ""), len + 1);
|
||||
(*st)->inode = sqlite3_column_int64(stmt,3);
|
||||
(*st)->uid = sqlite3_column_int(stmt, 4);
|
||||
(*st)->gid = sqlite3_column_int(stmt, 5);
|
||||
(*st)->mode = sqlite3_column_int(stmt, 6);
|
||||
(*st)->modtime = strtoul((char*)sqlite3_column_text(stmt, 7), NULL, 10);
|
||||
|
||||
@@ -337,6 +274,15 @@ static int _csync_file_stat_from_metadata_table( csync_file_stat_t **st, sqlite3
|
||||
if(column_count > 10 && sqlite3_column_text(stmt,10)) {
|
||||
csync_vio_set_file_id((*st)->file_id, (char*) sqlite3_column_text(stmt, 10));
|
||||
}
|
||||
if(column_count > 11 && sqlite3_column_text(stmt,11)) {
|
||||
strncpy((*st)->remotePerm,
|
||||
(char*) sqlite3_column_text(stmt, 11),
|
||||
REMOTE_PERM_BUF_SIZE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if( rc != SQLITE_DONE ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "WARN: Query results in %d", rc);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
@@ -356,7 +302,8 @@ csync_file_stat_t *csync_statedb_get_stat_by_hash(CSYNC *ctx,
|
||||
if( ctx->statedb.by_hash_stmt == NULL ) {
|
||||
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 ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for hash query.");
|
||||
return NULL;
|
||||
@@ -369,8 +316,10 @@ 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);
|
||||
|
||||
if( _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_hash_stmt) < 0 ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata!");
|
||||
rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_hash_stmt);
|
||||
ctx->statedb.lastReturnValue = rc;
|
||||
if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata: %d!", rc);
|
||||
}
|
||||
sqlite3_reset(ctx->statedb.by_hash_stmt);
|
||||
|
||||
@@ -396,7 +345,8 @@ csync_file_stat_t *csync_statedb_get_stat_by_file_id(CSYNC *ctx,
|
||||
if( ctx->statedb.by_fileid_stmt == NULL ) {
|
||||
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 ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for file id query.");
|
||||
return NULL;
|
||||
@@ -406,8 +356,10 @@ csync_file_stat_t *csync_statedb_get_stat_by_file_id(CSYNC *ctx,
|
||||
/* bind the query value */
|
||||
sqlite3_bind_text(ctx->statedb.by_fileid_stmt, 1, file_id, -1, SQLITE_STATIC);
|
||||
|
||||
if( _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_fileid_stmt) < 0 ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata!");
|
||||
rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_fileid_stmt);
|
||||
ctx->statedb.lastReturnValue = rc;
|
||||
if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata: %d!", rc);
|
||||
}
|
||||
// clear the resources used by the statement.
|
||||
sqlite3_reset(ctx->statedb.by_fileid_stmt);
|
||||
@@ -433,7 +385,8 @@ csync_file_stat_t *csync_statedb_get_stat_by_inode(CSYNC *ctx,
|
||||
if( ctx->statedb.by_inode_stmt == NULL ) {
|
||||
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 ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for inode query.");
|
||||
return NULL;
|
||||
@@ -446,8 +399,10 @@ 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);
|
||||
|
||||
if( _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_inode_stmt) < 0 ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata by inode!");
|
||||
rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_inode_stmt);
|
||||
ctx->statedb.lastReturnValue = rc;
|
||||
if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata by inode: %d!", rc);
|
||||
}
|
||||
sqlite3_reset(ctx->statedb.by_inode_stmt);
|
||||
|
||||
@@ -476,7 +431,7 @@ char *csync_statedb_get_etag( CSYNC *ctx, uint64_t jHash ) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define BELOW_PATH_QUERY "SELECT phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid FROM metadata WHERE path LIKE(?)"
|
||||
#define BELOW_PATH_QUERY "SELECT phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm FROM metadata WHERE pathlen>? AND path LIKE(?)"
|
||||
|
||||
int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
||||
int rc;
|
||||
@@ -484,6 +439,7 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
||||
int64_t cnt = 0;
|
||||
char *likepath;
|
||||
int asp;
|
||||
int min_path_len;
|
||||
|
||||
if( !path ) {
|
||||
return -1;
|
||||
@@ -493,9 +449,10 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
||||
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 ) {
|
||||
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 below path query.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -509,10 +466,13 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
sqlite3_bind_text(stmt, 1, likepath, -1, SQLITE_STATIC);
|
||||
min_path_len = strlen(path);
|
||||
sqlite3_bind_int(stmt, 1, min_path_len);
|
||||
sqlite3_bind_text(stmt, 2, likepath, -1, SQLITE_STATIC);
|
||||
|
||||
cnt = 0;
|
||||
|
||||
ctx->statedb.lastReturnValue = rc;
|
||||
do {
|
||||
csync_file_stat_t *st = NULL;
|
||||
|
||||
@@ -528,6 +488,7 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
||||
}
|
||||
} while( rc == SQLITE_ROW );
|
||||
|
||||
ctx->statedb.lastReturnValue = rc;
|
||||
if( rc != SQLITE_DONE ) {
|
||||
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
|
||||
} 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);
|
||||
|
||||
/**
|
||||
* @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
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -100,6 +100,10 @@ static bool _csync_sameextension(const char *p1, const char *p2) {
|
||||
}
|
||||
#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,
|
||||
const csync_vio_file_stat_t *fs, const int type) {
|
||||
uint64_t h = 0;
|
||||
@@ -146,21 +150,21 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
if (excluded != CSYNC_NOT_EXCLUDED) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "%s excluded (%d)", path, excluded);
|
||||
if (excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE) {
|
||||
switch (ctx->current) {
|
||||
case LOCAL_REPLICA:
|
||||
ctx->local.ignored_cleanup = c_list_append(ctx->local.ignored_cleanup, c_strdup(path));
|
||||
break;
|
||||
case REMOTE_REPLICA:
|
||||
ctx->remote.ignored_cleanup = c_list_append(ctx->remote.ignored_cleanup, c_strdup(path));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
if (excluded == CSYNC_FILE_SILENTLY_EXCLUDED) {
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ctx->current_fs) {
|
||||
ctx->current_fs->has_ignored_files = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->current == REMOTE_REPLICA && ctx->checkSelectiveSyncBlackListHook) {
|
||||
if (ctx->checkSelectiveSyncBlackListHook(ctx->checkSelectiveSyncBlackListData, path)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
h = _hash_of_file(ctx, file );
|
||||
@@ -179,17 +183,26 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
st->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
st->etag = NULL;
|
||||
st->child_modified = 0;
|
||||
st->has_ignored_files = 0;
|
||||
|
||||
/* check hardlink count */
|
||||
if (type == CSYNC_FTW_TYPE_FILE ) {
|
||||
if( fs->nlink > 1) {
|
||||
st->instruction = CSYNC_INSTRUCTION_IGNORE;
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_IS_HARDLINK;
|
||||
goto out;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s - not found in db, IGNORE!", path);
|
||||
st->instruction = CSYNC_INSTRUCTION_IGNORE;
|
||||
@@ -226,16 +239,28 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
if (csync_get_statedb_exists(ctx)) {
|
||||
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 */
|
||||
/* we have an update! */
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Database entry found, compare: %" PRId64 " <-> %" PRId64 ", etag: %s <-> %s, inode: %" PRId64 " <-> %" PRId64,
|
||||
((int64_t) fs->mtime), ((int64_t) tmp->modtime), fs->etag, tmp->etag, (uint64_t) fs->inode, (uint64_t) tmp->inode);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Database entry found, compare: %" PRId64 " <-> %" PRId64
|
||||
", 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) {
|
||||
st->instruction = CSYNC_INSTRUCTION_EVAL;
|
||||
goto out;
|
||||
}
|
||||
if((ctx->current == REMOTE_REPLICA && !c_streq(fs->etag, tmp->etag ))
|
||||
|| (ctx->current == LOCAL_REPLICA && (fs->mtime != tmp->modtime
|
||||
// zero size in statedb can happen during migration
|
||||
|| (tmp->size != 0 && fs->size != tmp->size)
|
||||
#if 0
|
||||
|| fs->inode != tmp->inode
|
||||
#endif
|
||||
@@ -254,20 +279,22 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
st->instruction = CSYNC_INSTRUCTION_EVAL;
|
||||
goto out;
|
||||
}
|
||||
bool metadata_differ = (ctx->current == REMOTE_REPLICA && (!c_streq(fs->file_id, tmp->file_id)
|
||||
|| !c_streq(fs->remotePerm, tmp->remotePerm)))
|
||||
|| (ctx->current == LOCAL_REPLICA && fs->inode != tmp->inode);
|
||||
if (type == CSYNC_FTW_TYPE_DIR && ctx->current == REMOTE_REPLICA
|
||||
&& c_streq(fs->file_id, tmp->file_id) && !ctx->read_from_db_disabled) {
|
||||
&& !metadata_differ && !ctx->read_from_db_disabled) {
|
||||
/* If both etag and file id are equal for a directory, read all contents from
|
||||
* the database.
|
||||
* The comparison of file id ensure that we fetch all the file id when upgrading from
|
||||
* owncloud 5 to owncloud 6.
|
||||
* The metadata comparison ensure that we fetch all the file id or permission when
|
||||
* upgrading owncloud
|
||||
*/
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Reading from database: %s", path);
|
||||
ctx->remote.read_from_db = true;
|
||||
}
|
||||
|
||||
if (!c_streq(fs->file_id, tmp->file_id) && ctx->current == REMOTE_REPLICA) {
|
||||
/* file id has changed. Which means we need to update the DB.
|
||||
* (upgrade from owncloud 5 to owncloud 6 for instence) */
|
||||
if (metadata_differ) {
|
||||
/* file id or permissions has changed. Which means we need to update them in the DB. */
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Need to update metadata for: %s", path);
|
||||
st->should_update_etag = true;
|
||||
}
|
||||
st->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
@@ -283,6 +310,12 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
|
||||
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. */
|
||||
if( tmp && tmp->type == 0 ) {
|
||||
tmp_vio_type = CSYNC_VIO_FILE_TYPE_REGULAR;
|
||||
@@ -313,6 +346,12 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
} else {
|
||||
/* Remote Replica Rename check */
|
||||
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->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)) {
|
||||
@@ -340,7 +379,9 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
st->instruction = CSYNC_INSTRUCTION_NEW;
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Unable to open statedb" );
|
||||
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -364,8 +405,6 @@ out:
|
||||
st->mode = fs->mode;
|
||||
st->size = fs->size;
|
||||
st->modtime = fs->mtime;
|
||||
st->uid = fs->uid;
|
||||
st->gid = fs->gid;
|
||||
st->nlink = fs->nlink;
|
||||
st->type = type;
|
||||
st->etag = NULL;
|
||||
@@ -374,6 +413,17 @@ out:
|
||||
st->etag = c_strdup(fs->etag);
|
||||
}
|
||||
csync_vio_set_file_id(st->file_id, fs->file_id);
|
||||
if (fs->fields & CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADURL) {
|
||||
SAFE_FREE(st->directDownloadUrl);
|
||||
st->directDownloadUrl = c_strdup(fs->directDownloadUrl);
|
||||
}
|
||||
if (fs->fields & CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADCOOKIES) {
|
||||
SAFE_FREE(st->directDownloadCookies);
|
||||
st->directDownloadCookies = c_strdup(fs->directDownloadCookies);
|
||||
}
|
||||
if (fs->fields & CSYNC_VIO_FILE_STAT_FIELDS_PERM) {
|
||||
strncpy(st->remotePerm, fs->remotePerm, REMOTE_PERM_BUF_SIZE);
|
||||
}
|
||||
|
||||
fastout: /* target if the file information is read from database into st */
|
||||
st->phash = h;
|
||||
@@ -419,11 +469,19 @@ int csync_walker(CSYNC *ctx, const char *file, const csync_vio_file_stat_t *fs,
|
||||
|
||||
switch (flag) {
|
||||
case CSYNC_FTW_FLAG_FILE:
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [file_id=%s]", file, fs->file_id);
|
||||
if (ctx->current == REMOTE_REPLICA) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [file_id=%s size=%" PRIu64 "]", file, fs->file_id, fs->size);
|
||||
} else {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [inode=%" PRIu64 " size=%" PRIu64 "]", file, fs->inode, fs->size);
|
||||
}
|
||||
type = CSYNC_FTW_TYPE_FILE;
|
||||
break;
|
||||
case CSYNC_FTW_FLAG_DIR: /* enter directory */
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "directory: %s [file_id=%s]", file, fs->file_id);
|
||||
if (ctx->current == REMOTE_REPLICA) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "directory: %s [file_id=%s]", file, fs->file_id);
|
||||
} else {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "directory: %s [inode=%" PRIu64 "]", file, fs->inode);
|
||||
}
|
||||
type = CSYNC_FTW_TYPE_DIR;
|
||||
break;
|
||||
case CSYNC_FTW_FLAG_NSTAT: /* not statable file */
|
||||
@@ -579,19 +637,27 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
path = filename + ulen;
|
||||
|
||||
/* skip ".csync_journal.db" and ".csync_journal.db.ctmp" */
|
||||
/* Isn't this done via csync_exclude already? */
|
||||
if (c_streq(path, ".csync_journal.db")
|
||||
|| c_streq(path, ".csync_journal.db.ctmp")
|
||||
|| 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);
|
||||
dirent = NULL;
|
||||
SAFE_FREE(filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* == see if really stat has to be called. */
|
||||
fs = csync_vio_file_stat_new();
|
||||
res = csync_vio_stat(ctx, filename, fs);
|
||||
/* Only for the local replica we have to stat(), for the remote one we have all data already */
|
||||
if (ctx->replica == LOCAL_REPLICA) {
|
||||
fs = csync_vio_file_stat_new();
|
||||
res = csync_vio_stat(ctx, filename, fs);
|
||||
} else {
|
||||
fs = dirent;
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if( res == 0) {
|
||||
switch (fs->type) {
|
||||
@@ -623,6 +689,11 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
uint64_t h = c_jhash64((uint8_t *) path, len, 0);
|
||||
etag = csync_statedb_get_etag( ctx, h );
|
||||
|
||||
if(_last_db_return_error(ctx)) {
|
||||
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if( etag ) {
|
||||
SAFE_FREE(fs->etag);
|
||||
fs->etag = etag;
|
||||
@@ -642,12 +713,11 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
rc = fn(ctx, filename, fs, flag);
|
||||
/* this function may update ctx->current and ctx->read_from_db */
|
||||
|
||||
if (ctx->current_fs && previous_fs && ctx->current_fs->child_modified) {
|
||||
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 */
|
||||
if (ctx->replica == LOCAL_REPLICA) {
|
||||
csync_vio_file_stat_destroy(fs);
|
||||
}
|
||||
|
||||
csync_vio_file_stat_destroy(fs);
|
||||
|
||||
if (rc < 0) {
|
||||
if (CSYNC_STATUS_IS_OK(ctx->status_code)) {
|
||||
ctx->status_code = CSYNC_STATUS_UPDATE_ERROR;
|
||||
@@ -657,7 +727,7 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (flag == CSYNC_FTW_FLAG_DIR && depth
|
||||
if (flag == CSYNC_FTW_FLAG_DIR && depth && rc == 0
|
||||
&& (!ctx->current_fs || ctx->current_fs->instruction != CSYNC_INSTRUCTION_IGNORE)) {
|
||||
rc = csync_ftw(ctx, filename, fn, depth - 1);
|
||||
if (rc < 0) {
|
||||
@@ -670,12 +740,21 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
ctx->current_fs->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
ctx->current_fs->should_update_etag = true;
|
||||
}
|
||||
|
||||
if (ctx->current_fs && previous_fs && ctx->current_fs->has_ignored_files) {
|
||||
/* If a directory has ignored files, put the flag on the parent directory as well */
|
||||
previous_fs->has_ignored_files = ctx->current_fs->has_ignored_files;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
&& (ctx->current_fs->instruction == CSYNC_INSTRUCTION_EVAL ||
|
||||
ctx->current_fs->instruction == CSYNC_INSTRUCTION_NEW ||
|
||||
ctx->current_fs->instruction == CSYNC_INSTRUCTION_EVAL_RENAME)) {
|
||||
ctx->current_fs->instruction == CSYNC_INSTRUCTION_NEW)) {
|
||||
ctx->current_fs->should_update_etag = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -128,59 +128,6 @@ void csync_win32_set_file_hidden( const char *file, bool h ) {
|
||||
#endif
|
||||
}
|
||||
|
||||
csync_vio_file_stat_t *csync_vio_convert_file_stat(csync_file_stat_t *st) {
|
||||
csync_vio_file_stat_t *vfs = NULL;
|
||||
|
||||
if (st == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vfs = csync_vio_file_stat_new();
|
||||
if (vfs == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
vfs->acl = NULL;
|
||||
if (st->pathlen > 0) {
|
||||
vfs->name = c_strdup(st->path);
|
||||
}
|
||||
vfs->uid = st->uid;
|
||||
vfs->gid = st->gid;
|
||||
|
||||
vfs->atime = 0;
|
||||
vfs->mtime = st->modtime;
|
||||
vfs->ctime = 0;
|
||||
|
||||
vfs->size = st->size;
|
||||
vfs->blksize = 0; /* Depricated. */
|
||||
vfs->blkcount = 0;
|
||||
|
||||
vfs->mode = st->mode;
|
||||
vfs->device = 0;
|
||||
vfs->inode = st->inode;
|
||||
vfs->nlink = st->nlink;
|
||||
|
||||
/* fields. */
|
||||
vfs->fields = CSYNC_VIO_FILE_STAT_FIELDS_TYPE
|
||||
+ CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS
|
||||
+ CSYNC_VIO_FILE_STAT_FIELDS_INODE
|
||||
+ CSYNC_VIO_FILE_STAT_FIELDS_LINK_COUNT
|
||||
+ CSYNC_VIO_FILE_STAT_FIELDS_SIZE
|
||||
+ CSYNC_VIO_FILE_STAT_FIELDS_MTIME
|
||||
+ CSYNC_VIO_FILE_STAT_FIELDS_UID
|
||||
+ CSYNC_VIO_FILE_STAT_FIELDS_GID;
|
||||
|
||||
if (st->type == CSYNC_FTW_TYPE_DIR)
|
||||
vfs->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
|
||||
else if (st->type == CSYNC_FTW_TYPE_FILE)
|
||||
vfs->type = CSYNC_VIO_FILE_TYPE_REGULAR;
|
||||
else if (st->type == CSYNC_FTW_TYPE_SLINK)
|
||||
vfs->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK;
|
||||
else
|
||||
vfs->type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
|
||||
|
||||
return vfs;
|
||||
}
|
||||
|
||||
bool (*csync_file_locked_or_open_ext) (const char*) = 0; // filled in by library user
|
||||
void set_csync_file_locked_or_open_ext(bool (*f) (const char*));
|
||||
void set_csync_file_locked_or_open_ext(bool (*f) (const char*)) {
|
||||
@@ -193,7 +140,9 @@ bool csync_file_locked_or_open( const char *dir, const char *fname) {
|
||||
if (!csync_file_locked_or_open_ext) {
|
||||
return false;
|
||||
}
|
||||
asprintf(&tmp_uri, "%s/%s", dir, fname);
|
||||
if (asprintf(&tmp_uri, "%s/%s", dir, fname) < 0) {
|
||||
return -1;
|
||||
}
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "csync_file_locked_or_open %s", tmp_uri);
|
||||
ret = csync_file_locked_or_open_ext(tmp_uri);
|
||||
SAFE_FREE(tmp_uri);
|
||||
|
||||
@@ -32,8 +32,5 @@ void csync_memstat_check(void);
|
||||
|
||||
void csync_win32_set_file_hidden( const char *file, bool hidden );
|
||||
|
||||
/* Convert a csync_file_stat_t to csync_vio_file_stat_t */
|
||||
csync_vio_file_stat_t *csync_vio_convert_file_stat(csync_file_stat_t *st);
|
||||
|
||||
bool csync_file_locked_or_open( const char *dir, const char *fname);
|
||||
#endif /* _CSYNC_UTIL_H */
|
||||
|
||||
@@ -20,8 +20,6 @@ set(CSTDLIB_LINK_LIBRARIES
|
||||
|
||||
set(cstdlib_SRCS
|
||||
c_alloc.c
|
||||
c_dir.c
|
||||
c_file.c
|
||||
c_list.c
|
||||
c_path.c
|
||||
c_rbtree.c
|
||||
|
||||
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* cynapses libc functions
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "c_private.h"
|
||||
#include "c_macro.h"
|
||||
#include "c_alloc.h"
|
||||
#include "c_dir.h"
|
||||
#include "c_string.h"
|
||||
|
||||
int c_mkdirs(const char *path, mode_t mode) {
|
||||
int tmp;
|
||||
csync_stat_t sb;
|
||||
mbchar_t *wpath = c_utf8_to_locale(path);
|
||||
mbchar_t *swpath = NULL;
|
||||
|
||||
if (path == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_tstat(wpath, &sb) == 0) {
|
||||
if (! S_ISDIR(sb.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
c_free_locale_string(wpath);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
tmp = strlen(path);
|
||||
while(tmp > 0 && path[tmp - 1] == '/') --tmp;
|
||||
while(tmp > 0 && path[tmp - 1] != '/') --tmp;
|
||||
while(tmp > 0 && path[tmp - 1] == '/') --tmp;
|
||||
|
||||
if (tmp > 0) {
|
||||
char subpath[tmp + 1];
|
||||
memcpy(subpath, path, tmp);
|
||||
subpath[tmp] = '\0';
|
||||
swpath = c_utf8_to_locale(subpath);
|
||||
if (_tstat(swpath, &sb) == 0) {
|
||||
if (! S_ISDIR(sb.st_mode)) {
|
||||
c_free_locale_string(swpath);
|
||||
c_free_locale_string(wpath);
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
}
|
||||
} else if (errno != ENOENT) {
|
||||
c_free_locale_string(wpath);
|
||||
c_free_locale_string(swpath);
|
||||
return -1;
|
||||
} else if (c_mkdirs(subpath, mode) < 0) {
|
||||
c_free_locale_string(swpath);
|
||||
c_free_locale_string(wpath);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
tmp = _tmkdir(wpath, mode);
|
||||
|
||||
c_free_locale_string(swpath);
|
||||
c_free_locale_string(wpath);
|
||||
|
||||
if ((tmp < 0) && (errno == EEXIST)) {
|
||||
return 0;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
int c_rmdirs(const char *path) {
|
||||
_TDIR *d;
|
||||
struct _tdirent *dp;
|
||||
csync_stat_t sb;
|
||||
char *fname = NULL;
|
||||
mbchar_t *wfname = NULL;
|
||||
mbchar_t *wpath = c_utf8_to_locale(path);
|
||||
char *rd_name = NULL;
|
||||
|
||||
if ((d = _topendir(wpath)) != NULL) {
|
||||
while( _tstat(wpath, &sb) == 0) {
|
||||
/* if we can remove the directory we're done */
|
||||
if (_trmdir(wpath) == 0) {
|
||||
break;
|
||||
}
|
||||
switch (errno) {
|
||||
case ENOTEMPTY:
|
||||
case EEXIST:
|
||||
case EBADF:
|
||||
break; /* continue */
|
||||
default:
|
||||
_tclosedir(d);
|
||||
c_free_locale_string(wpath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((dp = _treaddir(d)) != NULL) {
|
||||
size_t len;
|
||||
rd_name = c_utf8_from_locale(dp->d_name);
|
||||
/* skip '.' and '..' */
|
||||
if( c_streq( rd_name, "." ) || c_streq( rd_name, ".." ) ) {
|
||||
c_free_locale_string(rd_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
len = strlen(path) + strlen(rd_name) + 2;
|
||||
fname = c_malloc(len);
|
||||
if (fname == NULL) {
|
||||
_tclosedir(d);
|
||||
c_free_locale_string(rd_name);
|
||||
c_free_locale_string(wpath);
|
||||
return -1;
|
||||
}
|
||||
snprintf(fname, len, "%s/%s", path, rd_name);
|
||||
wfname = c_utf8_to_locale(fname);
|
||||
|
||||
/* stat the file */
|
||||
if (_tstat(wfname, &sb) != -1) {
|
||||
#ifdef __unix__
|
||||
if (S_ISDIR(sb.st_mode) && !S_ISLNK(sb.st_mode)) {
|
||||
#else
|
||||
if (S_ISDIR(sb.st_mode)) {
|
||||
#endif
|
||||
if (_trmdir(wfname) < 0) { /* can't be deleted */
|
||||
if (errno == EACCES) {
|
||||
_tclosedir(d);
|
||||
SAFE_FREE(fname);
|
||||
c_free_locale_string(wfname);
|
||||
c_free_locale_string(rd_name);
|
||||
c_free_locale_string(wpath);
|
||||
return -1;
|
||||
}
|
||||
c_rmdirs(fname);
|
||||
}
|
||||
} else {
|
||||
_tunlink(wfname);
|
||||
}
|
||||
} /* lstat */
|
||||
SAFE_FREE(fname);
|
||||
c_free_locale_string(wfname);
|
||||
c_free_locale_string(rd_name);
|
||||
} /* readdir */
|
||||
|
||||
_trewinddir(d);
|
||||
}
|
||||
} else {
|
||||
c_free_locale_string(wpath);
|
||||
return -1;
|
||||
}
|
||||
c_free_locale_string(wpath);
|
||||
_tclosedir(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int c_isdir(const char *path) {
|
||||
csync_stat_t sb;
|
||||
mbchar_t *wpath = c_utf8_to_locale(path);
|
||||
int re = 0;
|
||||
|
||||
if (path != NULL) {
|
||||
if (_tstat (wpath, &sb) == 0 && S_ISDIR(sb.st_mode)) {
|
||||
re = 1;
|
||||
}
|
||||
}
|
||||
c_free_locale_string(wpath);
|
||||
return re;
|
||||
}
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* cynapses libc functions
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c_dir.h
|
||||
*
|
||||
* @brief Interface of the cynapses libc directory function
|
||||
*
|
||||
* @defgroup cynDirInternals cynapses libc directory functions
|
||||
* @ingroup cynLibraryAPI
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _C_DIR_H
|
||||
#define _C_DIR_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create parent directories as needed.
|
||||
*
|
||||
* The newly created directory will be owned by the effective user ID of the
|
||||
* process.
|
||||
*
|
||||
* @param path The path to the directory to create.
|
||||
*
|
||||
* @param mode Specifies the permissions to use. It is modified
|
||||
* by the process's umask in the usual way: the
|
||||
* permissions of the created file are (mode & ~umask).
|
||||
*
|
||||
* @return 0 on success, < 0 on error with errno set:
|
||||
* - EACCES The parent directory does not allow write
|
||||
* permission to the process, or one of the directories
|
||||
* - ENOTDIR if durl is not a directory
|
||||
* - EINVAL NULL durl passed or smbc_init not called.
|
||||
* - ENOMEM Insufficient memory was available.
|
||||
*
|
||||
* @see mkdir()
|
||||
*/
|
||||
int c_mkdirs(const char *path, mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Remove the directory and subdirectories including the content.
|
||||
*
|
||||
* This removes all directories and files recursivly.
|
||||
*
|
||||
* @param dir The directory to remove recusively.
|
||||
*
|
||||
* @return 0 on success, < 0 on error with errno set.
|
||||
*/
|
||||
int c_rmdirs(const char *dir);
|
||||
|
||||
/**
|
||||
* @brief Check if a path is a directory.
|
||||
*
|
||||
* @param path The path to check.
|
||||
*
|
||||
* @return 1 if the path is a directory, 0 if the path doesn't exist, is a
|
||||
* file or can't be accessed.
|
||||
*/
|
||||
int c_isdir(const char *path);
|
||||
|
||||
/**
|
||||
* }@
|
||||
*/
|
||||
#endif /* _CDIR_H */
|
||||
|
||||
@@ -1,346 +0,0 @@
|
||||
/*
|
||||
* cynapses libc functions
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "c_file.h"
|
||||
#include "c_string.h"
|
||||
|
||||
#include "c_private.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
/* check if path is a symlink */
|
||||
int c_islink(const char *path) {
|
||||
int re = 0;
|
||||
|
||||
mbchar_t *wpath = 0;
|
||||
DWORD dwAttrs;
|
||||
WIN32_FIND_DATAW FindFileData;
|
||||
HANDLE hFind;
|
||||
|
||||
wpath = c_utf8_to_locale(path);
|
||||
|
||||
dwAttrs = GetFileAttributesW(wpath);
|
||||
if (dwAttrs != INVALID_FILE_ATTRIBUTES) {
|
||||
|
||||
if ((dwAttrs & FILE_ATTRIBUTE_REPARSE_POINT)) {
|
||||
hFind = FindFirstFileW(wpath, &FindFileData );
|
||||
if (hFind != INVALID_HANDLE_VALUE) {
|
||||
if( (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
|
||||
(FindFileData.dwReserved0 & IO_REPARSE_TAG_SYMLINK) ) {
|
||||
re = 1;
|
||||
}
|
||||
}
|
||||
FindClose(hFind);
|
||||
}
|
||||
}
|
||||
c_free_locale_string(wpath);
|
||||
return re;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check if path is a file */
|
||||
int c_isfile(const char *path) {
|
||||
csync_stat_t sb;
|
||||
mbchar_t *wpath = c_utf8_to_locale(path);
|
||||
|
||||
int re = _tstat(wpath, &sb);
|
||||
c_free_locale_string(wpath);
|
||||
|
||||
if (re< 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __unix__
|
||||
if (S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode)) {
|
||||
#else
|
||||
if (S_ISREG(sb.st_mode)) {
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* copy file from src to dst, overwrites dst */
|
||||
#ifdef _WIN32
|
||||
int c_copy(const char* src, const char *dst, mode_t mode) {
|
||||
int rc = -1;
|
||||
mbchar_t *wsrc = 0;
|
||||
mbchar_t *wdst = 0;
|
||||
(void) mode; /* unused on win32 */
|
||||
if(src && dst) {
|
||||
wsrc = c_utf8_to_locale(src);
|
||||
wdst = c_utf8_to_locale(dst);
|
||||
if (CopyFileW(wsrc, wdst, FALSE)) {
|
||||
rc = 0;
|
||||
}
|
||||
c_free_locale_string(wsrc);
|
||||
c_free_locale_string(wdst);
|
||||
if( rc < 0 ) {
|
||||
errno = GetLastError();
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#else
|
||||
int c_copy(const char* src, const char *dst, mode_t mode) {
|
||||
int srcfd = -1;
|
||||
int dstfd = -1;
|
||||
int rc = -1;
|
||||
ssize_t bread, bwritten;
|
||||
csync_stat_t sb;
|
||||
char buf[4096];
|
||||
|
||||
if (c_streq(src, dst)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
srcfd = open(src, O_RDONLY, 0);
|
||||
if (srcfd < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = _tfstat(srcfd, &sb);
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (S_ISDIR(sb.st_mode)) {
|
||||
errno = EISDIR;
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mode == 0) {
|
||||
mode = sb.st_mode;
|
||||
}
|
||||
|
||||
dstfd = open(dst, O_CREAT|O_WRONLY|O_TRUNC, mode);
|
||||
if (dstfd < 0) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = _tfstat(dstfd, &sb);
|
||||
if (rc == 0) {
|
||||
if (S_ISDIR(sb.st_mode)) {
|
||||
errno = EISDIR;
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
bread = read(srcfd, buf, sizeof(buf));
|
||||
if (bread == 0) {
|
||||
/* done */
|
||||
break;
|
||||
} else if (bread < 0) {
|
||||
errno = ENODATA;
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bwritten = write(dstfd, buf, bread);
|
||||
if (bwritten < 0) {
|
||||
errno = ENODATA;
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bread != bwritten) {
|
||||
errno = EFAULT;
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __unix__
|
||||
fsync(dstfd);
|
||||
#endif
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
if (srcfd >= 0) {
|
||||
close(srcfd);
|
||||
}
|
||||
if (dstfd >= 0) {
|
||||
close(dstfd);
|
||||
}
|
||||
if (rc < 0 && c_isfile(dst)) {
|
||||
unlink(dst);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
int c_rename( const char *src, const char *dst ) {
|
||||
mbchar_t *nuri = NULL;
|
||||
mbchar_t *ouri = NULL;
|
||||
int rc = 0;
|
||||
|
||||
nuri = c_utf8_to_locale(dst);
|
||||
if (nuri == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ouri = c_utf8_to_locale(src);
|
||||
if (ouri == NULL) {
|
||||
c_free_locale_string(nuri);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
#define MAX_TRIES_RENAME 3
|
||||
int err = 0;
|
||||
int cnt = 0;
|
||||
|
||||
do {
|
||||
BOOL ok;
|
||||
ok = MoveFileExW(ouri,
|
||||
nuri,
|
||||
MOVEFILE_COPY_ALLOWED +
|
||||
MOVEFILE_REPLACE_EXISTING +
|
||||
MOVEFILE_WRITE_THROUGH);
|
||||
if (!ok) {
|
||||
/* error */
|
||||
err = GetLastError();
|
||||
if( (err == ERROR_ACCESS_DENIED ||
|
||||
err == ERROR_LOCK_VIOLATION ||
|
||||
err == ERROR_SHARING_VIOLATION) && cnt < MAX_TRIES_RENAME ) {
|
||||
cnt++;
|
||||
Sleep(cnt*100);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} while( 1 );
|
||||
if( err != 0 ) {
|
||||
errno = err;
|
||||
rc = -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
rc = rename(ouri, nuri);
|
||||
#endif
|
||||
|
||||
c_free_locale_string(nuri);
|
||||
c_free_locale_string(ouri);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int c_compare_file( const char *f1, const char *f2 ) {
|
||||
mbchar_t *wf1, *wf2;
|
||||
int fd1 = -1, fd2 = -1;
|
||||
size_t size1, size2;
|
||||
char buffer1[BUFFER_SIZE];
|
||||
char buffer2[BUFFER_SIZE];
|
||||
csync_stat_t stat1;
|
||||
csync_stat_t stat2;
|
||||
|
||||
int rc = -1;
|
||||
|
||||
if(f1 == NULL || f2 == NULL) return -1;
|
||||
|
||||
wf1 = c_utf8_to_locale(f1);
|
||||
if(wf1 == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
wf2 = c_utf8_to_locale(f2);
|
||||
if(wf2 == NULL) {
|
||||
c_free_locale_string(wf1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
_fmode = _O_BINARY;
|
||||
#endif
|
||||
|
||||
fd1 = _topen(wf1, O_RDONLY);
|
||||
if(fd1 < 0) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd2 = _topen(wf2, O_RDONLY);
|
||||
if(fd2 < 0) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* compare size first. */
|
||||
rc = _tfstat(fd1, &stat1);
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = _tfstat(fd2, &stat2);
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* if sizes are different, the files can not be equal. */
|
||||
if (stat1.st_size != stat2.st_size) {
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
while( (size1 = read(fd1, buffer1, BUFFER_SIZE)) > 0 ) {
|
||||
size2 = read( fd2, buffer2, BUFFER_SIZE );
|
||||
|
||||
if( size1 != size2 ) {
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
if(memcmp(buffer1, buffer2, size1) != 0) {
|
||||
/* buffers are different */
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
rc = 1;
|
||||
|
||||
out:
|
||||
|
||||
if(fd1 > -1) close(fd1);
|
||||
if(fd2 > -1) close(fd2);
|
||||
|
||||
c_free_locale_string( wf1 );
|
||||
c_free_locale_string( wf2 );
|
||||
return rc;
|
||||
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* cynapses libc functions
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c_file.h
|
||||
*
|
||||
* @brief Interface of the cynapses libc file function
|
||||
*
|
||||
* @defgroup cynFileInternals cynapses libc file functions
|
||||
* @ingroup cynLibraryAPI
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _C_FILE_H
|
||||
#define _C_FILE_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef BUFFER_SIZE
|
||||
#define BUFFER_SIZE (16 * 1024)
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
/**
|
||||
* @brief Check if a path is a link.
|
||||
*
|
||||
* @param path The path to check.
|
||||
*
|
||||
* @return 1 if the path is a symbolic link, 0 if the path doesn't
|
||||
* exist or is something else.
|
||||
*/
|
||||
int c_islink(const char *path);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Check if a path is a regular file or a link.
|
||||
*
|
||||
* @param path The path to check.
|
||||
*
|
||||
* @return 1 if the path is a file, 0 if the path doesn't exist, is
|
||||
* something else or can't be accessed.
|
||||
*/
|
||||
int c_isfile(const char *path);
|
||||
|
||||
/**
|
||||
* @brief copy a file from source to destination.
|
||||
*
|
||||
* @param src Path to the source file
|
||||
* @param dst Path to the destination file
|
||||
* @param mode File creation mode of the destination. If mode is 0 then the
|
||||
* mode from the source will be used.
|
||||
*
|
||||
* @return 0 on success, less than 0 on error with errno set.
|
||||
* EISDIR if src or dst is a file.
|
||||
*/
|
||||
int c_copy(const char *src, const char *dst, mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Compare the content of two files byte by byte.
|
||||
* @param f1 Path of file 1
|
||||
* @param f2 Path of file 2
|
||||
*
|
||||
* @return 0 if the files differ, 1 if the files are equal or -1 on
|
||||
* error with errno set.
|
||||
*/
|
||||
int c_compare_file( const char *f1, const char *f2 );
|
||||
|
||||
/**
|
||||
* @brief move a file from source to destination.
|
||||
*
|
||||
* @param src Path to the source file
|
||||
* @param dst Path to the destination file
|
||||
*
|
||||
* @return 0 on success, less than 0 on error with errno set.
|
||||
*/
|
||||
int c_rename( const char *src, const char *dst );
|
||||
|
||||
/**
|
||||
* }@
|
||||
*/
|
||||
#endif /* _C_FILE_H */
|
||||
|
||||
@@ -23,45 +23,9 @@
|
||||
|
||||
#include "c_macro.h"
|
||||
#include "c_alloc.h"
|
||||
#include "c_dir.h"
|
||||
#include "c_file.h"
|
||||
#include "c_list.h"
|
||||
#include "c_path.h"
|
||||
#include "c_rbtree.h"
|
||||
#include "c_string.h"
|
||||
#include "c_time.h"
|
||||
#include "c_private.h"
|
||||
|
||||
#ifndef UNIT_TESTING
|
||||
#ifdef malloc
|
||||
#undef malloc
|
||||
#endif
|
||||
#define malloc(x) DO_NOT_CALL_MALLOC__USE_C_MALLOC_INSTEAD
|
||||
|
||||
#ifdef calloc
|
||||
#undef calloc
|
||||
#endif
|
||||
#define calloc(x,y) DO_NOT_CALL_CALLOC__USE_C_CALLOC_INSTEAD
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef realloc
|
||||
#undef realloc
|
||||
#endif
|
||||
#define realloc(x,y) DO_NOT_CALL_REALLOC__USE_C_REALLOC_INSTEAD
|
||||
|
||||
#ifdef dirname
|
||||
#undef dirname
|
||||
#endif
|
||||
#define dirname(x) DO_NOT_CALL_MALLOC__USE_C_DIRNAME_INSTEAD
|
||||
|
||||
#ifdef basename
|
||||
#undef basename
|
||||
#endif
|
||||
#define basename(x) DO_NOT_CALL_MALLOC__USE_C_BASENAME_INSTEAD
|
||||
|
||||
#ifdef strdup
|
||||
#undef strdup
|
||||
#endif
|
||||
#define strdup(x) DO_NOT_CALL_STRDUP__USE_C_STRDUP_INSTEAD
|
||||
|
||||
|
||||
@@ -117,81 +117,6 @@ char *c_basename (const char *path) {
|
||||
return newbuf;
|
||||
}
|
||||
|
||||
|
||||
char *c_tmpname(const char *templ) {
|
||||
char *tmp = NULL;
|
||||
char *target = NULL;
|
||||
int rc;
|
||||
int i = 0;
|
||||
|
||||
if (!templ) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* If the template does not contain the XXXXXX it will be appended. */
|
||||
if( !strstr( templ, "XXXXXX" )) {
|
||||
/* split up the path */
|
||||
char *path = c_dirname(templ);
|
||||
char *base = c_basename(templ);
|
||||
|
||||
if (!base) {
|
||||
if (path) {
|
||||
SAFE_FREE(path);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
/* Create real hidden files for unixoide. */
|
||||
if( path ) {
|
||||
#ifdef _WIN32
|
||||
rc = asprintf(&target, "%s/%s.~XXXXXX", path, base);
|
||||
#else
|
||||
rc = asprintf(&target, "%s/.%s.~XXXXXX", path, base);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef _WIN32
|
||||
rc = asprintf(&target, "%s.~XXXXXX", base);
|
||||
#else
|
||||
rc = asprintf(&target, ".%s.~XXXXXX", base);
|
||||
#endif
|
||||
|
||||
}
|
||||
SAFE_FREE(path);
|
||||
SAFE_FREE(base);
|
||||
|
||||
if (rc < 0) {
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
target = c_strdup(templ);
|
||||
}
|
||||
|
||||
if (!target) {
|
||||
goto err;
|
||||
}
|
||||
tmp = strstr( target, "XXXXXX" );
|
||||
if (!tmp) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; ++i) {
|
||||
#ifdef _WIN32
|
||||
/* in win32 MAX_RAND is 32767, thus we can not shift that far,
|
||||
* otherwise the last three chars are 0
|
||||
*/
|
||||
int hexdigit = (rand() >> (i * 2)) & 0x1f;
|
||||
#else
|
||||
int hexdigit = (rand() >> (i * 5)) & 0x1f;
|
||||
#endif
|
||||
tmp[i] = hexdigit > 9 ? hexdigit + 'a' - 10 : hexdigit + '0';
|
||||
}
|
||||
|
||||
return target;
|
||||
|
||||
err:
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int c_parse_uri(const char *uri,
|
||||
char **scheme,
|
||||
char **user, char **passwd,
|
||||
@@ -470,84 +395,3 @@ int c_parse_uri(const char *uri,
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* http://refactormycode.com/codes/1345-extracting-directory-filename-and-extension-from-a-path
|
||||
* Allocate a block of memory that holds the PATHINFO at the beginning
|
||||
* followed by the actual path. Two extra bytes are allocated (+3 instead
|
||||
* of just +1) to deal with shifting the filename and extension to protect the trailing '/'
|
||||
* and the leading '.'. These extra bytes also double as the empty string, as
|
||||
* well as a pad to keep from reading past the memory block.
|
||||
*
|
||||
*/
|
||||
C_PATHINFO * c_split_path(const char* pathSrc)
|
||||
{
|
||||
size_t length = strlen(pathSrc);
|
||||
size_t len=0;
|
||||
C_PATHINFO * pathinfo = (C_PATHINFO *) c_malloc(sizeof(C_PATHINFO) + length + 3);
|
||||
|
||||
if (pathinfo)
|
||||
{
|
||||
char * path = (char *) &pathinfo[1]; // copy of the path
|
||||
char * theEnd = &path[length + 1]; // second null terminator
|
||||
char * extension;
|
||||
char * lastSep;
|
||||
|
||||
// Copy the original string and double null terminate it.
|
||||
strcpy(path, pathSrc);
|
||||
*theEnd = '\0';
|
||||
pathinfo->directory = theEnd; // Assume no path
|
||||
pathinfo->extension = theEnd; // Assume no extension
|
||||
pathinfo->filename = path; // Assume filename only
|
||||
|
||||
lastSep = strrchr(path, '/');
|
||||
if (lastSep)
|
||||
{
|
||||
pathinfo->directory = path; // Pick up the path
|
||||
|
||||
memmove(lastSep + 1, lastSep, strlen(lastSep));
|
||||
*lastSep++ ='/';
|
||||
*lastSep++ ='\0'; // Truncate directory
|
||||
|
||||
pathinfo->filename = lastSep; // Pick up name after path
|
||||
}
|
||||
|
||||
// Start at the second character of the filename to handle
|
||||
// filenames that start with '.' like ".login".
|
||||
// We don't overrun the buffer in the cases of an empty path
|
||||
// or a path that looks like "/usr/bin/" because of the extra
|
||||
// byte.
|
||||
|
||||
|
||||
extension = strrchr(&pathinfo->filename[1], '.');
|
||||
if (extension)
|
||||
{
|
||||
// Shift the extension over to protect the leading '.' since
|
||||
// we need to truncate the filename.
|
||||
memmove(extension + 1, extension, strlen(extension));
|
||||
pathinfo->extension = extension + 1;
|
||||
|
||||
*extension = '\0'; // Truncate filename
|
||||
}
|
||||
else
|
||||
{
|
||||
len=strlen(pathinfo->filename);
|
||||
if(len>1)
|
||||
{
|
||||
//tmp files from kate/kwrite "somefile~": '~' should be the extension
|
||||
if(pathinfo->filename[len-1]=='~')
|
||||
{
|
||||
extension = &pathinfo->filename[len-1];
|
||||
memmove(extension + 1, extension, strlen(extension));
|
||||
pathinfo->extension = extension + 1;
|
||||
*extension = '\0'; // Truncate filename
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return pathinfo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -66,19 +66,6 @@ char *c_dirname(const char *path);
|
||||
*/
|
||||
char *c_basename (const char *path);
|
||||
|
||||
/**
|
||||
* @brief Make a temporary filename.
|
||||
*
|
||||
* @param templ The template to replace. If the template contains six X like
|
||||
* 'XXXXXX', these are replaced by a random string. If not, the
|
||||
* templ is interpreted as a path, and a name to a hidden file
|
||||
* with six random is returned.
|
||||
* The caller has to free the memory.
|
||||
*
|
||||
* @return a poitner to the random hidden filename or NULL.
|
||||
*/
|
||||
char *c_tmpname(const char *templ);
|
||||
|
||||
/**
|
||||
* @brief parse a uri and split it into components.
|
||||
*
|
||||
@@ -120,15 +107,6 @@ typedef struct
|
||||
char * extension;
|
||||
} C_PATHINFO;
|
||||
|
||||
/**
|
||||
* @brief Extracting directory, filename and extension from a path.
|
||||
*
|
||||
* @param pathSrc The path to parse.
|
||||
*
|
||||
* @return Returns a C_PATHINFO structure that should be freed using SAFE_FREE().
|
||||
*/
|
||||
C_PATHINFO * c_split_path(const char* pathSrc);
|
||||
|
||||
|
||||
/**
|
||||
* }@
|
||||
|
||||
@@ -134,6 +134,14 @@ static char *c_iconv(const char* str, enum iconv_direction dir)
|
||||
}
|
||||
#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) {
|
||||
register const char *s1 = a;
|
||||
register const char *s2 = b;
|
||||
@@ -239,69 +247,6 @@ void c_strlist_destroy(c_strlist_t *strlist) {
|
||||
SAFE_FREE(strlist);
|
||||
}
|
||||
|
||||
char *c_strreplace(char *src, const char *pattern, const char *repl) {
|
||||
char *p = NULL;
|
||||
|
||||
while ((p = strstr(src, pattern)) != NULL) {
|
||||
size_t of = p - src;
|
||||
size_t l = strlen(src);
|
||||
size_t pl = strlen(pattern);
|
||||
size_t rl = strlen(repl);
|
||||
|
||||
if (rl > pl) {
|
||||
src = (char *) c_realloc(src, strlen(src) + rl - pl + 1);
|
||||
}
|
||||
|
||||
if (rl != pl) {
|
||||
memmove(src + of + rl, src + of + pl, l - of - pl + 1);
|
||||
}
|
||||
|
||||
strncpy(src + of, repl, rl);
|
||||
}
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
char *c_uppercase(const char* str) {
|
||||
char *new;
|
||||
char *p;
|
||||
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new = c_strdup(str);
|
||||
if (new == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (p = new; *p; p++) {
|
||||
*p = toupper(*p);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
char *c_lowercase(const char* str) {
|
||||
char *new;
|
||||
char *p;
|
||||
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new = c_strdup(str);
|
||||
if (new == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (p = new; *p; p++) {
|
||||
*p = tolower(*p);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
/* Convert a wide multibyte String to UTF8 */
|
||||
char* c_utf8_from_locale(const mbchar_t *wstr)
|
||||
{
|
||||
|
||||
@@ -59,6 +59,17 @@ struct c_strlist_s {
|
||||
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.
|
||||
*
|
||||
@@ -119,37 +130,6 @@ void c_strlist_clear(c_strlist_t *strlist);
|
||||
*/
|
||||
void c_strlist_destroy(c_strlist_t *strlist);
|
||||
|
||||
/**
|
||||
* @breif Replace a string with another string in a source string.
|
||||
*
|
||||
* @param src String to search for pattern.
|
||||
*
|
||||
* @param pattern Pattern to search for in the source string.
|
||||
*
|
||||
* @param repl The string which which should replace pattern if found.
|
||||
*
|
||||
* @return Return a pointer to the source string.
|
||||
*/
|
||||
char *c_strreplace(char *src, const char *pattern, const char *repl);
|
||||
|
||||
/**
|
||||
* @brief Uppercase a string.
|
||||
*
|
||||
* @param str The String to uppercase.
|
||||
*
|
||||
* @return The malloced uppered string or NULL on error.
|
||||
*/
|
||||
char *c_uppercase(const char* str);
|
||||
|
||||
/**
|
||||
* @brief Lowercase a string.
|
||||
*
|
||||
* @param str The String to lowercase.
|
||||
*
|
||||
* @return The malloced lowered string or NULL on error.
|
||||
*/
|
||||
char *c_lowercase(const char* str);
|
||||
|
||||
/**
|
||||
* @brief Convert a platform locale string to utf8.
|
||||
*
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "csync_private.h"
|
||||
#include "csync_util.h"
|
||||
@@ -44,9 +45,12 @@ csync_vio_handle_t *csync_vio_opendir(CSYNC *ctx, const char *name) {
|
||||
if(ctx->remote.read_from_db) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Read from db flag is true, should not!" );
|
||||
}
|
||||
return owncloud_opendir(name);
|
||||
return owncloud_opendir(ctx, name);
|
||||
break;
|
||||
case LOCAL_REPLICA:
|
||||
if( ctx->callbacks.update_callback ) {
|
||||
ctx->callbacks.update_callback(ctx->replica, name, ctx->callbacks.update_callback_userdata);
|
||||
}
|
||||
return csync_vio_local_opendir(name);
|
||||
break;
|
||||
default:
|
||||
@@ -69,7 +73,7 @@ int csync_vio_closedir(CSYNC *ctx, csync_vio_handle_t *dhandle) {
|
||||
if( ctx->remote.read_from_db ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Remote ReadFromDb is true, should not!");
|
||||
}
|
||||
rc = owncloud_closedir(dhandle);
|
||||
rc = owncloud_closedir(ctx, dhandle);
|
||||
break;
|
||||
case LOCAL_REPLICA:
|
||||
rc = csync_vio_local_closedir(dhandle);
|
||||
@@ -87,7 +91,7 @@ csync_vio_file_stat_t *csync_vio_readdir(CSYNC *ctx, csync_vio_handle_t *dhandle
|
||||
if( ctx->remote.read_from_db ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Remote readfromdb is true, should not!");
|
||||
}
|
||||
return owncloud_readdir(dhandle);
|
||||
return owncloud_readdir(ctx, dhandle);
|
||||
break;
|
||||
case LOCAL_REPLICA:
|
||||
return csync_vio_local_readdir(dhandle);
|
||||
@@ -106,7 +110,8 @@ int csync_vio_stat(CSYNC *ctx, const char *uri, csync_vio_file_stat_t *buf) {
|
||||
|
||||
switch(ctx->replica) {
|
||||
case REMOTE_REPLICA:
|
||||
rc = owncloud_stat(uri, buf);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "ERROR: Cannot call remote stat, not implemented");
|
||||
assert(ctx->replica != REMOTE_REPLICA);
|
||||
break;
|
||||
case LOCAL_REPLICA:
|
||||
rc = csync_vio_local_stat(uri, buf);
|
||||
@@ -121,21 +126,9 @@ int csync_vio_stat(CSYNC *ctx, const char *uri, csync_vio_file_stat_t *buf) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *csync_vio_get_status_string(CSYNC *ctx) {
|
||||
if(ctx->error_string) {
|
||||
return ctx->error_string;
|
||||
}
|
||||
return owncloud_error_string();
|
||||
}
|
||||
|
||||
int csync_vio_set_property(CSYNC* ctx, const char* key, void* data) {
|
||||
(void) ctx;
|
||||
return owncloud_set_property(key, data);
|
||||
}
|
||||
|
||||
int csync_vio_commit(CSYNC *ctx) {
|
||||
(void) ctx;
|
||||
return owncloud_commit();
|
||||
return owncloud_error_string(ctx);
|
||||
}
|
||||
|
||||
@@ -39,10 +39,7 @@ csync_vio_file_stat_t *csync_vio_readdir(CSYNC *ctx, csync_vio_handle_t *dhandle
|
||||
|
||||
int csync_vio_stat(CSYNC *ctx, const char *uri, csync_vio_file_stat_t *buf);
|
||||
|
||||
int csync_vio_set_property(CSYNC *ctx, const char *key, void *data);
|
||||
|
||||
char *csync_vio_get_status_string(CSYNC *ctx);
|
||||
|
||||
int csync_vio_commit(CSYNC *ctx);
|
||||
|
||||
#endif /* _CSYNC_VIO_H */
|
||||
|
||||
@@ -22,14 +22,8 @@
|
||||
#include "vio/csync_vio_file_stat.h"
|
||||
|
||||
csync_vio_file_stat_t *csync_vio_file_stat_new(void) {
|
||||
csync_vio_file_stat_t *file_stat = NULL;
|
||||
|
||||
file_stat = (csync_vio_file_stat_t *) c_malloc(sizeof(csync_vio_file_stat_t));
|
||||
if (file_stat == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
file_stat->etag = NULL;
|
||||
memset(file_stat->file_id, 0, FILE_ID_BUF_SIZE+1);
|
||||
csync_vio_file_stat_t *file_stat = (csync_vio_file_stat_t *) c_malloc(sizeof(csync_vio_file_stat_t));
|
||||
ZERO_STRUCTP(file_stat);
|
||||
return file_stat;
|
||||
}
|
||||
|
||||
@@ -39,15 +33,11 @@ void csync_vio_file_stat_destroy(csync_vio_file_stat_t *file_stat) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (file_stat->fields & CSYNC_VIO_FILE_STAT_FIELDS_SYMLINK_NAME) {
|
||||
SAFE_FREE(file_stat->u.symlink_name);
|
||||
}
|
||||
if (file_stat->fields & CSYNC_VIO_FILE_STAT_FIELDS_CHECKSUM) {
|
||||
SAFE_FREE(file_stat->u.checksum);
|
||||
}
|
||||
if (file_stat->fields & CSYNC_VIO_FILE_STAT_FIELDS_ETAG) {
|
||||
SAFE_FREE(file_stat->etag);
|
||||
}
|
||||
SAFE_FREE(file_stat->directDownloadUrl);
|
||||
SAFE_FREE(file_stat->directDownloadCookies);
|
||||
SAFE_FREE(file_stat->name);
|
||||
SAFE_FREE(file_stat);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
|
||||
#define FILE_ID_BUF_SIZE 21
|
||||
|
||||
// currently specified at https://github.com/owncloud/core/issues/8322 are 9 to 10
|
||||
#define REMOTE_PERM_BUF_SIZE 15
|
||||
|
||||
typedef struct csync_vio_file_stat_s csync_vio_file_stat_t;
|
||||
|
||||
enum csync_vio_file_flags_e {
|
||||
@@ -56,48 +59,44 @@ enum csync_vio_file_type_e {
|
||||
enum csync_vio_file_stat_fields_e {
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_NONE = 0,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_TYPE = 1 << 0,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS = 1 << 1,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_MODE = 1 << 1, // local POSIX mode
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_FLAGS = 1 << 2,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_DEVICE = 1 << 3,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_INODE = 1 << 4,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_LINK_COUNT = 1 << 5,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_SIZE = 1 << 6,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_BLOCK_COUNT = 1 << 7, /* will be removed */
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_BLOCK_SIZE = 1 << 8, /* will be removed */
|
||||
// CSYNC_VIO_FILE_STAT_FIELDS_BLOCK_COUNT = 1 << 7, /* will be removed */
|
||||
// CSYNC_VIO_FILE_STAT_FIELDS_BLOCK_SIZE = 1 << 8, /* will be removed */
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_ATIME = 1 << 9,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_MTIME = 1 << 10,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_CTIME = 1 << 11,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_SYMLINK_NAME = 1 << 12,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_CHECKSUM = 1 << 13,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_ACL = 1 << 14,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_UID = 1 << 15,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_GID = 1 << 16,
|
||||
// CSYNC_VIO_FILE_STAT_FIELDS_SYMLINK_NAME = 1 << 12,
|
||||
// CSYNC_VIO_FILE_STAT_FIELDS_CHECKSUM = 1 << 13,
|
||||
// CSYNC_VIO_FILE_STAT_FIELDS_ACL = 1 << 14,
|
||||
// CSYNC_VIO_FILE_STAT_FIELDS_UID = 1 << 15,
|
||||
// CSYNC_VIO_FILE_STAT_FIELDS_GID = 1 << 16,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_ETAG = 1 << 17,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_FILE_ID = 1 << 18
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_FILE_ID = 1 << 18,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADURL = 1 << 19,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADCOOKIES = 1 << 20,
|
||||
CSYNC_VIO_FILE_STAT_FIELDS_PERM = 1 << 21 // remote oC perm
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct csync_vio_file_stat_s {
|
||||
union {
|
||||
char *symlink_name;
|
||||
char *checksum;
|
||||
} u;
|
||||
|
||||
void *acl;
|
||||
char *name;
|
||||
char *etag;
|
||||
char *etag; // FIXME: Should this be inlined like file_id and perm?
|
||||
char file_id[FILE_ID_BUF_SIZE+1];
|
||||
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
char *directDownloadUrl;
|
||||
char *directDownloadCookies;
|
||||
char remotePerm[REMOTE_PERM_BUF_SIZE+1];
|
||||
|
||||
time_t atime;
|
||||
time_t mtime;
|
||||
time_t ctime;
|
||||
|
||||
int64_t size;
|
||||
int64_t blksize; /* will be removed in future, not used in csync */
|
||||
unsigned long blkcount; /* will be removed in future, not used in csync */
|
||||
|
||||
mode_t mode;
|
||||
|
||||
@@ -109,10 +108,6 @@ struct csync_vio_file_stat_s {
|
||||
enum csync_vio_file_type_e type;
|
||||
|
||||
enum csync_vio_file_flags_e flags;
|
||||
|
||||
void *reserved1;
|
||||
void *reserved2;
|
||||
void *reserved3;
|
||||
};
|
||||
|
||||
csync_vio_file_stat_t *csync_vio_file_stat_new(void);
|
||||
|
||||
@@ -227,9 +227,6 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_FLAGS;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
|
||||
|
||||
buf->mode = 666;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS;
|
||||
|
||||
buf->device = fileInfo.dwVolumeSerialNumber;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_DEVICE;
|
||||
|
||||
@@ -240,7 +237,7 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
/* printf("Index: %I64i\n", FileIndex.QuadPart); */
|
||||
buf->inode = FileIndex.QuadPart;
|
||||
|
||||
buf->size = (fileInfo.nFileSizeHigh * (int64_t)(MAXDWORD+1)) + fileInfo.nFileSizeLow;
|
||||
buf->size = (fileInfo.nFileSizeHigh * ((int64_t)(MAXDWORD)+1)) + fileInfo.nFileSizeLow;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
|
||||
|
||||
/* Get the file time with a win32 call rather than through stat. See
|
||||
@@ -316,7 +313,7 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
|
||||
|
||||
buf->mode = sb.st_mode;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MODE;
|
||||
|
||||
if (buf->type == CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK) {
|
||||
/* FIXME: handle symlink */
|
||||
@@ -332,11 +329,6 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
buf->inode = sb.st_ino;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_INODE;
|
||||
|
||||
/* Both values are only initialized to zero as they are not used in csync */
|
||||
/* They are deprecated and will be rmemoved later. */
|
||||
buf->blksize = 0;
|
||||
buf->blkcount = 0;
|
||||
|
||||
buf->atime = sb.st_atime;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ATIME;
|
||||
|
||||
@@ -349,12 +341,6 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
buf->nlink = sb.st_nlink;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_LINK_COUNT;
|
||||
|
||||
buf->uid = sb.st_uid;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_UID;
|
||||
|
||||
buf->gid = sb.st_gid;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_GID;
|
||||
|
||||
buf->size = sb.st_size;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
|
||||
|
||||
|
||||
@@ -21,8 +21,6 @@ set(TEST_TARGET_LIBRARIES ${TORTURE_LIBRARY})
|
||||
|
||||
# std
|
||||
add_cmocka_test(check_std_c_alloc std_tests/check_std_c_alloc.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_std_c_dir std_tests/check_std_c_dir.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_std_c_file std_tests/check_std_c_file.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_std_c_jhash std_tests/check_std_c_jhash.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_std_c_list std_tests/check_std_c_list.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_std_c_path std_tests/check_std_c_path.c ${TEST_TARGET_LIBRARIES})
|
||||
|
||||
@@ -36,9 +36,6 @@ static void setup(void **state) {
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = csync_set_config_dir(csync, "/tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = csync;
|
||||
}
|
||||
|
||||
@@ -55,9 +52,6 @@ static void setup_module(void **state) {
|
||||
rc = csync_create(&csync, "/tmp/check_csync1", "dummy://foo/bar");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = csync_set_config_dir(csync, "/tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = csync_init(csync);
|
||||
*state = csync;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user