Comparar commits

..

183 Commits

Autor SHA1 Mensagem Data
Markus Goetz 5ef7d174b8 Excludes: Use QRegularExpression for speedup WiP 2016-06-23 14:44:28 +02:00
Christian Kamm 7601783553 Fix Qt4 build 2016-06-22 15:47:33 +02:00
Christian Kamm c0b0bd5b63 owncloudcmd: Fix --exclude regression
It's ok if the system exclude file is missing when --exclude is
specified explicitly.
2016-06-22 15:30:20 +02:00
Jenkins for ownCloud 28d86cee17 [tx-robot] updated from transifex 2016-06-22 02:18:48 -04:00
ckamm 32bb8295a2 csync: Use the full file stat destructors (#4992)
* For csync_file_stat_t and csync_vio_file_stat_t
* Add original_name to the vio file stat destructor
2016-06-21 12:06:21 +02:00
Jocelyn Turcotte 5d71ad83ec Fix the Qt4 build
QSharedPointer::reset doesn't exist in Qt4.
2016-06-21 12:04:26 +02:00
Markus Goetz ab24980001 Merge pull request #4979 from jturcotte/2.2
Memory improvements during propagation
2016-06-21 10:00:41 +02:00
ckamm 07dea72c37 Setup csync logging earlier (#4991)
We were missing some csync related log output during startup.

Discovered in #4967
2016-06-21 09:58:53 +02:00
Jenkins for ownCloud a734be347b [tx-robot] updated from transifex 2016-06-21 02:18:36 -04:00
Daniel Molkentin 1443ddc7c9 This branch is headed towards 2.2.3 now 2016-06-20 17:42:19 +02:00
Klaas Freitag 191177ff22 excludes: Only log if the pattern was really logged. (#4989) 2016-06-20 15:50:20 +02:00
ckamm 43a2aec92b Performance: Don't redundantly add the same exclude files #4967 (#4988)
Excludes: Don't redundantly add the same exclude files #4967, Never accept duplicate exclude patterns #4967
2016-06-20 15:14:13 +02:00
Jenkins for ownCloud c848097c6b [tx-robot] updated from transifex 2016-06-20 02:18:29 -04:00
Jenkins for ownCloud 096e2cf233 [tx-robot] updated from transifex 2016-06-19 02:18:34 -04:00
Jenkins for ownCloud 7181aedb4b [tx-robot] updated from transifex 2016-06-18 02:18:33 -04:00
Jocelyn Turcotte edfd75949d Reduce the memory usage of the StopWatch during propagation
Use a QMap to avoid using a full hashtable for only a few entries, and
clear the QMap once we're done with the measuring. This saves a few
hundred bytes per job during propagation that would otherwise only be
freed at the end of the sync.
2016-06-17 19:20:53 +02:00
Jocelyn Turcotte 7fb134b4e0 Delete the ComputeChecksum object when the job is finished
Each object takes almost 1k and we don't need it once the propagation is
done.
2016-06-17 19:20:53 +02:00
Jocelyn Turcotte 87e3553c85 Prevent the sync protocol widget from over-using memory
During propagation, we create a line for each file, taking memory, but
we delete all lines passed 2000 right at the beginning of the next sync.
Since the user has little chances of being able to read past those 2000
lines in the log, we might as well keep it capped at 2000 also during
propagation to prevent it from eating memory.
2016-06-17 19:20:53 +02:00
Jocelyn Turcotte 6f3aaecb78 Fix a crash on if shutting down during propagation
The SyncRunFileLog owned by the Folder must be destroyed after the
SyncEngine since the SyncEngine will abort during destruction, resulting
in all jobs being aborted.

It's possible that this crash only happens with a debug build.
2016-06-17 19:20:52 +02:00
Markus Goetz 40e3653722 VERSION.cmake: This is 2.2.2 2016-06-17 10:31:30 +02:00
Jenkins for ownCloud 5a4f50a0ff [tx-robot] updated from transifex 2016-06-17 02:19:00 -04:00
Jocelyn Turcotte 3342ebfcc5 SocketAPI: Push new status of dirty files regardless when not synced (#4970)
The FolderWatcher inserts files to be marked as SYNC and we
currently assume that all file statuses will be updated by the
following sync. It's however possible that the FolderWatcher
notify us of a change that csync won't consider necessary to
propagate, in which case a new status wouldn't be pushed and
the file manager would continue showing this file as syncing.

Re-push the file status when emptying the dirty files list
before propagating to avoid this issue, most likely the OK
status.
2016-06-16 15:27:10 +02:00
Olivier Goffart b4900d60b7 Checksum speedup. (#4968)
No need to allocate (and initialize to 0) a 10 MiB buffer for each files, even
when most files are much smaller than that.
So make sure the buffer that we allocate is not bigger than the file size.
And Also 10 MiB is a bit big for a buffer. 500 KiB should be more than enough.
(Too big allocations can cause problem because of memory fragmentation and such)
2016-06-16 08:28:30 +02:00
Olivier Goffart 92309013da SyncEngine: make abort and closing more robust
We first need to set the abort flag to csync and then aborting the discovery
job, otherwise, the discovery thread could start a new job in the mean time.

We also need to make sure that the thread has existed before we destroy the
exclude list.
2016-06-16 08:26:33 +02:00
Jenkins for ownCloud 4895589e4d [tx-robot] updated from transifex 2016-06-16 02:18:46 -04:00
Jocelyn Turcotte 05d199881e Merge pull request #4971 from owncloud/fixAccountHandleSslErrorsCrash
Attempt to fix the Account::slotHandleSslErrors crash
2016-06-15 18:53:47 +02:00
Jocelyn Turcotte 147cf798a6 Attempt to fix the Account::slotHandleSslErrors crash
Events from the crash reporter suggest that the QNAM and its
child replies might get deleted before returning from this method
and the only possible cause we can see is that the inner event
loop has something to do with it.

Try keeping a ref on the QNAM while in this method to make sure
that it won't get deleted by the inner event loop.
2016-06-15 18:12:02 +02:00
Jocelyn Turcotte d40c56eda5 Account: Use smart pointers to hold its credentials and QNAM objects
Also make sure that both use QObject::deleteLater as their delete
function.
2016-06-15 18:12:01 +02:00
Olivier Goffart 6dade0b114 PropagateUpload: fix crash in PUTFileJob::slotTimeout
Same fix as in commit 60c101d9

From the crash reporter:

Crash
EXCEPTION_ACCESS_VIOLATION_READ at 0x4
qnetworkreply.cpp in QNetworkReply::request at line 476
propagateupload.cpp in OCC::PUTFileJob::slotTimeout at line 100
moc_abstractnetworkjob.cpp in OCC::AbstractNetworkJob::qt_static_metacall at line 98
qobject.cpp in QMetaObject::activate at line 3716
moc_qtimer.cpp in QTimer::timeout at line 192
qtimer.cpp in QTimer::timerEvent at line 247
qobject.cpp in QObject::event at line 1267
qapplication.cpp in QApplicationPrivate::notify_helper at line 3722
qapplication.cpp in QApplication::notify at line 3505
qcoreapplication.cpp in QCoreApplication::notifyInternal at line 932
2016-06-15 14:32:25 +02:00
Jenkins for ownCloud 5de44407bf [tx-robot] updated from transifex 2016-06-15 02:18:44 -04:00
Jenkins for ownCloud 2df741e456 [tx-robot] updated from transifex 2016-06-14 02:18:36 -04:00
Olivier Goffart 8b5f71f49e Fix docker build instruction for windows 2016-06-13 15:30:39 +02:00
Jenkins for ownCloud 77791ccb34 [tx-robot] updated from transifex 2016-06-13 02:18:35 -04:00
Jenkins for ownCloud a6e4f9939c [tx-robot] updated from transifex 2016-06-12 02:18:35 -04:00
Jenkins for ownCloud 523cdff1cf [tx-robot] updated from transifex 2016-06-11 02:18:33 -04:00
Jenkins for ownCloud c4d6277ce3 [tx-robot] updated from transifex 2016-06-10 02:18:39 -04:00
Jenkins for ownCloud 70196eb48c [tx-robot] updated from transifex 2016-06-09 02:26:12 -04:00
Jenkins for ownCloud 9b249716a3 [tx-robot] updated from transifex 2016-06-08 02:19:30 -04:00
Jürgen Weigert a4b46db91e Merge pull request #4949 from owncloud/jnweiger-tray-patch-patch-patch
Update accountsettings.cpp fixing the tray-patch
2016-06-07 15:59:53 +02:00
Jürgen Weigert ebc44fa494 Update accountsettings.cpp 2016-06-07 14:21:50 +02:00
ckamm 355a8a0a27 Workaround for Ubuntu 16.04 tray issue #4944 (#4947) 2016-06-07 11:48:25 +02:00
Jenkins for ownCloud ab050f9093 [tx-robot] updated from transifex 2016-06-07 02:19:44 -04:00
Jenkins for ownCloud bf9cffe4b3 [tx-robot] updated from transifex 2016-06-06 02:19:25 -04:00
Carla Schroder 43f727cf69 fix win install instructions: build path and docker image name (#4901) 2016-06-05 10:56:56 +02:00
Jenkins for ownCloud 256331fbaa [tx-robot] updated from transifex 2016-06-05 02:18:37 -04:00
Jenkins for ownCloud 32e6585ae6 [tx-robot] updated from transifex 2016-06-04 02:19:18 -04:00
Olivier Goffart d072e4a678 Fix compilation on windows 2016-06-03 13:28:53 +02:00
Olivier Goffart b99c8fe28b Folder: fix removing folder with escaped characters (#4943)
FolderDefinition::save and load escapes the alias. We also need to escape
it when we remove it.
New folder can't be created with alias that needs escaping, but old folder
from old config may still exist, and we must allow user to delete them.
2016-06-03 13:10:01 +02:00
Olivier Goffart 5a3120bd52 Folder: Ignore change from the watcher if the file has not changed its mtime or size (#4942)
For issue #4927:
On Windows 10, we get a notification after the sync is finished for file that were
just downloaded. The guard we have against our "own changes" are only working when
the sync is running and the OwncloudPropagator still alive.
2016-06-03 13:06:11 +02:00
Jenkins for ownCloud 9ea69be6ab [tx-robot] updated from transifex 2016-06-03 02:19:51 -04:00
Daniel Molkentin 801cb42d57 Merge pull request #4939 from owncloud/osx_filewatcher_fix
OS X filewatcher fix
2016-06-02 18:37:38 +02:00
Markus Goetz 51f8a59a9a OS X: White-list the folder watcher enums
I got syncs triggered for even opening a file by double clicking it in Finder
and having launched Preview.app (e.g. for JPEG files).
2016-06-02 18:20:07 +02:00
Daniel Molkentin ebbe5acf2b Merge pull request #4938 from owncloud/fix_4840
GUI: don't force the environment variable for high DPI on linux.
2016-06-02 18:13:25 +02:00
Olivier Goffart 6ccd9e872d GUI: don't force the environment variable for high DPI on linux.
Setting the Environment variable only for owncloud makes in inconsistant with
other Qt application running at the same time.

The users can still set it themself for the whole desktop if they wish.

Addresses #4840
2016-06-02 17:57:10 +02:00
Daniel Molkentin da69756bb0 Merge pull request #4935 from owncloud/fix_updater_memleak
Fix memleak in updater
2016-06-02 15:36:49 +02:00
Daniel Molkentin 1787da8a9d Fix memleak in updater 2016-06-02 15:03:52 +02:00
Giovanni Capuano f0f82d02ff Fix link to the binary packages in README.md 2016-06-02 14:55:48 +02:00
Jenkins for ownCloud ff20cd4d57 [tx-robot] updated from transifex 2016-06-02 02:19:35 -04:00
Jenkins for ownCloud 9ab812f89b [tx-robot] updated from transifex 2016-06-01 02:19:17 -04:00
Markus Goetz de82d8fcdb QNAM: Try to workaround missing Qt patches #4720 #3888 #4051
We try this on all platforms now so we have more consistent behaviour.
2016-05-31 10:26:52 +02:00
Stephen Colebrook af2b712dc6 Search results are filtered by server. Don't filter a second time.
Also allows searching on attributes other than displayname in ldap
configurations. Search results match web and mobile apps.
2016-05-31 09:46:52 +02:00
Markus Goetz a507558dee Connectivity: Reduce ETag job timeout to 60 sec #4275
Before it used the default job timeout
2016-05-31 09:35:47 +02:00
Jenkins for ownCloud e73c3199c0 [tx-robot] updated from transifex 2016-05-31 02:20:28 -04:00
Markus Goetz d88ab4653b Connectivity: Delete job on timeout #4275
This was not done if there was no reply
2016-05-30 18:15:41 +02:00
Klaas Freitag 9a2450c4c1 Update changelog for 2.2.1 2016-05-30 17:19:40 +02:00
Daniel Molkentin 3c1f5e662f Remove stray file 2016-05-30 12:05:22 +02:00
Daniel Molkentin 100ee69ddd Merge pull request #4923 from RobinGeuze/2.2
Fix Qt4 build
2016-05-30 11:50:50 +02:00
Robin Geuze d45d6ca9da Fix Qt4 build 2016-05-30 09:55:45 +02:00
Daniel Molkentin 2608c7007e Merge pull request #4922 from owncloud/fix_4840
Don't try to determine pixel ratio with Qt < 5.6.0
2016-05-30 09:20:50 +02:00
Jenkins for ownCloud 06a88ea9a4 [tx-robot] updated from transifex 2016-05-30 02:41:51 -04:00
Daniel Molkentin 0194ebb222 Don't try to determine pixel ratio with Qt < 5.6.0
This seems to be broken. Worst case users can still
set it manually

Addresses #4840
2016-05-30 08:27:57 +02:00
Jenkins for ownCloud dc654ac846 [tx-robot] updated from transifex 2016-05-29 02:18:52 -04:00
Jenkins for ownCloud 370fd5062c [tx-robot] updated from transifex 2016-05-28 02:19:09 -04:00
Daniel Molkentin 00d20b4a42 Merge pull request #4913 from owncloud/normalize_name_in_filestatus
Undo regression caused by 727e73d
2016-05-27 18:08:08 +02:00
Daniel Molkentin a2b238e2e5 Undo regression caused by 727e73d
normalization to NFC is still required. Mac OS API will not take
care of that by default.

Resolves #4884
2016-05-27 16:03:59 +02:00
ckamm 0e2c16e827 Certs: Re-ask for different cert after rejection #4898 (#4911)
Previously rejecting any kind of certificate meant that the user
was never asked again, even if the certificate changed.

Now we keep track of which certificates were rejected and ask again
if the ones mentioned in the ssl errors change.

mitmproxy is excellent for testing this.
2016-05-27 12:08:42 +02:00
ckamm b9fdae6d67 Progress: Don't count items without propagation jobs #4856 (#4910)
* Progress: Don't count dirs without propagation jobs #4856

These directory SyncFileItems are necessary for bookkeeping
but should not influence the progress display at all.

* Progress: Skip ignored files #4856
2016-05-27 10:52:00 +02:00
Jenkins for ownCloud c34115610e [tx-robot] updated from transifex 2016-05-27 02:19:21 -04:00
Olivier Goffart 275ad1e157 Utility: Better fix for the translation of minutes, seconds, ...
The plural was not translated because of QTBUG-3945. Work around it.
Issue #4855
2016-05-26 12:17:16 +02:00
Jenkins for ownCloud 1855950fa1 [tx-robot] updated from transifex 2016-05-26 02:33:30 -04:00
Olivier Goffart fff5c280b3 SyncEngine: cleanup setting isDirectory 2016-05-25 16:27:40 +02:00
Olivier Goffart e960b265a8 Merge remote-tracking branch '2.1' into 2.2 2016-05-25 16:23:58 +02:00
Olivier Goffart f6b35e5d58 SyncEngine: invalid the blacklist entry when the rename destination change
The problem in this case is if we rename the file "xxx" to "invalid\file".
The rename will fail because the new filename constains a slash, and it
will be blacklisted.
But then if the user re-rename the file to "valid_name", then we should
invalidate the blacklist entry and retry to upload. But we did not do
that because renaming don't change the mtime and we did not store the
rename target in the database

IL issue 558
2016-05-25 15:32:45 +02:00
Jenkins for ownCloud 1d93af5f64 [tx-robot] updated from transifex 2016-05-25 02:19:18 -04:00
Markus Goetz 75efa8b252 sqlite: Update bundled version to 3.13.0
For OS X and Windows.
2016-05-24 17:27:31 +02:00
Markus Goetz 009a0b03da Add ChangeLog for 2.2.1 2016-05-24 17:04:04 +02:00
Jenkins for ownCloud 8379a36a75 [tx-robot] updated from transifex 2016-05-24 07:40:14 -04:00
Daniel Molkentin 2f1a40ff7c Travis coverity: Enforce Ubuntu 14.04 env, fix repo 2016-05-24 11:30:03 +02:00
Daniel Molkentin c041ca6163 Fix pot. mem leak found by coverity (CID 96004) 2016-05-24 11:21:33 +02:00
Daniel Molkentin eacc0c8bd6 Fix pot. mem leak found by coverity (CID 12900) 2016-05-24 11:21:33 +02:00
Jenkins for ownCloud 171de99e00 [tx-robot] updated from transifex 2016-05-24 02:19:53 -04:00
ckamm bf02ccc1e8 Remember to upload files that are locked during a sync run (#4865)
See owncloud/enterprise#1342
2016-05-23 09:03:03 +02:00
Jenkins for ownCloud 7ba961c21a [tx-robot] updated from transifex 2016-05-23 02:19:05 -04:00
Jenkins for ownCloud cb7be78352 [tx-robot] updated from transifex 2016-05-22 02:19:13 -04:00
Jenkins for ownCloud 6cb194e0d5 [tx-robot] updated from transifex 2016-05-21 02:19:09 -04:00
Markus Goetz 552ba94c41 SyncEngine: Set isDirectory before syncItemDiscovered
(cherry picked from commit fc1933803e)
2016-05-20 17:00:22 +02:00
Markus Goetz fc1933803e SyncEngine: Set isDirectory before syncItemDiscovered 2016-05-20 16:58:44 +02:00
Markus Goetz 46e4ec3183 Checksums: Use SHA1 like in >=2.2 2016-05-20 16:31:47 +02:00
Olivier Goffart 03e3b3bf50 Upload: put the job in the active list while doing the checksum computation.
This fixes an issue in which too many jobs are started un parallel
while uploading many files, which could cause too much memory usage as the
chunks are stored in memory.

Probably the fix for #4611
2016-05-20 16:28:27 +02:00
Christian Kamm 9aed8dbce8 Checksums: Compute content checksum on download #4375
Cherry-picked from d6d35029
2016-05-20 16:06:30 +02:00
ckamm c6794cd338 Progress info: Reset between syncs #4856 (PR #4872) 2016-05-20 15:07:54 +02:00
Jenkins for ownCloud 65ec1b74d5 [tx-robot] updated from transifex 2016-05-20 02:19:16 -04:00
Jenkins for ownCloud 1a3c9a9c1a [tx-robot] updated from transifex 2016-05-19 02:19:20 -04:00
Markus Goetz a038c99232 Upload: Remove bandwidth quota debug message #4837 2016-05-18 16:18:13 +02:00
Olivier Goffart 30c8fa1c93 Utility: Fix translation of second, minute, hour
Issue #4855

A typo in the context string made the translation lookup fail.
But also the %Ln was not recognized as a plural form by transifex, so only
the singular was translated
2016-05-18 10:52:22 +02:00
Olivier Goffart 010649f997 FolderWizard: remove dead code and fix the alias
Remove a bunch of dead code.

And also set the root folder name properly since alias is gone.

Fix the warning:
QWizard::field: No such field 'alias'
2016-05-18 10:52:22 +02:00
Jenkins for ownCloud 597f2a4dfc [tx-robot] updated from transifex 2016-05-18 02:19:16 -04:00
Olivier Goffart cf1fe690a3 Shibboleth: Show the inspector if OWNCLOUD_SHIBBOLETH_DEBUG is set
Help to debug https://github.com/owncloud/enterprise/issues/1265
2016-05-17 12:29:20 +02:00
Jenkins for ownCloud 31b27bea38 [tx-robot] updated from transifex 2016-05-17 02:18:59 -04:00
Jenkins for ownCloud 04f99f3bd7 [tx-robot] updated from transifex 2016-05-15 02:19:07 -04:00
Jenkins for ownCloud fbf92ac239 [tx-robot] updated from transifex 2016-05-14 02:19:15 -04:00
hefee 669a72f0e1 A final release version number breaks this regex (#4835)
f.ex. a valid verson nr: 2.2.0
-> fist \d+ = 2
-> second \d+ = 2
-> the last \d+ = 0
-> .+ in not matching, because there is nothing to match
2016-05-13 16:55:11 +02:00
Jenkins for ownCloud 2f0e65d37c [tx-robot] updated from transifex 2016-05-13 02:25:05 -04:00
Olivier Goffart 5676685f58 SyncEngine: Add a compile option so we rename to restoring a move we don't have the permission to do
IL issue 550
2016-05-12 13:15:30 +02:00
Christian Kamm db9ccb40a4 Fix compile with strict C flags 2016-05-12 13:14:40 +02:00
Christian Kamm d4c15d2c38 Ignores: expand escapes #4568
(cherry picked from commit d7bd1300a8)
2016-05-12 11:53:17 +02:00
Hefee edb3759684 For tests we do not need a xserver running.
Use for tests QTEST_GUILESS_MAIN and QTEST_APPLESS_MAIN.
2016-05-12 11:34:21 +02:00
Christian Kamm 0f9c32452c Protocol: Increase width of timestamp column #4721
Since the font metrics aren't reliable on windows, we add some
extra space there.
2016-05-12 10:24:34 +02:00
Daniel Molkentin 45dd1d0acf Bump to 2.2.1 2016-05-12 09:58:12 +02:00
Daniel Molkentin 552af7b94d 2.2.0 final 2016-05-12 09:58:12 +02:00
Christian Kamm 8934979ba1 timeAgo test: Fix for qt4, clean up 2016-05-12 09:25:15 +02:00
Daniel Molkentin b3e16e0eb0 Merge pull request #4825 from owncloud/22-user-manual
[Doc] 2.2 user manual updates
2016-05-12 08:20:55 +02:00
Carla Schroder 7773380deb update file manager screenshot 2016-05-11 12:44:27 -07:00
Carla Schroder e22050a434 updates to 2.2 user manual 2016-05-11 12:37:40 -07:00
Daniel Molkentin 7b0231bfce Merge pull request #4821 from owncloud/notification_doc
Documentation draft to introduce notifications.
2016-05-11 21:16:35 +02:00
Jocelyn Turcotte edc58c045f Fix assert on restore after propagation (#4823)
The assert was there to make sure that this case wasn't happening
to eventually be properly tested. Remove the assert for now but this
codepath should eventually be unit tested using this specific situation.
2016-05-11 18:16:46 +02:00
Klaas Freitag 035058934f Documentation draft to introduce notifications.
Also added a screenshot.
2016-05-11 11:16:08 +02:00
Klaas Freitag 9b1f46e560 Fix exclude unit test, adopt to new Iface of isExcluded. 2016-05-10 16:46:08 +02:00
Klaas Freitag 9e7a8e619b Fix utility test: Pass a command name to do the version check. 2016-05-10 16:26:42 +02:00
Klaas Freitag 9c0cd2b13e Added Changelog for 2.2.0 2016-05-10 15:39:44 +02:00
Daniel Molkentin 58ad781bd4 Update binary submodule 2016-05-10 14:39:22 +02:00
Daniel Molkentin 9d6701ecbe Windows Shell Integration: Fix another spot where the pipe path was constructed manually 2016-05-10 13:49:14 +02:00
Daniel Molkentin d659c54798 Update binary sub module 2016-05-10 10:36:49 +02:00
Daniel Molkentin 0e9170cb36 Windows Shell Integration: Unify path lookups 2016-05-10 10:18:53 +02:00
Markus Goetz 8820bc1c17 Windows: Fix Share menu #4781 2016-05-09 14:37:46 +02:00
Jenkins for ownCloud 74f67c97a9 [tx-robot] updated from transifex 2016-05-09 02:19:15 -04:00
Jenkins for ownCloud fd96b482c5 [tx-robot] updated from transifex 2016-05-07 02:19:16 -04:00
Jocelyn Turcotte 727e73d640 [shell/windows] Fix the windows status push not working (#4784)
Since the windows implementation first does cache lookups using the
path string, directories need to be passed identically as through
RETRIEVE_FILE_STATUS.

Change the convention to never have a trailing slash for directories
in the protocol. This allows the convention to be applied without
having to access the disk (since we'd need to know if the path is
represented by a directory) and also matches the convention of the
rest of the sync engine. Individual file manager plugins are then
responsible of handling pushed paths as not ending with a trailing
slash.

This also:
- Moves the trailing slash removal logic from the SyncFileStatusTracker
  to the SocketApi class
- Remove the unneeded QString::normalized call in fileStatus, since
  this should already be done by the FolderWatcher and plugins
2016-05-06 12:32:01 +02:00
Jenkins for ownCloud d7804d8df3 [tx-robot] updated from transifex 2016-05-06 02:19:00 -04:00
Olivier Goffart 3d9d106bb1 Dolphin plugin: fix build with branding
Make sure that the name of the _export.h file is the same no matter the plugin
2016-05-04 14:19:18 +02:00
Jenkins for ownCloud 15dc3408ef [tx-robot] updated from transifex 2016-05-04 02:19:15 -04:00
Markus Goetz 928643f597 NSIS: Properly uninstall both x64 and x86 DLLs #4762
Viel hilft viel ;-)
2016-05-03 18:35:01 +02:00
Markus Goetz 7110091fdd Qt patches: Update with information about Qt 5.6 2016-05-03 15:16:07 +02:00
Jocelyn Turcotte 064c2b678a Merge branch 'overlayIconFixes' into 2.2 (#4765) 2016-05-03 13:04:34 +02:00
Jocelyn Turcotte e58739de00 [osx] Fix missing overlay icons on client startup
Since the statuses are cached and that we can't invalidate the cache,
sending NOP would need to be overwritten by the default OK status
once the client successfully connected. But instead of remembering
which files we NOPed, rather wait until we are ready to sync before
sending the REGISTER_PATH message to the socket API client. It will
also prevent the client from sending unnecessary RETRIEVE_FILE_STATUS
requests.

Also remove AccountState::canSync, since it does the same as
isConnected and syncing is not an account responsibility.
2016-05-03 13:01:51 +02:00
Jocelyn Turcotte 7c2fdee78b Avoid a SyncFileStatusTracker private overload with the same name
Having an overload as a private function in the same class makes the
code harder to follow. Rename the private fileStatus to syncFileItemStatus.
2016-05-03 13:01:51 +02:00
Jocelyn Turcotte 7bfe46962f Simplify the root status logic
Go through fileStatus like other cases to make sure that all use
cases go through the same code path. This also makes sure to use
lookupProblem which will use lower_bound which is more efficient
for larger sets of sync problems.

This also fixes the issue with lookupProblem that prevented it to
properly match an empty pathToMatch, caused by the fact that the
problem map contains relative paths not starting with a slash.
2016-05-03 13:01:51 +02:00
Jocelyn Turcotte 32b3023a8e Fix the root item sync status #4682
Make sure that we push the new status when the status of the SyncEngine
changed. SyncEngine::started comes a bit late, only when the propagation
starts, although it's better in this case since child folders will
only switch to Sync in aboutToPropagate.

Also fix an issue with SyncEngine::findSyncItem when using an empty
fileName; this would match and return the wrong item, even though
not currently happening with the code since fileStatus won't call
it with an empty fileName anymore.
2016-05-03 13:01:51 +02:00
Jocelyn Turcotte a5df44c757 Fix the sync status push for parent directories #4682
As before, we rely on metadata-update SyncFileItem entries for parent
directories to notify us that a directory contains files to propagate,
and to know when all children were propagated through its itemCompleted
signal.

Those metadata SyncFileItems however have a None direction and we need
to add a explicit directory check to show them as Sync.
This fix also handles new files as well as existing ones, so no need
to keep a separate logic for new files.
2016-05-03 13:01:51 +02:00
Klaas Freitag 641125eac1 Fix nautilus and nemo plugin branding strings. (#4780)
* Fix nautilus and nemo plugin branding strings.

Fix for owncloud/enterprise#1314

* nautilus plugin: Add a comment why the line needs to stay unchanged.
2016-05-03 11:36:56 +02:00
Jenkins for ownCloud d340017a0a [tx-robot] updated from transifex 2016-05-03 02:19:16 -04:00
Olivier Goffart a67173610d Propagator: fix qt4 build
propagatedownload.cpp:712:35: error: 'seenLockedFile' is a protected member of 'OCC::OwncloudPropagator'

Signals are protected in Qt4 but public in Qt5, mark the class accessing it
as friend when compiling with Qt4
2016-05-02 17:34:21 +02:00
Daniel Molkentin e833d01288 Re-Apply: Disambiguate socket API pathes on Windows with user name
Addresses #3411
2016-05-02 16:09:48 +02:00
Olivier Goffart 3047682223 ShareDialog: show the error message in red
Do the visual stuff from designer.
The previous code that was ment to change the color in red did not work
and changed it to gray instead.
Also I don't see why there should be a frame.

Issue #4773
2016-05-02 14:12:04 +02:00
Jenkins for ownCloud c91dd94728 [tx-robot] updated from transifex 2016-05-02 02:19:41 -04:00
Jenkins for ownCloud 52f9f44b51 [tx-robot] updated from transifex 2016-05-01 02:19:18 -04:00
Jenkins for ownCloud 49748191a9 [tx-robot] updated from transifex 2016-04-30 02:19:14 -04:00
ckamm e6b937f508 LockWatcher: Keep an eye on Windows file locks (#4758)
When a conflict-rename or a temporary-rename fails, notify the
LockWatcher. It'll regularly check whether the file has become
accesible again. When it has, another sync is triggered.

owncloud/enterprise#1288
2016-04-29 16:14:18 +02:00
Roeland Douma 31c13f74fb Add spinner during sharee search (#4764)
Fixed #4740

When searching for sharees we should display a loading spinner.
2016-04-29 14:11:27 +02:00
Olivier Goffart be466b47b7 Merge remote-tracking branch 'origin/2.1' into 2.2 2016-04-29 08:52:17 +02:00
Olivier Goffart 11b144957b PropagateDownload: Throw an error if the file is empty while it should not have been (#4753)
If the downloaded file is empty but the PROPFIND previously announced it
should not have been empty, this might mean the file was somehow corrupted
because of a bug on the server and that we should therefore not accept
the file.

Normaly we accept a change between the actual size of the file and what we
got during discovery because the file might have been updated to a new version
inbetween. But after this patch we won't accept the file if it was replaced
by an empty file.

Will help for issue #4583
Also requested by IL for issue 548
2016-04-29 08:49:27 +02:00
Jenkins for ownCloud 817e97c148 [tx-robot] updated from transifex 2016-04-29 02:19:14 -04:00
Markus Goetz 29932004ae Shibboleth: Load username from config for UI (#4751)
For https://github.com/owncloud/enterprise/issues/1034
2016-04-28 14:55:29 +02:00
Daniel Molkentin 6d83e841a9 Merge pull request #4756 from owncloud/revert-4738-fix_3411
Revert "Disambiguate socket API pathes on Windows with user name"
2016-04-28 13:53:06 +02:00
Daniel Molkentin b43a9421d2 Revert "Disambiguate socket API pathes on Windows with user name" 2016-04-28 13:52:15 +02:00
Klaas Freitag e70b78d14b Merge pull request #4738 from owncloud/fix_3411
Disambiguate socket API pathes on Windows with user name
2016-04-28 13:46:10 +02:00
Klaas Freitag 6814342d1f Merge pull request #4748 from owncloud/win_stat_revisited
vio for windows: Use more graceful create file params.
2016-04-28 13:45:30 +02:00
Christian Kamm 68126dcff6 Checksums: Skip uploads of .eml files only #4754
This is a workaround. A correct solution would still update file metadata
such as the mtime. See #4755.
2016-04-28 12:59:39 +02:00
Christian Kamm e7f00339e6 Fix perl tests #4722
* The dav auth realm is "sabre/dav" for newer server versions
* Content checksums are enabled generally, so conflict detection
  is smarter
2016-04-28 10:44:37 +02:00
Christian Kamm a36b4ec863 FolderWizard: Sort remote folders #4612 2016-04-28 09:29:07 +02:00
Christian Kamm 074f8eadb1 Selective sync: Sort folders in FolderStatusModel #4612 2016-04-28 09:29:07 +02:00
Jenkins for ownCloud 6a51ae5b1b [tx-robot] updated from transifex 2016-04-28 02:19:20 -04:00
Christian Kamm af5f2d3860 Protocol: Make timestamp column width fit the text #4721 2016-04-28 07:37:42 +02:00
ckamm 38bad564a0 Merge pull request #4739 from ckamm/trackdirty
Overlay icons: Track touched files #4730
2016-04-28 07:17:17 +02:00
Christian Kamm c2fa3fb4c8 Overlay icons: Track touched files #4730
This uses the file watcher to keep track of files that were modified
in order to assign them the blue icon.

This is transient state that's not persisted across restarts.
2016-04-28 07:16:49 +02:00
Markus Goetz f7082ee3df sqlite: Update to version 3.12.2
For OS X and Windows
2016-04-27 12:22:12 +02:00
Markus Goetz f7c6efb391 ConnectionValidator: Also set short timeout for capabilities job
Default timeout was 5 min.
2016-04-27 12:19:49 +02:00
Klaas Freitag 051a348afd Vio for windows: Removed the overlap param again.
After discussion and studying docs again we agreed that
the parameter is not neccessary here as it only affects
the process that opens the handle. And we do not want to
do async stuff.
2016-04-27 11:37:21 +02:00
Olivier Goffart d0af3ede05 AccountSettings: context menu: don't rely on the alias
Don't rely on the alias to know weather we shuld show a context menu or not.
Use the classify function to know if it's a root folder instead
2016-04-27 11:21:58 +02:00
Olivier Goffart 0da2adcbe0 Workaround ubuntu 16.04 systemtray bug (#4693) (#4747) 2016-04-27 11:21:13 +02:00
Klaas Freitag 07bdd519e9 vio for windows: Use more graceful create file params. 2016-04-27 11:17:42 +02:00
Christian Kamm 0829a94c92 Remote folder selection: improve path typing #4745 #4746
* Scroll to the target typed path
* Show non-404 errors that were triggered by typing paths
2016-04-27 10:37:17 +02:00
Daniel Molkentin ce6a365328 Disambiguate socket API pathes on Windows with user name
Addresses #3411
2016-04-26 14:49:45 +02:00
151 arquivos alterados com 20624 adições e 10509 exclusões
+10 -4
Ver Arquivo
@@ -1,15 +1,21 @@
sudo: required
language: cpp
services:
- docker
branches:
only:
- coverity_scan
before_install:
- sudo sh -c "echo 'deb http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/xUbuntu_12.04/ /' >> /etc/apt/sources.list.d/owncloud-client.list"
- sudo sh -c "echo 'deb-src http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/xUbuntu_12.04/ /' >> /etc/apt/sources.list.d/owncloud-client.list"
- wget http://download.opensuse.org/repositories/isv:ownCloud:desktop/xUbuntu_12.04/Release.key
- sudo sh -c "echo 'deb http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/Ubuntu_14.04/ /' >> /etc/apt/sources.list.d/owncloud-client.list"
- sudo sh -c "echo 'deb-src http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/Ubuntu_14.04/ /' >> /etc/apt/sources.list.d/owncloud-client.list"
- wget http://download.opensuse.org/repositories/isv:ownCloud:desktop/Ubuntu_14.04/Release.key
- sudo apt-key add - < Release.key
- sudo apt-get update
- sudo apt-get build-dep owncloud-client
- sudo apt-get -y build-dep owncloud-client
- checkout=$(git show-ref --head --hash head)
- cd ../
- wget https://scan.coverity.com/download/linux-64 --post-data "token=$token&project=owncloud%2Fmirall" -O coverity_tool.tgz
+12
Ver Arquivo
@@ -1,3 +1,4 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(VERSION 2.8.0)
@@ -125,6 +126,17 @@ if(OWNCLOUD_5XX_NO_BLACKLIST)
add_definitions(-DOWNCLOUD_5XX_NO_BLACKLIST=1)
endif()
# When this option is enabled, a rename that is not allowed will be renamed back
# do the original as a restoration step. Withut this option, the restoration will
# re-download the file instead.
# The default is off because we don't want to rename the files back behind the user's back
# Added for IL issue #550
option(OWNCLOUD_RESTORE_RENAME "OWNCLOUD_RESTORE_RENAME" OFF)
if(OWNCLOUD_RESTORE_RENAME)
add_definitions(-DOWNCLOUD_RESTORE_RENAME=1)
endif()
if(APPLE)
set( SOCKETAPI_TEAM_IDENTIFIER_PREFIX "" CACHE STRING "SocketApi prefix (including a following dot) that must match the codesign key's TeamIdentifier/Organizational Unit" )
endif()
+33
Ver Arquivo
@@ -1,5 +1,38 @@
ChangeLog
=========
version 2.2.1 (release 2016-05-xx)
* Fix out of memory error when too many uploads happen (#4611)
* Fix display errors in progress display (#4803 #4856)
* LockWatcher: Remember to upload files after they become unlocked (#4865)
* Fix overlay icons for files with umlauts (#4884)
* Certs: Re-ask for different cert after rejection (#4898, #4911)
* Progress: Don't count items without propagation jobs (#4856, #4910)
* Utility: Fix for the translation of minutes, second (#4855)
* SyncEngine: invalid the blacklist entry when the rename destination change
version 2.2.0 (release 2016-05-12)
* Overlay icons: Refactoring - mainly for performance improvements
* Improved error handling with Sync Journal on USB storages (#4632)
* Sharing Completion: Improved UI of completion in sharing from desktop. (#3737)
* Show server notifications on the client (#3733)
* Improved Speed with small files by dynamic parallel request count (#4529)
* LockWatcher: Make sure to sync files after apps released exclusive locks on Windows.
* Improved handling of Win32 file locks and network files
* Workaround Ubuntu 16.04 tray icon bug (#4693)
* Removed the Alias field from the folder definition (#4695)
* Improved netrc parser (#4691)
* Improved user notifications about ignored files and conflicts (#4761, #3222)
* Add warnings for old server versions (#4523)
* Enable tranportation checksums if the server supports based on server capabilities (#3735)
* Default Chunk-size changed to 10MB (#4354)
* Documentation Improvements, ie. about overlay icons
* Translation fixes
* Countless other bugfixes
* Sqlite Update to recent version
* Update of QtKeyChain to support Windows credential store
* Packaging of dolphin overlay icon module for bleeding edge distros
version 2.1.1 (release 2016-02-10)
* UI improvements for HiDPI screens, error messages, RTL languages
* Fix occurences of "Connection Closed" when a new unauthenticated TCP socket is used
+1 -1
Ver Arquivo
@@ -15,7 +15,7 @@ with your computer.
### Binary packages
* Refer to the download page http://owncloud.org/sync-clients/
* Refer to the download page https://owncloud.org/install/#install-clients
### Source code
+1 -1
Ver Arquivo
@@ -1,6 +1,6 @@
set( MIRALL_VERSION_MAJOR 2 )
set( MIRALL_VERSION_MINOR 2 )
set( MIRALL_VERSION_PATCH 0 )
set( MIRALL_VERSION_PATCH 3 )
set( MIRALL_VERSION_YEAR 2016 )
set( MIRALL_SOVERSION 0 )
+13 -5
Ver Arquivo
@@ -1,7 +1,7 @@
## Patches used
There are our patches on top of Qt 5.4.0, which we are currently
using for our binary packages on Windows and Mac OS. Most of them
using for our binary packages on Windows and Mac OS X. Most of them
have been sent upstream and are part of newer Qt releases.
All changes are designed to up upstream, and all those that are
@@ -28,18 +28,26 @@ purpose is outlined in each patches' front matter.
* 0007-X-Network-Fix-up-previous-corruption-patch.patch
* 0008-QNAM-Fix-reply-deadlocks-on-server-closing-connectio.patch
* 0014-Fix-SNI-for-TlsV1_0OrLater-TlsV1_1OrLater-and-TlsV1_.patch
* 0016-Fix-possible-crash-when-passing-an-invalid-PAC-URL.patch
* 0011-Make-sure-to-report-correct-NetworkAccessibility.patch
### Upstreamed but not in any release yet (as of 2015-11-16)
### Part of Qt v5.5.2 (UNRELEASED!)
* 0009-QNAM-Assign-proper-channel-before-sslErrors-emission.patch
* 0010-Don-t-let-closed-http-sockets-pass-as-valid-connecti.patch
* 0012-Make-sure-networkAccessibilityChanged-is-emitted.patch
### Part of Qt v5.6 and later
* 0009-QNAM-Assign-proper-channel-before-sslErrors-emission.patch
* 0010-Don-t-let-closed-http-sockets-pass-as-valid-connecti.patch
* 0011-Make-sure-to-report-correct-NetworkAccessibility.patch
* 0012-Make-sure-networkAccessibilityChanged-is-emitted.patch
* 0013-Make-UnknownAccessibility-not-block-requests.patch
* 0015-Remove-legacy-platform-code-in-QSslSocket-for-OS-X-1.patch
* 0016-Fix-possible-crash-when-passing-an-invalid-PAC-URL.patch
* 0019-Ensure-system-tray-icon-is-prepared-even-when-menu-bar.patch
### Not submitted to be part of any release:
### Part of Qt 5.7 and later
* 0015-Remove-legacy-platform-code-in-QSslSocket-for-OS-X-1.patch
### Not submitted upstream to be part of any release:
* 0006-Fix-force-debug-info-with-macx-clang_NOUPSTREAM.patch
This is only needed if you intent to harvest debugging symbols
for breakpad.
+1 -1
Submodule binary updated: ac42257499...d27d472817
-5
Ver Arquivo
@@ -1,5 +0,0 @@
--- binary
+++ binary
@@ -1 +1 @@
-Subproject commit 1fb9ddfa9a9a1b4dbc447eee10dbed89172d968a
+Subproject commit 01d73965dc8b862d1b2310d3ef801c297b697ec7
-1
Ver Arquivo
@@ -620,7 +620,6 @@ Section Uninstall
!insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\shellext\OCOverlays_x64.dll"
!insertmacro UnInstallLib DLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\shellext\OCUtil_x64.dll"
!undef LIBRARY_X64
${Else}
DetailPrint "Uninstalling x86 overlay DLLs"
!insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\shellext\OCContextMenu_x86.dll"
!insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\shellext\OCOverlays_x86.dll"
+1
Ver Arquivo
@@ -39,6 +39,7 @@
#include <unistd.h>
#include <sys/types.h>
#include <config_csync.h>
#include "csync_exclude.h"
#ifdef __cplusplus
extern "C" {
+30 -5
Ver Arquivo
@@ -44,6 +44,18 @@
static
#endif
int _csync_exclude_add(c_strlist_t **inList, const char *string) {
size_t i = 0;
// We never want duplicates, so check whether the string is already
// in the list first.
if (*inList) {
for (i = 0; i < (*inList)->count; ++i) {
char *pattern = (*inList)->vector[i];
if (c_streq(pattern, string)) {
return 1;
}
}
}
return c_strlist_add_grow(inList, string);
}
@@ -139,8 +151,10 @@ int csync_exclude_load(const char *fname, c_strlist_t **list) {
buf[i] = '\0';
if (*entry != '#') {
const char *unescaped = csync_exclude_expand_escapes(entry);
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Adding entry: %s", unescaped);
rc = _csync_exclude_add(list, unescaped);
if( rc == 0 ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Adding entry: %s", unescaped);
}
SAFE_FREE(unescaped);
if (rc < 0) {
goto out;
@@ -158,6 +172,7 @@ out:
return rc;
}
// See http://support.microsoft.com/kb/74496 and
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
// Additionally, we ignore '$Recycle.Bin', see https://github.com/owncloud/client/issues/2955
@@ -193,7 +208,7 @@ bool csync_is_windows_reserved_word(const char* filename) {
return false;
}
static CSYNC_EXCLUDE_TYPE _csync_excluded_common(c_strlist_t *excludes, const char *path, int filetype, bool check_leading_dirs) {
static CSYNC_EXCLUDE_TYPE _csync_excluded_common(c_strlist_t *excludes, const char *path, int filetype, bool check_leading_dirs, csync_exclude_traversal_hook hook, void *hookUserData) {
size_t i = 0;
const char *bname = NULL;
size_t blen = 0;
@@ -286,6 +301,13 @@ static CSYNC_EXCLUDE_TYPE _csync_excluded_common(c_strlist_t *excludes, const ch
SAFE_FREE(conflict);
}
if (!check_leading_dirs && hook) {
//
match = hook(bname, filetype, hookUserData);
goto out;
}
if( ! excludes ) {
goto out;
}
@@ -318,6 +340,8 @@ static CSYNC_EXCLUDE_TYPE _csync_excluded_common(c_strlist_t *excludes, const ch
SAFE_FREE(path_split);
}
/* Loop over all exclude patterns and evaluate the given path */
for (i = 0; match == CSYNC_NOT_EXCLUDED && i < excludes->count; i++) {
bool match_dirs_only = false;
@@ -386,11 +410,12 @@ static CSYNC_EXCLUDE_TYPE _csync_excluded_common(c_strlist_t *excludes, const ch
return match;
}
CSYNC_EXCLUDE_TYPE csync_excluded_traversal(c_strlist_t *excludes, const char *path, int filetype) {
return _csync_excluded_common(excludes, path, filetype, false);
CSYNC_EXCLUDE_TYPE csync_excluded_traversal(c_strlist_t *excludes, const char *path, int filetype, csync_exclude_traversal_hook hook, void *hookUserData) {
// return ctx->callbacks.excluded_traversal_hook(path, filetype);
return _csync_excluded_common(excludes, path, filetype, false, hook, hookUserData);
}
CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype) {
return _csync_excluded_common(excludes, path, filetype, true);
return _csync_excluded_common(excludes, path, filetype, true, 0, 0);
}
+8 -3
Ver Arquivo
@@ -21,6 +21,8 @@
#ifndef _CSYNC_EXCLUDE_H
#define _CSYNC_EXCLUDE_H
#include "std/c_string.h"
enum csync_exclude_type_e {
CSYNC_NOT_EXCLUDED = 0,
CSYNC_FILE_SILENTLY_EXCLUDED,
@@ -37,6 +39,10 @@ typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE;
int _csync_exclude_add(c_strlist_t **inList, const char *string);
#endif
// Hook from mirall
typedef CSYNC_EXCLUDE_TYPE (*csync_exclude_traversal_hook) (
const char *path, int filetype, void *userData);
/**
* @brief Load exclude list
*
@@ -62,7 +68,7 @@ int csync_exclude_load(const char *fname, c_strlist_t **list);
*
* @return 2 if excluded and needs cleanup, 1 if excluded, 0 if not.
*/
CSYNC_EXCLUDE_TYPE csync_excluded_traversal(c_strlist_t *excludes, const char *path, int filetype);
CSYNC_EXCLUDE_TYPE csync_excluded_traversal(c_strlist_t *excludes, const char *path, int filetype, csync_exclude_traversal_hook hook, void *hookUserData);
/**
* @brief csync_excluded_no_ctx
@@ -72,7 +78,6 @@ CSYNC_EXCLUDE_TYPE csync_excluded_traversal(c_strlist_t *excludes, const char *p
* @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
@@ -81,5 +86,5 @@ CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path
*/
bool csync_is_windows_reserved_word(const char *file_name);
#endif /* _CSYNC_EXCLUDE_H */
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */
+1 -5
Ver Arquivo
@@ -59,14 +59,10 @@ int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags) {
#include <shlwapi.h>
int csync_fnmatch(const char *pattern, const char *name, int flags) {
BOOL match;
mbchar_t *mbname = c_utf8_path_to_locale(name);
mbchar_t *mbpatt = c_utf8_path_to_locale(pattern);
(void) flags;
match = PathMatchSpecW(mbname, mbpatt);
c_free_locale_string(mbname);
c_free_locale_string(mbpatt);
match = PathMatchSpecA(name, pattern);
if(match)
return 0;
+1
Ver Arquivo
@@ -33,6 +33,7 @@
* than fmmatch anyway, which does not care for flags.
**/
#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
#endif
int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags);
+4
Ver Arquivo
@@ -101,6 +101,10 @@ struct csync_s {
csync_checksum_hook checksum_hook;
void *checksum_userdata;
/* Hook for the QRegExp based exclude checker */
csync_exclude_traversal_hook excluded_traversal_hook;
void *excluded_traversal_userdata;
} callbacks;
c_strlist_t *excludes;
+3 -3
Ver Arquivo
@@ -466,13 +466,13 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
/* Check for exclusion from the tree.
* Note that this is only a safety net in case the ignore list changes
* without a full remote discovery being triggered. */
CSYNC_EXCLUDE_TYPE excluded = csync_excluded_traversal(ctx->excludes, st->path, st->type);
CSYNC_EXCLUDE_TYPE excluded = csync_excluded_traversal(ctx->excludes, st->path, st->type, ctx->callbacks.excluded_traversal_hook, ctx->callbacks.excluded_traversal_userdata);
if (excluded != CSYNC_NOT_EXCLUDED) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "%s excluded (%d)", st->path, excluded);
if (excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE
|| excluded == CSYNC_FILE_SILENTLY_EXCLUDED) {
SAFE_FREE(st);
csync_file_stat_free(st);
continue;
}
@@ -481,7 +481,7 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
/* store into result list. */
if (c_rbtree_insert(ctx->remote.tree, (void *) st) < 0) {
SAFE_FREE(st);
csync_file_stat_free(st);
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
break;
}
+14 -10
Ver Arquivo
@@ -203,7 +203,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
excluded =CSYNC_FILE_EXCLUDE_STAT_FAILED;
} else {
/* Check if file is excluded */
excluded = csync_excluded_traversal(ctx->excludes, path, type);
excluded = csync_excluded_traversal(ctx->excludes, path, type, ctx->callbacks.excluded_traversal_hook, ctx->callbacks.excluded_traversal_userdata);
}
if( excluded == CSYNC_NOT_EXCLUDED ) {
@@ -269,7 +269,8 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
tmp = csync_statedb_get_stat_by_hash(ctx, h);
if(_last_db_return_error(ctx)) {
SAFE_FREE(st);
csync_file_stat_free(st);
csync_file_stat_free(tmp);
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
return -1;
}
@@ -297,7 +298,10 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
// zero size in statedb can happen during migration
|| (tmp->size != 0 && fs->size != tmp->size))) {
if (fs->size == tmp->size && tmp->checksumTypeId) {
// Checksum comparison at this stage is only enabled for .eml files,
// check #4754 #4755
bool isEmlFile = csync_fnmatch("*.eml", file, FNM_CASEFOLD) == 0;
if (isEmlFile && fs->size == tmp->size && tmp->checksumTypeId) {
if (ctx->callbacks.checksum_hook) {
st->checksum = ctx->callbacks.checksum_hook(
file, tmp->checksumTypeId,
@@ -353,7 +357,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
enum csync_vio_file_type_e tmp_vio_type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
/* tmp might point to malloc mem, so free it here before reusing tmp */
SAFE_FREE(tmp);
csync_file_stat_free(tmp);
/* check if it's a file and has been renamed */
if (ctx->current == LOCAL_REPLICA) {
@@ -362,7 +366,7 @@ 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);
csync_file_stat_free(st);
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
return -1;
}
@@ -418,7 +422,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
tmp = csync_statedb_get_stat_by_file_id(ctx, fs->file_id);
if(_last_db_return_error(ctx)) {
SAFE_FREE(st);
csync_file_stat_free(st);
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
return -1;
}
@@ -447,7 +451,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
if (fs->type == CSYNC_VIO_FILE_TYPE_DIRECTORY && ctx->current == REMOTE_REPLICA && ctx->callbacks.checkSelectiveSyncNewFolderHook) {
if (ctx->callbacks.checkSelectiveSyncNewFolderHook(ctx->callbacks.update_callback_userdata, path)) {
SAFE_FREE(st);
csync_file_stat_free(st);
return 1;
}
}
@@ -457,7 +461,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
}
} else {
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Unable to open statedb" );
SAFE_FREE(st);
csync_file_stat_free(st);
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
return -1;
}
@@ -519,14 +523,14 @@ out:
switch (ctx->current) {
case LOCAL_REPLICA:
if (c_rbtree_insert(ctx->local.tree, (void *) st) < 0) {
SAFE_FREE(st);
csync_file_stat_free(st);
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
return -1;
}
break;
case REMOTE_REPLICA:
if (c_rbtree_insert(ctx->remote.tree, (void *) st) < 0) {
SAFE_FREE(st);
csync_file_stat_free(st);
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
return -1;
}
+1
Ver Arquivo
@@ -56,6 +56,7 @@ void csync_vio_file_stat_destroy(csync_vio_file_stat_t *file_stat) {
SAFE_FREE(file_stat->directDownloadUrl);
SAFE_FREE(file_stat->directDownloadCookies);
SAFE_FREE(file_stat->name);
SAFE_FREE(file_stat->original_name);
SAFE_FREE(file_stat);
}
+1 -1
Ver Arquivo
@@ -141,7 +141,7 @@ csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_handle_t *dhandle) {
return file_stat;
err:
SAFE_FREE(file_stat);
csync_vio_file_stat_destroy(file_stat);
return NULL;
}
+4 -2
Ver Arquivo
@@ -230,8 +230,10 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
ULARGE_INTEGER FileIndex;
mbchar_t *wuri = c_utf8_path_to_locale( uri );
h = CreateFileW( wuri, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL+FILE_FLAG_BACKUP_SEMANTICS+FILE_FLAG_OPEN_REPARSE_POINT, NULL );
h = CreateFileW( wuri, 0, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
NULL );
if( h == INVALID_HANDLE_VALUE ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_CRIT, "CreateFileW failed on %s", uri );
errno = GetLastError();
+18 -24
Ver Arquivo
@@ -85,6 +85,16 @@ sub fromFileName($)
}
}
sub setCredentials
{
my ($dav, $user, $passwd) = @_;
$dav->credentials(-url=> $owncloud, -realm=>"sabre/dav",
-user=> $user, -pass=> $passwd);
$dav->credentials(-url=> $owncloud, -realm=>"ownCloud",
-user=> $user, -pass=> $passwd);
}
sub initTesting(;$)
{
@@ -127,9 +137,7 @@ sub initTesting(;$)
my $ua = HTTP::DAV::UserAgent->new(keep_alive => 1 );
$d = HTTP::DAV->new(-useragent => $ua);
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
-user=> $user,
-pass=> $passwd );
setCredentials($d, $user, $passwd);
# $d->DebugLevel(3);
$prefix = "t1" unless( defined $prefix );
@@ -193,9 +201,7 @@ sub removeRemoteDir($;$)
my $url = testDirUrl() . $dir;
if( $optionsRef && $optionsRef->{user} && $optionsRef->{passwd} ) {
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
-user=> $optionsRef->{user},
-pass=> $optionsRef->{passwd} );
setCredentials($d, $optionsRef->{user}, $optionsRef->{passwd});
if( $optionsRef->{url} ) {
$url = $optionsRef->{url} . $dir;
}
@@ -219,9 +225,7 @@ sub createRemoteDir(;$$)
my $url = testDirUrl() . $dir;
if( $optionsRef && $optionsRef->{user} && $optionsRef->{passwd} ) {
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
-user=> $optionsRef->{user},
-pass=> $optionsRef->{passwd} );
setCredentials($d, $optionsRef->{user}, $optionsRef->{passwd});
if( $optionsRef->{url} ) {
$url = $optionsRef->{url} . $dir;
}
@@ -396,9 +400,7 @@ sub traverse( $$;$ )
my %seen;
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
-user=> $user,
-pass=> $passwd );
setCredentials($d, $user, $passwd);
$d->open( $owncloud );
if( my $r = $d->propfind( -url => $url, -depth => 1 ) ) {
@@ -513,9 +515,7 @@ sub put_to_dir( $$;$ )
my $targetUrl = testDirUrl();
if( $optionsRef && $optionsRef->{user} && $optionsRef->{passwd} ) {
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
-user=> $optionsRef->{user},
-pass=> $optionsRef->{passwd} );
setCredentials($d, $optionsRef->{user}, $optionsRef->{passwd});
if( $optionsRef->{url} ) {
$targetUrl = $optionsRef->{url};
}
@@ -649,9 +649,7 @@ sub moveRemoteFile($$;$)
{
my ($from, $to, $no_testdir) = @_;
$d->credentials( -url=> $owncloud, -realm=>"ownCloud",
-user=> $user,
-pass=> $passwd );
setCredentials($d, $user, $passwd);
my $fromUrl = testDirUrl(). $from;
my $toUrl = testDirUrl() . $to;
@@ -725,9 +723,7 @@ sub createShare($$)
my $dd = HTTP::DAV->new();
$dd->credentials( -url=> $owncloud, -realm=>"ownCloud",
-user=> $share_user,
-pass=> $share_passwd );
setCredentials($dd, $share_user, $share_passwd);
$dd->open( $owncloud);
# create a remote dir
@@ -769,9 +765,7 @@ sub removeShare($$)
my $dd = HTTP::DAV->new();
$dd->credentials( -url => $owncloud, -realm=>"ownCloud",
-user => $share_user,
-pass => $share_passwd );
setCredentials($dd, $share_user, $share_passwd);
$dd->open( $owncloud);
my $ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 0 });
+2 -2
Ver Arquivo
@@ -146,9 +146,9 @@ assertLocalAndRemoteDir( '', 0);
# create a true conflict.
printInfo( "Create a conflict." );
system( "echo \"This is more stuff\" >> /tmp/kernelcrash.txt" );
system( "echo \"This is more server stuff\" >> /tmp/kernelcrash.txt" );
put_to_dir( '/tmp/kernelcrash.txt', 'remoteToLocal1' );
system( "sleep 2 && touch " . localDir() . "remoteToLocal1/kernelcrash.txt" );
system( "sleep 2 && echo \"This is more client stuff\" >> " . localDir() . "remoteToLocal1/kernelcrash.txt" );
csync();
assertLocalAndRemoteDir( '', 1);
+1 -1
Ver Arquivo
@@ -71,7 +71,7 @@ assert($emlpropafter->get_property( "getlastmodified" ) eq
$emlpropbefore->get_property( "getlastmodified" ));
printInfo( "Change content of eml file (but not size)");
system( "sed -i -e 's/in/IN/' $locDir/test.eml" );
system( "sleep 1 && sed -i -e 's/in/IN/' $locDir/test.eml" );
csync( );
+4 -4
Ver Arquivo
@@ -159,8 +159,8 @@ In order to make setup simple, you can use the provided Dockerfile to build your
1. Assuming you are in the root of the ownCloud Client's source tree, you can
build an image from this Dockerfile like this::
cd admin/win32/docker
docker build . -t ownCloud-client-win32:<version>
cd admin/win/docker
docker build . -t owncloud-client-win32:<version>
Replace ``<version>`` by the version of the client you are building, e.g.
|version| for the release of the client that this document describes.
@@ -174,8 +174,8 @@ In order to make setup simple, you can use the provided Dockerfile to build your
2. From within the source tree Run the docker instance::
docker run ownCloud-client-win32:<version> -v "$PWD:/home/jenkins/client" \
admin/win32/docker/build.sh $(id -u)
docker run -v "$PWD:/home/user/client" owncloud-client-win32:<version> \
/home/user/client/admin/win/docker/build.sh client/ $(id -u)
It will run the build, create an NSIS based installer, as well as run tests.
You will find the resulting binary in an newly created ``build-win32`` subfolder.
+2 -2
Ver Arquivo
@@ -41,7 +41,7 @@ master_doc = 'index'
# General information about the project.
project = u'ownCloud Client Manual'
copyright = u'2013, The ownCloud developers'
copyright = u'2013-2016, The ownCloud developers'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -250,7 +250,7 @@ texinfo_documents = [
epub_title = u'ownCloud Client Manual'
epub_author = u'The ownCloud developers'
epub_publisher = u'The ownCloud developers'
epub_copyright = u'2013, The ownCloud developers'
epub_copyright = u'2013-2016, The ownCloud developers'
# The language of the text. It defaults to the language option
# or en if the language is not set.
Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 86 KiB

Depois

Largura:  |  Altura:  |  Tamanho: 52 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 82 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 49 KiB

Depois

Largura:  |  Altura:  |  Tamanho: 58 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 58 KiB

Depois

Largura:  |  Altura:  |  Tamanho: 224 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 23 KiB

Depois

Largura:  |  Altura:  |  Tamanho: 20 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 24 KiB

Depois

Largura:  |  Altura:  |  Tamanho: 34 KiB

+3 -3
Ver Arquivo
@@ -4,16 +4,16 @@ ownCloud Desktop Client Manual
==============================
.. toctree::
:maxdepth: 3
:maxdepth: 2
introduction
installing
navigating
advancedusage
autoupdate
building
architecture
troubleshooting
faq
glossary
glossary
+12 -16
Ver Arquivo
@@ -12,26 +12,22 @@ Desktop Sync client enables you to:
Your files are always automatically synchronized between your ownCloud server
and local PC.
.. note:: Because of various technical issues, desktop sync clients older than
1.7 will not allowed to connect and sync with the ownCloud 8.1+ server. It
is highly recommended to keep your client updated.
Because of various technical issues, desktop sync clients older than 1.7 will
not allowed to connect and sync with the ownCloud 8.1+ server. It is highly
recommended to keep your client updated.
Improvements and New Features
-----------------------------
The 2.1 release of the ownCloud desktop sync client has many new features and
The 2.2 release of the ownCloud desktop sync client has many new features and
improvements. (See the `complete changelog
<https://owncloud.org/changelog/desktop/>`_.)
* Improved appearance on HiDPI screens
* Improved error messages
* Several fixes/improvements to the sharing dialog
* Several fixes/improvements to the server activity tab
* Allow changeable upload chunk size in owncloud.cfg
* Forget password on explicit sign-out
* Windows: Fix deleting and replacing of read-only files
* Share with internal ownCloud users from your desktop
* Separate views for server activity, sync activity, and errors
* Don't re-upload *eml-files if size and checksum are unchanged
* Improved upload/download progress indicator
* Show server notifications on the client
* Improved sync speed
* Improved handling of Win32 file locks and network files
* Improved user notifications about ignored files and conflicts
* Add warnings for old server versions
* Update of QtKeyChain to support Windows credential store
* Packaging of dolphin overlay icon module for bleeding edge distros
+29 -22
Ver Arquivo
@@ -62,6 +62,7 @@ This menu provides the following options:
* Recent Changes, showing latest activities
* Settings
* Help menu
* Pause synchronizations
* An option to log in or log out of all of your accounts at once
* Quit ownCloud, logging out and closing the client
@@ -83,7 +84,7 @@ have the following features:
* Connection status, showing which ownCloud server you are connected to, and
your ownCloud username.
* An **Account** button, which contains a dropdown menu with **Add New**,
**Log In/Log Out**, and **Remove**.
**Log Out**, and **Remove**.
* Used and available space on the server.
* Current synchronization status.
* **Add Folder Sync Connection** button, which is active only when you have
@@ -93,26 +94,17 @@ The little button with three dots (the overflow menu) that sits to the right of
the sync status bar offers four additional options:
* Open Folder
* Choose What to Sync
* Choose What to Sync (This appears only when your file tree is collapsed, and
expands the file tree)
* Pause Sync / Resume Sync
* Remove folder sync connection
**Open Folder** opens a file explorer window displaying the client-side folder
that is being synced.
**Choose What to Sync** opens the folder sync tree view. Use this to sync all
or only some of the folders in the folder tree.
**Open Folder** opens your local ownCloud sync folder.
**Pause Sync** pauses sync operations without making any changes to your
account. It will continue to update file and folder lists, without
downloading or updating files. To stop all sync activity use **Remove Sync**.
**Resume Sync** resumes sync operations.
**Remove Sync** removes the sync connection without removing the account. This
stops all sync activity, including file and folder list updates. If you want to
synchronize the folder tree again then click the **Add Folder Sync Connection**
button, and re-select the folder tree that you want to sync.
downloading or updating files. To stop all sync activity use **Remove
Folder Sync Connection**.
.. figure:: images/client-7.png
:alt: Extra options for sync operations
@@ -125,12 +117,10 @@ button, and re-select the folder tree that you want to sync.
Adding New Accounts
^^^^^^^^^^^^^^^^^^^
You may configure multiple ownCloud accounts in your desktop sync client.
Simply
You may configure multiple ownCloud accounts in your desktop sync client. Simply
click the **Account** > **Add New** button on any account tab to add a new
account, and then follow the account creation wizard. The new account will
appear as a new tab in the settings dialog, where you can adjust its settings
at
appear as a new tab in the settings dialog, where you can adjust its settings at
any time. Use **Account** > **Remove** to delete accounts.
File Manager Overlay Icons
@@ -175,9 +165,7 @@ the ``owncloud-client-nautilus`` plugin.) You can create share links, and share
with internal ownCloud users the same way as in your ownCloud Web interface.
.. figure:: images/mac-share.png
:alt: Sync client integration in Finder on Mac OS X.
*Shared ownCloud files in Finder on Mac OS X*
:alt: Sync client integration in Windows Explorer.
Right-click your systray icon, hover over the account you want to use, and
left-click "Open folder [folder name] to quickly enter your local ownCloud
@@ -206,6 +194,25 @@ such as files not synced.
.. figure:: images/client-8.png
:alt: Activity windows logs all server and client activities.
Server Notifications
--------------------
Starting with version 2.2.0, the client will display notifications from your
ownCloud server that require manual interaction by you. For example, when a
user on a remote ownCloud creates a new Federated share for you, you can accept
it from your desktop client.
The desktop client automatically checks for available notifications
automatically on a regular basis. Notifications are displayed in the Server
Activity tab, and if you have **Show Desktop Notifications** enabled (General
tab) you'll also see a systray notification.
.. figure:: images/client12.png
:alt: Activity window with notification.
This also displays notifications sent to users by the ownCloud admin via the
Announcements app.
General Window
--------------
+208 -4
Ver Arquivo
@@ -11,11 +11,215 @@ X-GNOME-Autostart-Delay=3
# Translations
Comment[sq]=Klient njëkohësimesh @APPLICATION_NAME@ për desktop
GenericName[sq]=Njëkohësim Dosjesh
Name[sq]=Klient njëkohësimesh @APPLICATION_NAME@ për desktop
Icon[sq]=@APPLICATION_EXECUTABLE@
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
Icon[oc]=@APPLICATION_EXECUTABLE@
Comment[ar]=@APPLICATION_NAME@ زبون مزامنة مكتبي
GenericName[ar]=مزامنة المجلد
Name[ar]=@APPLICATION_NAME@ زبون مزامنة مكتبي
Icon[ar]=@APPLICATION_EXECUTABLE@
Comment[ca]=Client de sincronització d'escriptori @APPLICATION_NAME@
GenericName[ca]=Sincronització de carpetes
Name[ca]=Client de sincronització d'escriptori @APPLICATION_NAME@
Icon[ca]=@APPLICATION_EXECUTABLE@
Comment[da]=@APPLICATION_NAME@ skrivebordsklient til synkronisering
GenericName[da]=Mappesynkronisering
Name[da]=@APPLICATION_NAME@ skrivebordsklient til synk
Icon[da]=@APPLICATION_EXECUTABLE@
Comment[de]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
GenericName[de]=Ordner-Synchronisation
Name[de]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
Icon[de]=@APPLICATION_EXECUTABLE@
Comment[ja_JP]=@APPLICATION_NAME@ デスクトップ同期クライアント
GenericName[ja_JP]=フォルダ同期
Name[ja_JP]=@APPLICATION_NAME@ デスクトップ同期クライアント
Icon[ja_JP]=@APPLICATION_EXECUTABLE@
Comment[en_GB]=@APPLICATION_NAME@ desktop synchronisation client
GenericName[en_GB]=Folder Sync
Name[en_GB]=@APPLICATION_NAME@ desktop sync client
Icon[en_GB]=@APPLICATION_EXECUTABLE@
Comment[es]=@APPLICATION_NAME@ cliente de sincronización de escritorio
GenericName[es]=Sincronización de carpeta
Name[es]=@APPLICATION_NAME@ cliente de sincronización de escritorio
Icon[es]=@APPLICATION_EXECUTABLE@
Comment[de_DE]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
GenericName[de_DE]=Ordner-Synchronisation
Name[de_DE]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
Icon[de_DE]=@APPLICATION_EXECUTABLE@
Comment[bg_BG]=@APPLICATION_NAME@ клиент за десктоп синхронизация
GenericName[bg_BG]=Синхронизиране на папката
Name[bg_BG]=@APPLICATION_NAME@ клиент десктоп синхронизация
Icon[bg_BG]=@APPLICATION_EXECUTABLE@
Comment[fr]=@APPLICATION_NAME@ synchronisation du client
GenericName[fr]=Dossier de Synchronisation
Name[fr]=@APPLICATION_NAME@ synchronisation du client
Icon[fr]=@APPLICATION_EXECUTABLE@
Comment[he]=@APPLICATION_NAME@ לקוח סנכון שולחן עבודה
GenericName[he]=סנכון תיקייה
Name[he]=@APPLICATION_NAME@ לקוח סנכרון שולחן עבודה
Icon[he]=@APPLICATION_EXECUTABLE@
Comment[id]=Klien sinkronisasi desktop @APPLICATION_NAME@
GenericName[id]=Folder Sync
Name[id]=Klien sync desktop @APPLICATION_NAME@
Icon[id]=@APPLICATION_EXECUTABLE@
Comment[is]=@APPLICATION_NAME@ skjáborðsforrit samstillingar
GenericName[is]=Samstilling möppu
Name[is]=@APPLICATION_NAME@ skjáborðsforrit samstillingar
Icon[is]=@APPLICATION_EXECUTABLE@
Comment[it]=Client di sincronizzazione del desktop di @APPLICATION_NAME@
GenericName[it]=Sincronizzazione cartella
Name[it]=Client di sincronizzazione del desktop di @APPLICATION_NAME@
Icon[it]=@APPLICATION_EXECUTABLE@
Comment[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
GenericName[ko]=폴더 동기화
Name[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
Comment[hu_HU]=@APPLICATION_NAME@ asztali szinkronizációs kliens
GenericName[hu_HU]=Könyvtár szinkronizálás
Name[hu_HU]=@APPLICATION_NAME@ asztali szinkr. kliens
Icon[hu_HU]=@APPLICATION_EXECUTABLE@
Comment[nl]=@APPLICATION_NAME@ desktop synchronisatie client
GenericName[nl]=Mappen sync
Name[nl]=@APPLICATION_NAME@ desktop sync client
Icon[nl]=@APPLICATION_EXECUTABLE@
Icon[pl]=@APPLICATION_EXECUTABLE@
Comment[pt_BR]=@APPLICATION_NAME@ cliente de sincronização do computador
GenericName[pt_BR]=Sincronização de Pasta
Name[pt_BR]=@APPLICATION_NAME@ cliente de sincronização de desktop
Icon[pt_BR]=@APPLICATION_EXECUTABLE@
Comment[cs_CZ]=@APPLICATION_NAME@ počítačový synchronizační klient
GenericName[cs_CZ]=Synchronizace adresáře
Name[cs_CZ]=@APPLICATION_NAME@ počítačový synchronizační klient
Icon[cs_CZ]=@APPLICATION_EXECUTABLE@
Comment[ru]=Настольный клиент синхронизации @НАЗВАНИЕ_ПРИЛОЖЕНИЯ@
GenericName[ru]=Синхронизация папки
Name[ru]=Настольный клиент синхронизации @НАЗВАНИЕ_ПРИЛОЖЕНИЯ@
Icon[ru]=@ВЫПОЛНЯЕМОЕ_ПРИЛОЖЕНИЕ@
Comment[sl]=@APPLICATION_NAME@ Program za usklajevanje datotek z namizjem
GenericName[sl]=Usklajevanje map
Name[sl]=@APPLICATION_NAME@ Program za usklajevanje datotek z namizjem
Icon[sl]=@APPLICATION_EXECUTABLE@
Comment[sq]=Klient njëkohësimesh @APPLICATION_NAME@ për desktop
GenericName[sq]=Njëkohësim Dosjesh
Name[sq]=Klient njëkohësimesh @APPLICATION_NAME@ për desktop
Icon[sq]=@APPLICATION_EXECUTABLE@
Comment[sv]=@APPLICATION_NAME@ desktop synkroniseringsklient
GenericName[sv]=Mappsynk
Name[sv]=@APPLICATION_NAME@ desktop synk-klient
Icon[sv]=@APPLICATION_EXECUTABLE@
Comment[tr]=@APPLICATION_NAME@ masaüstü senkronizasyon istemcisi
GenericName[tr]=Dosya Senkronizasyonu
Name[tr]=@APPLICATION_NAME@ masaüstü senkronizasyon istemcisi
Icon[tr]=@APPLICATION_EXECUTABLE@
Comment[uk]=Настільний клієнт синхронізації @APPLICATION_NAME@
GenericName[uk]=Синхронізація теки
Name[uk]=Настільний клієнт синхронізації @APPLICATION_NAME@
Icon[uk]=@APPLICATION_EXECUTABLE@
Comment[ro]=@APPLICATION_NAME@ client de sincronizare pe desktop
GenericName[ro]=Sincronizare director
Name[ro]=@APPLICATION_NAME@ client de sincronizare pe desktop
Icon[ro]=@APPLICATION_EXECUTABLE@
Comment[zh_CN]=@APPLICATION_NAME@ 桌面同步客户端
GenericName[zh_CN]=文件夹同步
Name[zh_CN]=@APPLICATION_NAME@ 桌面同步客户端
Icon[zh_CN]=@APPLICATION_EXECUTABLE@
GenericName[zh_TW]=資料夾同步
Comment[pt_PT]=@APPLICATION_NAME@ - Cliente de Sincronização para PC
GenericName[pt_PT]=Sincronizar Pasta
Name[pt_PT]=@APPLICATION_NAME@ - Cliente de Sincronização para PC
Icon[pt_PT]=@APPLICATION_EXECUTABLE@
Comment[lb]=@APPLICATION_NAME@ Desktop Synchronisatioun Client
GenericName[lb]=Dossier Dync
Name[lb]=@APPLICATION_NAME@ Desktop Sync Client
Icon[lb]=@APPLICATION_EXECUTABLE@
Comment[th_TH]=@APPLICATION_NAME@ ไคลเอนต์ประสานข้อมูลเดสก์ท็อป
GenericName[th_TH]=ประสานข้อมูลโฟลเดอร์
Name[th_TH]= @APPLICATION_NAME@ ไคลเอนต์ประสานข้อมูลเดสก์ท็อป
Icon[th_TH]=@APPLICATION_EXECUTABLE@
+1 -1
Ver Arquivo
@@ -36,7 +36,7 @@ endif()
set(OWNCLOUDDOLPHINHELPER ${APPLICATION_EXECUTABLE}dolphinpluginhelper)
add_library(${OWNCLOUDDOLPHINHELPER} SHARED ownclouddolphinpluginhelper.cpp)
target_link_libraries(${OWNCLOUDDOLPHINHELPER} Qt5::Network)
generate_export_header(${OWNCLOUDDOLPHINHELPER})
generate_export_header(${OWNCLOUDDOLPHINHELPER} BASE_NAME ownclouddolphinpluginhelper)
install(TARGETS ${OWNCLOUDDOLPHINHELPER} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
#---OVERLAY PLUGIN---
+9 -5
Ver Arquivo
@@ -21,11 +21,15 @@ import socket
from gi.repository import GObject, Nautilus
print("Initializing owncloud-client-nautilus extension")
# Do not touch the following line.
# Please do not touch the following line.
# The reason is that we use a script to adopt this file for branding
# by replacing this line with the branding app name. If the following
# line is changed, the script can not match the pattern and fails.
appname = 'ownCloud'
print("Initializing "+appname+"-client-nautilus extension")
def get_local_path(url):
if url[0:7] == 'file://':
url = url[7:]
@@ -181,10 +185,10 @@ class MenuExtension(GObject.GObject, Nautilus.MenuProvider):
if not syncedFile:
return items
# Create an menu item
# Create a menu item
labelStr = "Share with " + appname + "..."
item = Nautilus.MenuItem(name='NautilusPython::ShareItem', label=labelStr,
tip='Share file %s through ownCloud' % file.get_name())
tip='Share file {} through {}'.format(file.get_name(), appname) )
item.connect("activate", self.menu_share, file)
items.append(item)
@@ -36,8 +36,7 @@ using namespace std;
OCClientInterface::ContextMenuInfo OCClientInterface::FetchInfo()
{
auto pipename = std::wstring(L"\\\\.\\pipe\\");
pipename += L"ownCloud";
auto pipename = CommunicationSocket::DefaultPipePath();
CommunicationSocket socket;
if (!WaitNamedPipe(pipename.data(), PIPE_TIMEOUT)) {
@@ -72,8 +71,7 @@ OCClientInterface::ContextMenuInfo OCClientInterface::FetchInfo()
void OCClientInterface::ShareObject(const std::wstring &path)
{
auto pipename = std::wstring(L"\\\\.\\pipe\\");
pipename += L"ownCloud";
auto pipename = CommunicationSocket::DefaultPipePath();
CommunicationSocket socket;
if (!WaitNamedPipe(pipename.data(), PIPE_TIMEOUT)) {
@@ -24,11 +24,31 @@
#include <fstream>
#define BUFSIZE 1024
#define DEFAULT_BUFLEN 4096
using namespace std;
#define DEFAULT_BUFLEN 4096
namespace {
std::wstring getUserName() {
DWORD len = DEFAULT_BUFLEN;
TCHAR buf[DEFAULT_BUFLEN];
if (GetUserName(buf, &len)) {
return std::wstring(&buf[0], len);
} else {
return std::wstring();
}
}
}
std::wstring CommunicationSocket::DefaultPipePath()
{
auto pipename = std::wstring(L"\\\\.\\pipe\\");
pipename += L"ownCloud\\";
pipename += getUserName();
return pipename;
}
CommunicationSocket::CommunicationSocket()
: _pipe(INVALID_HANDLE_VALUE)
@@ -26,6 +26,8 @@
class __declspec(dllexport) CommunicationSocket
{
public:
static std::wstring DefaultPipePath();
CommunicationSocket();
~CommunicationSocket();
@@ -43,4 +45,4 @@ private:
bool _connected;
};
#endif
#endif
@@ -31,13 +31,10 @@
using namespace std;
// This code is run in a thread
void RemotePathChecker::workerThreadLoop()
{
auto pipename = std::wstring(L"\\\\.\\pipe\\");
pipename += L"ownCloud";
auto pipename = CommunicationSocket::DefaultPipePath();
bool connected = false;
CommunicationSocket socket;
std::unordered_set<std::wstring> asked;
@@ -241,4 +238,4 @@ RemotePathChecker::FileState RemotePathChecker::_StrToFileState(const std::wstri
}
return StateNone;
}
}
+3 -7
Ver Arquivo
@@ -28,16 +28,12 @@
* \return string PEM
*/
string x509ToString(BIO *o) {
int len = 0;
BUF_MEM *bptr;
void* data;
string ret = "";
BIO_get_mem_ptr(o, &bptr);
len = bptr->length;
data = calloc(len+10, sizeof(char));
int len = bptr->length;
void* data = calloc(len+10, sizeof(char));
BIO_read(o, data, len);
ret = strdup((char*)data);
string ret = std::string(static_cast<char*>(data));
free(data);
return ret;
+9471 -1933
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+1478 -23
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+14 -3
Ver Arquivo
@@ -443,16 +443,27 @@ restart_sync:
QObject::connect(&engine, SIGNAL(finished(bool)), &app, SLOT(quit()));
QObject::connect(&engine, SIGNAL(transmissionProgress(ProgressInfo)), &cmd, SLOT(transmissionProgressSlot()));
// Exclude lists
engine.excludedFiles().addExcludeFilePath(ConfigFile::excludeFileFromSystem());
if( QFile::exists(options.exclude) )
bool hasUserExcludeFile = !options.exclude.isEmpty();
QString systemExcludeFile = ConfigFile::excludeFileFromSystem();
// Always try to load the user-provided exclude list if one is specified
if ( hasUserExcludeFile ) {
engine.excludedFiles().addExcludeFilePath(options.exclude);
}
// Load the system list if available, or if there's no user-provided list
if ( !hasUserExcludeFile || QFile::exists(systemExcludeFile) ) {
engine.excludedFiles().addExcludeFilePath(systemExcludeFile);
}
if (!engine.excludedFiles().reloadExcludes()) {
// Always make sure at least one list has been loaded
qFatal("Cannot load system exclude list or list supplied via --exclude");
return EXIT_FAILURE;
}
// Have to be done async, else, an error before exec() does not terminate the event loop.
QMetaObject::invokeMethod(&engine, "startSync", Qt::QueuedConnection);
+1
Ver Arquivo
@@ -54,6 +54,7 @@ set(client_SRCS
folderwizard.cpp
generalsettings.cpp
ignorelisteditor.cpp
lockwatcher.cpp
logbrowser.cpp
networksettings.cpp
ocsjob.cpp
+8 -3
Ver Arquivo
@@ -159,7 +159,13 @@ void AccountSettings::createAccountToolbox()
void AccountSettings::slotOpenAccountWizard()
{
if (QSystemTrayIcon::isSystemTrayAvailable()) {
if (
#if QT_VERSION > QT_VERSION_CHECK(5, 0, 0)
qgetenv("QT_QPA_PLATFORMTHEME") == "appmenu-qt5" ||
// We can't call isSystemTrayAvailable with appmenu-qt5 because it breaks the systemtray
// (issue #4693, #4944)
#endif
QSystemTrayIcon::isSystemTrayAvailable()) {
topLevelWidget()->close();
}
#ifdef Q_OS_MAC
@@ -197,8 +203,7 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
return;
}
QString alias = _model->data( index, FolderStatusDelegate::FolderAliasRole ).toString();
if (alias.isEmpty()) {
if (_model->classify(index) != FolderStatusModel::RootFolder) {
return;
}
+7 -7
Ver Arquivo
@@ -95,6 +95,9 @@ void AccountState::setState(State state)
} else if (oldState == SignedOut && _state == Disconnected) {
checkConnectivity();
}
if (oldState == Connected || _state == Connected) {
emit isConnectedChanged();
}
}
// might not have changed but the underlying _connectionErrors might have
@@ -149,11 +152,6 @@ bool AccountState::isConnectedOrTemporarilyUnavailable() const
return isConnected() || _state == ServiceUnavailable;
}
bool AccountState::canSync() const
{
return isConnected();
}
void AccountState::tagLastSuccessfullETagRequest()
{
_timeSinceLastETagCheck.restart();
@@ -192,7 +190,8 @@ void AccountState::checkConnectivity()
} else {
// Check the server and then the auth.
#ifdef Q_OS_WIN
// Let's try this for all OS and see if it fixes the Qt issues we have on Linux #4720 #3888 #4051
//#ifdef Q_OS_WIN
// There seems to be a bug in Qt on Windows where QNAM sometimes stops
// working correctly after the computer woke up from sleep. See #2895 #2899
// and #2973.
@@ -203,7 +202,7 @@ void AccountState::checkConnectivity()
// If we don't reset the ssl config a second CheckServerJob can produce a
// ssl config that does not have a sensible certificate chain.
account()->setSslConfiguration(QSslConfiguration());
#endif
//#endif
conValidator->checkServerAndAuth();
}
}
@@ -211,6 +210,7 @@ void AccountState::checkConnectivity()
void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList& errors)
{
if (isSignedOut()) {
qDebug() << "Signed out, ignoring" << connectionStatusString(status) << _account->url().toString();
return;
}
+1 -3
Ver Arquivo
@@ -102,9 +102,6 @@ public:
bool isConnected() const;
bool isConnectedOrTemporarilyUnavailable() const;
/// Returns whether sync actions are allowed to run.
bool canSync() const;
/// Triggers a ping to the server to update state and
/// connection status and errors.
void checkConnectivity();
@@ -130,6 +127,7 @@ private:
signals:
void stateChanged(int state);
void isConnectedChanged();
protected Q_SLOTS:
void slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList& errors);
+12
Ver Arquivo
@@ -139,6 +139,7 @@ Application::Application(int &argc, char **argv) :
setupTranslations();
// Setup global excludes
qDebug() << "Loading global exclude list";
ConfigFile cfg;
ExcludedFiles& excludes = ExcludedFiles::instance();
excludes.addExcludeFilePath( cfg.excludeFile(ConfigFile::SystemScope) );
@@ -335,6 +336,14 @@ void Application::slotownCloudWizardDone( int res )
}
}
static void csyncLogCatcher(int /*verbosity*/,
const char */*function*/,
const char *buffer,
void */*userdata*/)
{
Logger::instance()->csyncLog( QString::fromUtf8(buffer) );
}
void Application::setupLogging()
{
// might be called from second instance
@@ -350,6 +359,9 @@ void Application::setupLogging()
.arg(property("ui_lang").toString())
.arg(_theme->version());
// Setup CSYNC logging to forward to our own logger
csync_set_log_callback( csyncLogCatcher );
csync_set_log_level( Logger::instance()->isNoop() ? 0 : 11 );
}
void Application::slotUseMonoIconsChanged(bool)
+6 -1
Ver Arquivo
@@ -38,7 +38,12 @@ namespace OCC
class UserAgentWebPage : public QWebPage {
public:
UserAgentWebPage(QObject *parent) : QWebPage(parent) {}
UserAgentWebPage(QObject *parent) : QWebPage(parent)
{
if (!qgetenv("OWNCLOUD_SHIBBOLETH_DEBUG").isEmpty()) {
settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
}
}
QString userAgentForUrl(const QUrl &url ) const {
return QWebPage::userAgentForUrl(url) + " " + Utility::userAgentString();
}
+6 -1
Ver Arquivo
@@ -67,8 +67,13 @@ void ShibbolethCredentials::setAccount(Account* account)
{
AbstractCredentials::setAccount(account);
// This is for existing saved accounts.
if (_user.isEmpty()) {
_user = _account->credentialSetting(QLatin1String(userC)).toString();
}
// When constructed with a cookie (by the wizard), we usually don't know the
// user name yet. Request it now.
// user name yet. Request it now from the server.
if (_ready && _user.isEmpty()) {
QTimer::singleShot(1234, this, SLOT(slotFetchUser()));
}
+28 -25
Ver Arquivo
@@ -46,14 +46,6 @@
namespace OCC {
static void csyncLogCatcher(int /*verbosity*/,
const char */*function*/,
const char *buffer,
void */*userdata*/)
{
Logger::instance()->csyncLog( QString::fromUtf8(buffer) );
}
Folder::Folder(const FolderDefinition& definition,
AccountState* accountState,
@@ -96,6 +88,7 @@ Folder::Folder(const FolderDefinition& definition,
if (!setIgnoredFiles())
qWarning("Could not read system exclude file");
connect(_accountState.data(), SIGNAL(isConnectedChanged()), this, SIGNAL(canSyncChanged()));
connect(_engine.data(), SIGNAL(rootEtag(QString)), this, SLOT(etagRetreivedFromSyncEngine(QString)));
connect(_engine.data(), SIGNAL(treeWalkResult(const SyncFileItemVector&)),
this, SLOT(slotThreadTreeWalkResult(const SyncFileItemVector&)), Qt::QueuedConnection);
@@ -115,10 +108,13 @@ Folder::Folder(const FolderDefinition& definition,
connect(_engine.data(), SIGNAL(itemCompleted(const SyncFileItem &, const PropagatorJob &)),
this, SLOT(slotItemCompleted(const SyncFileItem &, const PropagatorJob &)));
connect(_engine.data(), SIGNAL(newBigFolder(QString)), this, SLOT(slotNewBigFolderDiscovered(QString)));
connect(_engine.data(), SIGNAL(seenLockedFile(QString)), FolderMan::instance(), SLOT(slotSyncOnceFileUnlocks(QString)));
}
Folder::~Folder()
{
// Reset then engine first as it will abort and try to access members of the Folder
_engine.reset();
}
void Folder::checkLocalPath()
@@ -229,7 +225,7 @@ bool Folder::syncPaused() const
bool Folder::canSync() const
{
return !syncPaused() && accountState()->canSync();
return !syncPaused() && accountState()->isConnected();
}
void Folder::setSyncPaused( bool paused )
@@ -248,6 +244,7 @@ void Folder::setSyncPaused( bool paused )
}
emit syncPausedChanged(this, paused);
emit syncStateChange();
emit canSyncChanged();
}
void Folder::setSyncState(SyncResult::Status state)
@@ -317,6 +314,7 @@ void Folder::slotRunEtagJob()
// sync if it's different.
_requestEtagJob = new RequestEtagJob(account, remotePath(), this);
_requestEtagJob->setTimeout(60*1000);
// check if the etag is different
QObject::connect(_requestEtagJob, SIGNAL(etagRetreived(QString)), this, SLOT(etagRetreived(QString)));
FolderMan::instance()->slotScheduleETagJob(alias(), _requestEtagJob);
@@ -575,18 +573,10 @@ int Folder::slotWipeErrorBlacklist()
void Folder::slotWatchedPathChanged(const QString& path)
{
// When no sync is running or it's in the prepare phase, we can
// always schedule a new sync.
if (! _engine->isSyncRunning() || _syncResult.status() == SyncResult::SyncPrepare) {
emit scheduleToSync(this);
return;
}
// The folder watcher fires a lot of bogus notifications during
// a sync operation, both for actual user files and the database
// and log. Therefore we check notifications against operations
// the sync is doing to filter out our own changes.
bool ownChange = false;
#ifdef Q_OS_MAC
Q_UNUSED(path)
// On OSX the folder watcher does not report changes done by our
@@ -596,13 +586,23 @@ void Folder::slotWatchedPathChanged(const QString& path)
const auto maxNotificationDelay = 15*1000;
qint64 time = _engine->timeSinceFileTouched(path);
if (time != -1 && time < maxNotificationDelay) {
ownChange = true;
return;
}
#endif
if (! ownChange) {
emit scheduleToSync(this);
// Check that the mtime actually changed.
if (path.startsWith(this->path())) {
auto relativePath = path.mid(this->path().size());
auto record = _journal.getFileRecord(relativePath);
if (record.isValid() && !FileSystem::fileChanged(path, record._fileSize,
Utility::qDateTimeToTime_t(record._modtime))) {
qDebug() << "Ignoring spurious notification for file" << relativePath;
return; // probably a spurious notification
}
}
emit watchedFileChangedExternally(path);
emit scheduleToSync(this);
}
void Folder::slotThreadTreeWalkResult(const SyncFileItemVector& items)
@@ -625,7 +625,7 @@ void Folder::removeFromSettings() const
{
auto settings = _accountState->settings();
settings->beginGroup(QLatin1String("Folders"));
settings->remove(_definition.alias);
settings->remove(FolderMan::escapeAlias(_definition.alias));
}
bool Folder::isFileExcludedAbsolute(const QString& fullPath) const
@@ -683,11 +683,16 @@ void Folder::wipe()
QFile::remove( stateDbFile + "-wal" );
QFile::remove( stateDbFile + "-journal" );
FolderMan::instance()->socketApi()->slotRegisterPath(alias());
if (canSync())
FolderMan::instance()->socketApi()->slotRegisterPath(alias());
}
bool Folder::setIgnoredFiles()
{
// Note: Doing this on each sync run and on Folder construction is
// unnecessary, because _engine->excludedFiles() persists between
// sync runs. This is not a big problem because ExcludedFiles maintains
// a QSet of files to load.
ConfigFile cfg;
QString systemList = cfg.excludeFile(ConfigFile::SystemScope);
if( QFile::exists(systemList) ) {
@@ -719,8 +724,6 @@ void Folder::startSync(const QStringList &pathList)
if (proxyDirty()) {
setProxyDirty(false);
}
csync_set_log_callback( csyncLogCatcher );
csync_set_log_level( Logger::instance()->isNoop() ? 0 : 11 );
if (isBusy()) {
qCritical() << "* ERROR csync is still running and new sync requested.";
@@ -909,7 +912,7 @@ void Folder::slotFolderDiscovered(bool, QString folderName)
// and hand the result over to the progress dispatcher.
void Folder::slotTransmissionProgress(const ProgressInfo &pi)
{
if( !pi.hasStarted() ) {
if( !pi.isUpdatingEstimates() ) {
// this is the beginning of a sync, set the warning level to 0
_syncResult.setWarnCount(0);
}
+7 -2
Ver Arquivo
@@ -131,8 +131,6 @@ public:
/**
* Returns true when the folder may sync.
*
* !syncPaused() && accountState->canSync().
*/
bool canSync() const;
@@ -203,6 +201,13 @@ signals:
void progressInfo(const ProgressInfo& progress);
void newBigFolderDiscovered(const QString &); // A new folder bigger than the threshold was discovered
void syncPausedChanged(Folder*, bool paused);
void canSyncChanged();
/**
* Fires for each change inside this folder that wasn't caused
* by sync activity.
*/
void watchedFileChangedExternally(const QString& path);
public slots:
+37 -2
Ver Arquivo
@@ -22,6 +22,7 @@
#include "accountstate.h"
#include "accountmanager.h"
#include "filesystem.h"
#include "lockwatcher.h"
#include <syncengine.h>
#ifdef Q_OS_MAC
@@ -44,6 +45,7 @@ FolderMan::FolderMan(QObject *parent) :
QObject(parent),
_currentSyncFolder(0),
_syncEnabled( true ),
_lockWatcher(new LockWatcher),
_appRestartRequired(false)
{
Q_ASSERT(!_instance);
@@ -64,6 +66,9 @@ FolderMan::FolderMan(QObject *parent) :
connect(AccountManager::instance(), SIGNAL(accountRemoved(AccountState*)),
SLOT(slotRemoveFoldersForAccount(AccountState*)));
connect(_lockWatcher.data(), SIGNAL(fileUnlocked(QString)),
SLOT(slotScheduleFolderOwningFile(QString)));
}
FolderMan *FolderMan::instance()
@@ -107,6 +112,8 @@ void FolderMan::unloadFolder( Folder *f )
this, SLOT(slotFolderSyncPaused(Folder*,bool)));
disconnect(&f->syncEngine().syncFileStatusTracker(), SIGNAL(fileStatusChanged(const QString &, SyncFileStatus)),
_socketApi.data(), SLOT(slotFileStatusChanged(const QString &, SyncFileStatus)));
disconnect(f, SIGNAL(watchedFileChangedExternally(QString)),
&f->syncEngine().syncFileStatusTracker(), SLOT(slotPathTouched(QString)));
}
int FolderMan::unloadAndDeleteAllFolders()
@@ -145,11 +152,13 @@ void FolderMan::registerFolderMonitor( Folder *folder )
// to the signal mapper which maps to the folder alias. The changed path
// is lost this way, but we do not need it for the current implementation.
connect(fw, SIGNAL(pathChanged(QString)), folder, SLOT(slotWatchedPathChanged(QString)));
_folderWatchers.insert(folder->alias(), fw);
}
// register the folder with the socket API
_socketApi->slotRegisterPath(folder->alias());
if (folder->canSync())
_socketApi->slotRegisterPath(folder->alias());
}
void FolderMan::addMonitorPath( const QString& alias, const QString& path )
@@ -419,6 +428,17 @@ void FolderMan::slotFolderSyncPaused( Folder *f, bool paused )
}
}
void FolderMan::slotFolderCanSyncChanged()
{
Folder *f = qobject_cast<Folder*>(sender());
Q_ASSERT(f);
if (f->canSync()) {
_socketApi->slotRegisterPath(f->alias());
} else {
_socketApi->slotUnregisterPath(f->alias());
}
}
// this really terminates the current sync process
// ie. no questions, no prisoners
// csync still remains in a stable state, regardless of that.
@@ -457,6 +477,11 @@ void FolderMan::slotScheduleAppRestart()
qDebug() << "## Application restart requested!";
}
void FolderMan::slotSyncOnceFileUnlocks(const QString& path)
{
_lockWatcher->addFile(path);
}
/*
* if a folder wants to be synced, it calls this slot and is added
* to the queue. The slot to actually start a sync is called afterwards.
@@ -536,7 +561,7 @@ void FolderMan::slotAccountStateChanged()
}
QString accountName = accountState->account()->displayName();
if (accountState->canSync()) {
if (accountState->isConnected()) {
qDebug() << "Account" << accountName << "connected, scheduling its folders";
foreach (Folder *f, _folderMap.values()) {
@@ -741,6 +766,13 @@ void FolderMan::slotServerVersionChanged(Account *account)
}
}
void FolderMan::slotScheduleFolderOwningFile(const QString& path)
{
if (Folder* f = folderForPath(path)) {
slotScheduleSync(f);
}
}
void FolderMan::slotFolderSyncStarted( )
{
qDebug() << ">===================================== sync started for " << _currentSyncFolder->remoteUrl().toString();
@@ -800,8 +832,11 @@ Folder* FolderMan::addFolderInternal(FolderDefinition folderDefinition, AccountS
connect(folder, SIGNAL(syncFinished(SyncResult)), SLOT(slotFolderSyncFinished(SyncResult)));
connect(folder, SIGNAL(syncStateChange()), SLOT(slotForwardFolderSyncStateChange()));
connect(folder, SIGNAL(syncPausedChanged(Folder*,bool)), SLOT(slotFolderSyncPaused(Folder*,bool)));
connect(folder, SIGNAL(canSyncChanged()), SLOT(slotFolderCanSyncChanged()));
connect(&folder->syncEngine().syncFileStatusTracker(), SIGNAL(fileStatusChanged(const QString &, SyncFileStatus)),
_socketApi.data(), SLOT(slotFileStatusChanged(const QString &, SyncFileStatus)));
connect(folder, SIGNAL(watchedFileChangedExternally(QString)),
&folder->syncEngine().syncFileStatusTracker(), SLOT(slotPathTouched(QString)));
registerFolderMonitor(folder);
return folder;
+16
Ver Arquivo
@@ -32,6 +32,7 @@ namespace OCC {
class Application;
class SyncResult;
class SocketApi;
class LockWatcher;
/**
* @brief The FolderMan class
@@ -143,6 +144,7 @@ signals:
public slots:
void slotRemoveFolder( Folder* );
void slotFolderSyncPaused(Folder *, bool paused);
void slotFolderCanSyncChanged();
void slotFolderSyncStarted();
void slotFolderSyncFinished( const SyncResult& );
@@ -184,6 +186,13 @@ public slots:
*/
void slotScheduleAppRestart();
/**
* Triggers a sync run once the lock on the given file is removed.
*
* Automatically detemines the folder that's responsible for the file.
*/
void slotSyncOnceFileUnlocks(const QString& path);
private slots:
// slot to take the next folder from queue and start syncing.
void slotStartScheduledFolderSync();
@@ -197,6 +206,12 @@ private slots:
void slotServerVersionChanged(Account* account);
/**
* Schedules the folder for synchronization that contains
* the file with the given path.
*/
void slotScheduleFolderOwningFile(const QString& path);
private:
/** Adds a new folder, does not add it to the account settings and
* does not set an account on the new folder.
@@ -227,6 +242,7 @@ private:
QPointer<RequestEtagJob> _currentEtagJob; // alias of Folder running the current RequestEtagJob
QMap<QString, FolderWatcher*> _folderWatchers;
QScopedPointer<LockWatcher> _lockWatcher;
QScopedPointer<SocketApi> _socketApi;
/** The aliases of folders that shall be synced. */
+10 -7
Ver Arquivo
@@ -574,9 +574,6 @@ void FolderStatusModel::slotUpdateDirectories(const QStringList &list)
return;
}
QVarLengthArray<int, 10> undecidedIndexes;
QVector<SubFolderInfo> newSubs;
std::set<QString> selectiveSyncUndecidedSet; // not QSet because it's not sorted
foreach (const QString &str, selectiveSyncUndecidedList) {
if (str.startsWith(parentInfo->_path) || parentInfo->_path == QLatin1String("/")) {
@@ -584,10 +581,16 @@ void FolderStatusModel::slotUpdateDirectories(const QStringList &list)
}
}
newSubs.reserve(list.size() - 1);
for (int i = 1; // skip the parent item (first in the list)
i < list.size(); ++i) {
const QString &path = list.at(i);
QStringList sortedSubfolders = list;
// skip the parent item (first in the list)
sortedSubfolders.erase(sortedSubfolders.begin());
sortedSubfolders.sort();
QVarLengthArray<int, 10> undecidedIndexes;
QVector<SubFolderInfo> newSubs;
newSubs.reserve(sortedSubfolders.size());
foreach (const QString& path, sortedSubfolders) {
auto relativePath = path.mid(pathToRemove.size());
if (parentInfo->_folder->isFileExcludedRelative(relativePath)) {
continue;
+15 -1
Ver Arquivo
@@ -51,6 +51,14 @@ static void callback(
Q_UNUSED(eventFlags)
Q_UNUSED(eventIds)
const FSEventStreamEventFlags c_interestingFlags
= kFSEventStreamEventFlagItemCreated // for new folder/file
| kFSEventStreamEventFlagItemRemoved // for rm
| kFSEventStreamEventFlagItemInodeMetaMod // for mtime change
| kFSEventStreamEventFlagItemRenamed // also coming for moves to trash in finder
| kFSEventStreamEventFlagItemModified; // for content change
//We ignore other flags, e.g. for owner change, xattr change, Finder label change etc
qDebug() << "FolderWatcherPrivate::callback by OS X";
QStringList paths;
@@ -62,8 +70,14 @@ static void callback(
CFIndex pathLength = CFStringGetLength(path);
qstring.resize(pathLength);
CFStringGetCharacters(path, CFRangeMake(0, pathLength), reinterpret_cast<UniChar *>(qstring.data()));
QString fn = qstring.normalized(QString::NormalizationForm_C);
paths.append(qstring.normalized(QString::NormalizationForm_C));
if (!(eventFlags[i] & c_interestingFlags)) {
qDebug() << "Ignoring non-content changes for" << fn;
continue;
}
paths.append(fn);
}
reinterpret_cast<FolderWatcherPrivate*>(clientCallBackInfo)->doNotifyParent(paths);
+29 -19
Ver Arquivo
@@ -68,13 +68,6 @@ FolderWizardLocalPath::FolderWizardLocalPath()
_ui.localFolderLineEdit->setText( QDir::toNativeSeparators( defaultPath ) );
_ui.localFolderLineEdit->setToolTip(tr("Enter the path to the local folder."));
QString newAlias = Theme::instance()->appName();
int count = 0;
while (FolderMan::instance()->folder(newAlias)) {
// There is already a folder configured with this name and folder names need to be unique
newAlias = Theme::instance()->appName() + QString::number(++count);
}
_ui.warnLabel->setTextFormat(Qt::RichText);
_ui.warnLabel->hide();
}
@@ -135,14 +128,6 @@ void FolderWizardLocalPath::slotChooseLocalFolder()
if (!dir.isEmpty()) {
// set the last directory component name as alias
_ui.localFolderLineEdit->setText(QDir::toNativeSeparators(dir));
QDir pickedDir(dir);
QString newAlias = pickedDir.dirName();
int count = 0;
while (FolderMan::instance()->folder(newAlias)) {
// There is already a folder configured with this name and folder names need to be unique
newAlias = pickedDir.dirName() + QString::number(++count);
}
}
emit completeChanged();
}
@@ -306,6 +291,7 @@ bool FolderWizardRemotePath::selectByPath(QString path)
}
_ui.folderTreeWidget->setCurrentItem(it);
_ui.folderTreeWidget->scrollToItem(it);
return true;
}
@@ -321,7 +307,9 @@ void FolderWizardRemotePath::slotUpdateDirectories(const QStringList &list)
root->setToolTip(0, tr("Choose this to sync the entire account"));
root->setData(0, Qt::UserRole, "/");
}
foreach (QString path, list) {
QStringList sortedList = list;
sortedList.sort();
foreach (QString path, sortedList) {
path.remove(webdavFolder);
QStringList paths = path.split('/');
if (paths.last().isEmpty()) paths.removeLast();
@@ -374,8 +362,11 @@ void FolderWizardRemotePath::slotLsColFolderEntry()
path = path.mid(1);
LsColJob *job = runLsColJob(path);
// no error handling, no updating, we do this manually
// No error handling, no updating, we do this manually
// because of extra logic in the typed-path case.
disconnect(job, 0, this, 0);
connect(job, SIGNAL(finishedWithError(QNetworkReply*)),
SLOT(slotTypedPathError(QNetworkReply*)));
connect(job, SIGNAL(directoryListingSubfolders(QStringList)),
SLOT(slotTypedPathFound(QStringList)));
}
@@ -386,6 +377,21 @@ void FolderWizardRemotePath::slotTypedPathFound(const QStringList& subpaths)
selectByPath(_ui.folderEntry->text());
}
void FolderWizardRemotePath::slotTypedPathError(QNetworkReply* reply)
{
// Ignore 404s, otherwise users will get annoyed by error popups
// when not typing fast enough. It's still clear that a given path
// was not found, because the 'Next' button is disabled and no entry
// is selected in the tree view.
int httpCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (httpCode == 404) {
showWarn(""); // hides the warning pane
return;
}
slotHandleLsColNetworkError(reply);
}
LsColJob* FolderWizardRemotePath::runLsColJob(const QString& path)
{
LsColJob *job = new LsColJob(_account, path, this);
@@ -482,11 +488,13 @@ FolderWizardSelectiveSync::~FolderWizardSelectiveSync()
void FolderWizardSelectiveSync::initializePage()
{
QString alias = wizard()->field(QLatin1String("alias")).toString();
QString targetPath = wizard()->property("targetPath").toString();
if (targetPath.startsWith('/')) {
targetPath = targetPath.mid(1);
}
QString alias = QFileInfo(targetPath).fileName();
if (alias.isEmpty())
alias = Theme::instance()->appName();
_treeView->setFolderInfo(targetPath, alias);
QWizardPage::initializePage();
}
@@ -499,8 +507,10 @@ bool FolderWizardSelectiveSync::validatePage()
void FolderWizardSelectiveSync::cleanupPage()
{
QString alias = wizard()->field(QLatin1String("alias")).toString();
QString targetPath = wizard()->property("targetPath").toString();
QString alias = QFileInfo(targetPath).fileName();
if (alias.isEmpty())
alias = Theme::instance()->appName();
_treeView->setFolderInfo(targetPath, alias);
QWizardPage::cleanupPage();
}
+1
Ver Arquivo
@@ -98,6 +98,7 @@ protected slots:
void slotFolderEntryEdited(const QString& text);
void slotLsColFolderEntry();
void slotTypedPathFound(const QStringList& subpaths);
void slotTypedPathError(QNetworkReply* reply);
private:
LsColJob* runLsColJob(const QString& path);
void recursiveInsert(QTreeWidgetItem *parent, QStringList pathTrail, QString path);
-8
Ver Arquivo
@@ -161,12 +161,4 @@ void GeneralSettings::slotIgnoreFilesEditor()
}
}
void GeneralSettings::slotOpenAccountWizard()
{
if (QSystemTrayIcon::isSystemTrayAvailable()) {
topLevelWidget()->close();
}
OwncloudSetupWizard::runWizard(qApp, SLOT(slotownCloudWizardDone(int)), 0);
}
} // namespace OCC
-1
Ver Arquivo
@@ -44,7 +44,6 @@ private slots:
void slotToggleOptionalDesktopNotifications(bool);
void slotUpdateInfo();
void slotIgnoreFilesEditor();
void slotOpenAccountWizard();
private:
void loadMiscSettings();
+51
Ver Arquivo
@@ -0,0 +1,51 @@
/*
* Copyright (C) by Christian Kamm <mail@ckamm.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "lockwatcher.h"
#include "filesystem.h"
#include <QTimer>
using namespace OCC;
static const int check_frequency = 20 * 1000; // ms
LockWatcher::LockWatcher(QObject* parent)
: QObject(parent)
{
connect(&_timer, SIGNAL(timeout()),
SLOT(checkFiles()));
_timer.start(check_frequency);
}
void LockWatcher::addFile(const QString& path)
{
_watchedPaths.insert(path);
}
void LockWatcher::checkFiles()
{
QSet<QString> unlocked;
foreach (const QString& path, _watchedPaths) {
if (!FileSystem::isFileLocked(path)) {
emit fileUnlocked(path);
unlocked.insert(path);
}
}
// Doing it this way instead of with a QMutableSetIterator
// ensures that calling back into addFile from connected
// slots isn't a problem.
_watchedPaths.subtract(unlocked);
}
+66
Ver Arquivo
@@ -0,0 +1,66 @@
/*
* Copyright (C) by Christian Kamm <mail@ckamm.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#pragma once
#include "config.h"
#include <QList>
#include <QObject>
#include <QString>
#include <QSet>
#include <QTimer>
namespace OCC {
/**
* @brief Monitors files that are locked, signaling when they become unlocked
*
* Only relevant on Windows. Some high-profile applications like Microsoft
* Word lock the document that is currently being edited. The synchronization
* client will be unable to update them while they are locked.
*
* In this situation we do want to start a sync run as soon as the file
* becomes available again. To do that, we need to regularly check whether
* the file is still being locked.
*
* @ingroup gui
*/
class LockWatcher : public QObject
{
Q_OBJECT
public:
explicit LockWatcher(QObject* parent = 0);
/** Start watching a file.
*
* If the file is not locked later on, the fileUnlocked signal will be
* emitted once.
*/
void addFile(const QString& path);
signals:
/** Emitted when one of the watched files is no longer
* being locked. */
void fileUnlocked(const QString& path);
private slots:
void checkFiles();
private:
QSet<QString> _watchedPaths;
QTimer _timer;
};
}
+17 -6
Ver Arquivo
@@ -47,18 +47,19 @@ int main(int argc, char **argv)
{
Q_INIT_RESOURCE(client);
#ifndef Q_OS_MAC
#ifdef Q_OS_WIN
// If the font size ratio is set on Windows, we need to
// enable the auto pixelRatio in Qt since we don't
// want to use sizes relative to the font size everywhere.
// This is automatic on OS X, but opt-in on Windows and Linux
// https://doc-snapshots.qt.io/qt5-5.6/highdpi.html#qt-support
#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
qputenv("QT_DEVICE_PIXEL_RATIO", "auto");
#else
// We do not define it on linux so the behaviour is kept the same
// as other Qt apps in the desktop environment. (which may or may
// not set this envoronment variable)
#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
#endif
#endif // !Q_OS_MAC
#endif // !Q_OS_WIN
#ifdef Q_OS_MAC
Mac::CocoaInitializer cocoaInit; // RIIA
@@ -127,8 +128,17 @@ int main(int argc, char **argv)
return -1;
}
return 0;
} else {
}
#if QT_VERSION > QT_VERSION_CHECK(5, 0, 0)
if (qgetenv("QT_QPA_PLATFORMTHEME") != "appmenu-qt5")
// We can't call isSystemTrayAvailable with appmenu-qt5 begause it hides the systemtray
// (issue #4693)
#endif
{
if (!QSystemTrayIcon::isSystemTrayAvailable()) {
// If the systemtray is not there, we will wait one second for it to maybe start
// (eg boot time) then we show the settings dialog if there is still no systemtray.
// On XFCE however, we show a message box with explainaition how to install a systemtray.
Utility::sleep(1);
auto desktopSession = qgetenv("XDG_CURRENT_DESKTOP").toLower();
if (desktopSession.isEmpty()) {
@@ -152,6 +162,7 @@ int main(int argc, char **argv)
}
}
}
return app.exec();
}
+1 -1
Ver Arquivo
@@ -685,7 +685,7 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const ProgressInfo&
slotRebuildRecentMenus();
}
if (progress.hasStarted()
if (progress.isUpdatingEstimates()
&& progress.completedFiles() >= progress.totalFiles()
&& progress._currentDiscoveredFolder.isEmpty()) {
QTimer::singleShot(2000, this, SLOT(slotDisplayIdle()));
+1 -1
Ver Arquivo
@@ -173,7 +173,7 @@ void OwncloudSetupWizard::slotNoOwnCloudFoundAuth(QNetworkReply *reply)
// Allow the credentials dialog to pop up again for the same URL.
// Maybe the user just clicked 'Cancel' by accident or changed his mind.
_ocWizard->account()->resetSslCertErrorState();
_ocWizard->account()->resetRejectedCertificates();
}
void OwncloudSetupWizard::slotNoOwnCloudFoundAuthTimeout(const QUrl&url)
+22 -10
Ver Arquivo
@@ -57,7 +57,16 @@ ProtocolWidget::ProtocolWidget(QWidget *parent) :
header << tr("Action");
header << tr("Size");
int timestampColumnExtra = 0;
#ifdef Q_OS_WIN
timestampColumnExtra = 20; // font metrics are broken on Windows, see #4721
#endif
_ui->_treeWidget->setHeaderLabels( header );
int timestampColumnWidth =
_ui->_treeWidget->fontMetrics().width(timeString(QDateTime::currentDateTime()))
+ timestampColumnExtra;
_ui->_treeWidget->setColumnWidth(0, timestampColumnWidth);
_ui->_treeWidget->setColumnWidth(1, 180);
_ui->_treeWidget->setColumnCount(5);
_ui->_treeWidget->setRootIsDecorated(false);
@@ -79,6 +88,11 @@ ProtocolWidget::ProtocolWidget(QWidget *parent) :
_issueItemView = new QTreeWidget(this);
header.removeLast();
_issueItemView->setHeaderLabels( header );
timestampColumnWidth =
ActivityItemDelegate::rowHeight() // icon
+ _issueItemView->fontMetrics().width(timeString(QDateTime::currentDateTime()))
+ timestampColumnExtra;
_issueItemView->setColumnWidth(0, timestampColumnWidth);
_issueItemView->setColumnWidth(1, 180);
_issueItemView->setColumnCount(4);
_issueItemView->setRootIsDecorated(false);
@@ -107,17 +121,9 @@ void ProtocolWidget::hideEvent(QHideEvent *ev)
void ProtocolWidget::cleanItems(const QString& folder)
{
int itemCnt = _ui->_treeWidget->topLevelItemCount();
// Limit the number of items
while(itemCnt > 2000) {
delete _ui->_treeWidget->takeTopLevelItem(itemCnt - 1);
itemCnt--;
}
// The issue list is a state, clear it and let the next sync fill it
// with ignored files and propagation errors.
itemCnt = _issueItemView->topLevelItemCount();
int itemCnt = _issueItemView->topLevelItemCount();
for( int cnt = itemCnt-1; cnt >=0 ; cnt-- ) {
QTreeWidgetItem *item = _issueItemView->topLevelItem(cnt);
QString itemFolder = item->data(2, Qt::UserRole).toString();
@@ -205,7 +211,7 @@ QTreeWidgetItem* ProtocolWidget::createCompletedTreewidgetItem(const QString& fo
void ProtocolWidget::slotProgressInfo( const QString& folder, const ProgressInfo& progress )
{
if( !progress.hasStarted() ) {
if( !progress.isUpdatingEstimates() ) {
// The sync is restarting, clean the old items
cleanItems(folder);
} else if (progress.completedFiles() >= progress.totalFiles()) {
@@ -225,6 +231,12 @@ void ProtocolWidget::slotItemCompleted(const QString &folder, const SyncFileItem
_issueItemView->insertTopLevelItem(0, line);
emit issueItemCountUpdated(_issueItemView->topLevelItemCount());
} else {
// Limit the number of items
int itemCnt = _ui->_treeWidget->topLevelItemCount();
while(itemCnt > 2000) {
delete _ui->_treeWidget->takeTopLevelItem(itemCnt - 1);
itemCnt--;
}
_ui->_treeWidget->insertTopLevelItem(0, line);
}
}
+1
Ver Arquivo
@@ -222,6 +222,7 @@ void SelectiveSyncTreeView::slotUpdateDirectories(QStringList list)
}
}
list.sort();
foreach (QString path, list) {
auto size = job ? job->_sizes.value(path) : 0;
path.remove(pathToRemove);
-11
Ver Arquivo
@@ -98,17 +98,6 @@ ShareLinkWidget::ShareLinkWidget(AccountPtr account,
return;
}
// error label, red box and stuff
_ui->errorLabel->setLineWidth(1);
_ui->errorLabel->setFrameStyle(QFrame::Plain);
QPalette errPalette = _ui->errorLabel->palette();
errPalette.setColor(QPalette::Active, QPalette::Base, QColor(0xaa, 0x4d, 0x4d));
errPalette.setColor(QPalette::Active, QPalette::WindowText, QColor(0xaa, 0xaa, 0xaa));
_ui->errorLabel->setPalette(errPalette);
_ui->errorLabel->setFrameShape(QFrame::Box);
_ui->errorLabel->setContentsMargins(QMargins(12,12,12,12));
_ui->errorLabel->hide();
+37
Ver Arquivo
@@ -36,6 +36,43 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>123</red>
<green>121</green>
<blue>134</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="text">
<string>TextLabel</string>
</property>
+7 -4
Ver Arquivo
@@ -72,9 +72,7 @@ ShareUserGroupWidget::ShareUserGroupWidget(AccountPtr account,
_completer->setModel(_completerModel);
_completer->setCaseSensitivity(Qt::CaseInsensitive);
#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
_completer->setFilterMode(Qt::MatchContains);
#endif
_completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
_ui->shareeLineEdit->setCompleter(_completer);
_manager = new ShareManager(_account, this);
@@ -99,6 +97,9 @@ ShareUserGroupWidget::ShareUserGroupWidget(AccountPtr account,
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
_ui->errorLabel->hide();
// Setup the sharee search progress indicator
_ui->shareeHorizontalLayout->addWidget(&_pi_sharee);
}
ShareUserGroupWidget::~ShareUserGroupWidget()
@@ -147,6 +148,7 @@ void ShareUserGroupWidget::slotLineEditReturn()
void ShareUserGroupWidget::searchForSharees()
{
_completionTimer.stop();
_pi_sharee.startAnimation();
ShareeModel::ShareeSet blacklist;
// Add the current user to _sharees since we can't share with ourself
@@ -158,7 +160,6 @@ void ShareUserGroupWidget::searchForSharees()
}
_ui->errorLabel->hide();
_completerModel->fetch(_ui->shareeLineEdit->text(), blacklist);
}
void ShareUserGroupWidget::getShares()
@@ -218,6 +219,7 @@ void ShareUserGroupWidget::slotAdjustScrollWidgetSize()
void ShareUserGroupWidget::slotShareesReady()
{
_pi_sharee.stopAnimation();
if (_completerModel->rowCount() == 0) {
displayError(0, tr("No results for '%1'").arg(_completerModel->currentSearch()));
return;
@@ -274,6 +276,7 @@ void ShareUserGroupWidget::slotCompleterHighlighted(const QModelIndex & index)
void ShareUserGroupWidget::displayError(int code, const QString& message)
{
_pi_sharee.stopAnimation();
qDebug() << "Error from server" << code << message;
_ui->errorLabel->setText(message);
_ui->errorLabel->show();
+2
Ver Arquivo
@@ -129,6 +129,8 @@ private:
bool _isFile;
bool _disableCompleterActivated; // in order to avoid that we share the contents twice
ShareManager *_manager;
QProgressIndicator _pi_sharee;
};
}
+49 -8
Ver Arquivo
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>457</width>
<height>188</height>
<height>164</height>
</rect>
</property>
<property name="windowTitle">
@@ -15,14 +15,55 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLineEdit" name="shareeLineEdit">
<property name="placeholderText">
<string>Share with users or groups ...</string>
</property>
</widget>
<layout class="QHBoxLayout" name="shareeHorizontalLayout">
<item>
<widget class="QLineEdit" name="shareeLineEdit">
<property name="placeholderText">
<string>Share with users or groups ...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="errorLabel">
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>123</red>
<green>121</green>
<blue>134</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="text">
<string notr="true">Placeholder for Error text</string>
</property>
@@ -50,8 +91,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>441</width>
<height>98</height>
<width>437</width>
<height>94</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3"/>
+37 -19
Ver Arquivo
@@ -56,6 +56,13 @@
// The second number should be changed when there are new features.
#define MIRALL_SOCKET_API_VERSION "1.0"
static inline QString removeTrailingSlash(QString path)
{
Q_ASSERT(path.endsWith(QLatin1Char('/')));
path.truncate(path.length()-1);
return path;
}
namespace OCC {
#define DEBUG qDebug() << "SocketApi: "
@@ -67,7 +74,8 @@ SocketApi::SocketApi(QObject* parent)
if (Utility::isWindows()) {
socketPath = QLatin1String("\\\\.\\pipe\\")
+ QLatin1String("ownCloud");
+ QLatin1String("ownCloud") + '\\'
+ QString::fromLocal8Bit(qgetenv("USERNAME"));
// TODO: once the windows extension supports multiple
// client connections, switch back to the theme name
// See issue #2388
@@ -140,8 +148,10 @@ void SocketApi::slotNewConnection()
_listeners.append(socket);
foreach( Folder *f, FolderMan::instance()->map() ) {
QString message = buildRegisterPathMessage(f->path());
sendMessage(socket, message);
if (f->canSync()) {
QString message = buildRegisterPathMessage(removeTrailingSlash(f->path()));
sendMessage(socket, message);
}
}
}
@@ -180,20 +190,31 @@ void SocketApi::slotReadSocket()
void SocketApi::slotRegisterPath( const QString& alias )
{
// Make sure not to register twice to each connected client
if (_registeredAliases.contains(alias))
return;
Folder *f = FolderMan::instance()->folder(alias);
if (f) {
QString message = buildRegisterPathMessage(f->path());
QString message = buildRegisterPathMessage(removeTrailingSlash(f->path()));
foreach(QIODevice *socket, _listeners) {
sendMessage(socket, message);
}
}
_registeredAliases.insert(alias);
}
void SocketApi::slotUnregisterPath( const QString& alias )
{
if (!_registeredAliases.contains(alias))
return;
Folder *f = FolderMan::instance()->folder(alias);
if (f)
broadcastMessage(QLatin1String("UNREGISTER_PATH"), f->path(), QString::null, true );
broadcastMessage(QLatin1String("UNREGISTER_PATH"), removeTrailingSlash(f->path()), QString::null, true );
_registeredAliases.remove(alias);
}
void SocketApi::slotUpdateFolderView(Folder *f)
@@ -211,10 +232,11 @@ void SocketApi::slotUpdateFolderView(Folder *f)
f->syncResult().status() == SyncResult::Error ||
f->syncResult().status() == SyncResult::SetupError ) {
broadcastMessage(QLatin1String("STATUS"), f->path() ,
QString rootPath = removeTrailingSlash(f->path());
broadcastMessage(QLatin1String("STATUS"), rootPath,
f->syncEngine().syncFileStatusTracker().fileStatus("").toSocketAPIString());
broadcastMessage(QLatin1String("UPDATE_VIEW"), f->path() );
broadcastMessage(QLatin1String("UPDATE_VIEW"), rootPath);
} else {
qDebug() << "Not sending UPDATE_VIEW for" << f->alias() << "because status() is" << f->syncResult().status();
}
@@ -274,8 +296,6 @@ void SocketApi::command_RETRIEVE_FOLDER_STATUS(const QString& argument, QIODevic
void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, QIODevice* socket)
{
const QString nopString("NOP");
if( !socket ) {
qDebug() << "No valid socket object.";
return;
@@ -288,18 +308,16 @@ void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, QIODevice*
Folder* syncFolder = FolderMan::instance()->folderForPath( argument );
if (!syncFolder) {
// this can happen in offline mode e.g.: nothing to worry about
statusString = nopString;
statusString = QLatin1String("NOP");
} else {
const QString file = QDir::cleanPath(argument).mid(syncFolder->cleanPath().length()+1);
// future: Send more specific states for paused, disconnected etc.
if( syncFolder->syncPaused() || !syncFolder->accountState()->isConnected() ) {
statusString = nopString;
} else {
SyncFileStatus fileStatus = syncFolder->syncEngine().syncFileStatusTracker().fileStatus(file);
statusString = fileStatus.toSocketAPIString();
QString relativePath = QDir::cleanPath(argument).mid(syncFolder->cleanPath().length()+1);
if( relativePath.endsWith(QLatin1Char('/')) ) {
relativePath.truncate(relativePath.length()-1);
qWarning() << "Removed trailing slash for directory: " << relativePath << "Status pushes won't have one.";
}
SyncFileStatus fileStatus = syncFolder->syncEngine().syncFileStatusTracker().fileStatus(relativePath);
statusString = fileStatus.toSocketAPIString();
}
const QString message = QLatin1String("STATUS:") % statusString % QLatin1Char(':') % QDir::toNativeSeparators(argument);
+1
Ver Arquivo
@@ -77,6 +77,7 @@ private:
Q_INVOKABLE void command_SHARE_MENU_TITLE(const QString& argument, QIODevice* socket);
QString buildRegisterPathMessage(const QString& path);
QSet<QString> _registeredAliases;
QList<QIODevice*> _listeners;
SocketApiServer _localServer;
};
+2
Ver Arquivo
@@ -218,6 +218,7 @@ void OCUpdater::slotVersionInfoArrived()
{
_timeoutWatchdog->stop();
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
reply->deleteLater();
if( reply->error() != QNetworkReply::NoError ) {
qDebug() << "Failed to reach version check url: " << reply->errorString();
return;
@@ -258,6 +259,7 @@ void NSISUpdater::slotWriteFile()
void NSISUpdater::slotDownloadFinished()
{
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
reply->deleteLater();
if (reply->error() != QNetworkReply::NoError) {
setDownloadState(DownloadFailed);
return;
+1
Ver Arquivo
@@ -242,6 +242,7 @@ void AbstractNetworkJob::slotTimeout()
reply()->abort();
} else {
qDebug() << Q_FUNC_INFO << this << "Timeout reply was NULL";
deleteLater();
}
}
+45 -31
Ver Arquivo
@@ -38,9 +38,6 @@ namespace OCC {
Account::Account(QObject *parent)
: QObject(parent)
, _capabilities(QVariantMap())
, _am(0)
, _credentials(0)
, _treatSslErrorsAsFailure(false)
, _davPath( Theme::instance()->webDavPath() )
, _wasMigrated(false)
{
@@ -56,8 +53,6 @@ AccountPtr Account::create()
Account::~Account()
{
delete _credentials;
delete _am;
}
QString Account::davPath() const
@@ -118,14 +113,14 @@ bool Account::changed(AccountPtr other, bool ignoreUrlProtocol) const
changes = (_url == other->_url);
}
changes |= _credentials->changed(other->_credentials);
changes |= _credentials->changed(other->credentials());
return changes;
}
AbstractCredentials *Account::credentials() const
{
return _credentials;
return _credentials.data();
}
void Account::setCredentials(AbstractCredentials *cred)
@@ -136,29 +131,27 @@ void Account::setCredentials(AbstractCredentials *cred)
jar = _am->cookieJar();
jar->setParent(0);
_am->deleteLater();
}
if (_credentials) {
credentials()->deleteLater();
_am = QSharedPointer<QNetworkAccessManager>();
}
// The order for these two is important! Reading the credential's
// settings accesses the account as well as account->_credentials
_credentials = cred;
// settings accesses the account as well as account->_credentials,
// so deleteLater must be used.
_credentials = QSharedPointer<AbstractCredentials>(cred, &QObject::deleteLater);
cred->setAccount(this);
_am = _credentials->getQNAM();
_am = QSharedPointer<QNetworkAccessManager>(_credentials->getQNAM(), &QObject::deleteLater);
if (jar) {
_am->setCookieJar(jar);
}
connect(_am, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
connect(_am.data(), SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
SLOT(slotHandleSslErrors(QNetworkReply*,QList<QSslError>)));
connect(_am, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
connect(_am.data(), SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
connect(_credentials, SIGNAL(fetched()),
connect(_credentials.data(), SIGNAL(fetched()),
SLOT(slotCredentialsFetched()));
connect(_credentials, SIGNAL(asked()),
connect(_credentials.data(), SIGNAL(asked()),
SLOT(slotCredentialsAsked()));
}
@@ -197,18 +190,21 @@ void Account::resetNetworkAccessManager()
qDebug() << "Resetting QNAM";
QNetworkCookieJar* jar = _am->cookieJar();
_am->deleteLater();
_am = _credentials->getQNAM();
// Use a QSharedPointer to allow locking the life of the QNAM on the stack.
// Make it call deleteLater to make sure that we can return to any QNAM stack frames safely.
_am = QSharedPointer<QNetworkAccessManager>(_credentials->getQNAM(), &QObject::deleteLater);
_am->setCookieJar(jar); // takes ownership of the old cookie jar
connect(_am, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
connect(_am.data(), SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
SLOT(slotHandleSslErrors(QNetworkReply*,QList<QSslError>)));
connect(_am, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
connect(_am.data(), SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
}
QNetworkAccessManager *Account::networkAccessManager()
{
return _am;
return _am.data();
}
QNetworkReply *Account::headRequest(const QString &relPath)
@@ -329,9 +325,9 @@ void Account::addApprovedCerts(const QList<QSslCertificate> certs)
_approvedCerts += certs;
}
void Account::resetSslCertErrorState()
void Account::resetRejectedCertificates()
{
_treatSslErrorsAsFailure = false;
_rejectedCertificates.clear();
}
void Account::setSslErrorHandler(AbstractSslErrorHandler *handler)
@@ -412,8 +408,15 @@ void Account::slotHandleSslErrors(QNetworkReply *reply , QList<QSslError> errors
<< error.errorString() << "("<< error.error() << ")" << "\n";
}
if( _treatSslErrorsAsFailure ) {
// User decided once not to trust. Honor this decision.
bool allPreviouslyRejected = true;
foreach (const QSslError &error, errors) {
if (!_rejectedCertificates.contains(error.certificate())) {
allPreviouslyRejected = false;
}
}
// If all certs have previously been rejected by the user, don't ask again.
if( allPreviouslyRejected ) {
qDebug() << out << "Certs not trusted by user decision, returning.";
return;
}
@@ -424,6 +427,12 @@ void Account::slotHandleSslErrors(QNetworkReply *reply , QList<QSslError> errors
return;
}
// SslDialogErrorHandler::handleErrors will run an event loop that might execute
// the deleteLater() of the QNAM before we have the chance of unwinding our stack.
// Keep a ref here on our stackframe to make sure that it doesn't get deleted before
// handleErrors returns.
QSharedPointer<QNetworkAccessManager> qnamLock = _am;
if (_sslErrorHandler->handleErrors(errors, reply->sslConfiguration(), &approvedCerts, sharedFromThis())) {
QSslSocket::addDefaultCaCertificates(approvedCerts);
addApprovedCerts(approvedCerts);
@@ -436,7 +445,12 @@ void Account::slotHandleSslErrors(QNetworkReply *reply , QList<QSslError> errors
// certificate changes.
reply->ignoreSslErrors(errors);
} else {
_treatSslErrorsAsFailure = true;
// Mark all involved certificates as rejected, so we don't ask the user again.
foreach (const QSslError &error, errors) {
if (!_rejectedCertificates.contains(error.certificate())) {
_rejectedCertificates.append(error.certificate());
}
}
// if during normal operation, a new certificate was MITM'ed, and the user does not
// ACK it, the running request must be aborted and the QNAM must be reset, to not
// treat the new cert as granted. See bug #3283
@@ -448,12 +462,12 @@ void Account::slotHandleSslErrors(QNetworkReply *reply , QList<QSslError> errors
void Account::slotCredentialsFetched()
{
emit credentialsFetched(_credentials);
emit credentialsFetched(_credentials.data());
}
void Account::slotCredentialsAsked()
{
emit credentialsAsked(_credentials);
emit credentialsAsked(_credentials.data());
}
void Account::handleInvalidCredentials()
+7 -4
Ver Arquivo
@@ -133,7 +133,7 @@ public:
// Usually when a user explicitly rejects a certificate we don't
// ask again. After this call, a dialog will again be shown when
// the next unknown certificate is encountered.
void resetSslCertErrorState();
void resetRejectedCertificates();
// pluggable handler
void setSslErrorHandler(AbstractSslErrorHandler *handler);
@@ -214,9 +214,12 @@ private:
QString _serverVersion;
QScopedPointer<AbstractSslErrorHandler> _sslErrorHandler;
QuotaInfo *_quotaInfo;
QNetworkAccessManager *_am;
AbstractCredentials* _credentials;
bool _treatSslErrorsAsFailure;
QSharedPointer<QNetworkAccessManager> _am;
QSharedPointer<AbstractCredentials> _credentials;
/// Certificates that were explicitly rejected by the user
QList<QSslCertificate> _rejectedCertificates;
static QString _configFileName;
QByteArray _pemCertificate;
QString _pemPrivateKey;
+1
Ver Arquivo
@@ -219,6 +219,7 @@ void ConnectionValidator::slotAuthSuccess()
void ConnectionValidator::checkServerCapabilities()
{
JsonApiJob *job = new JsonApiJob(_account, QLatin1String("ocs/v1.php/cloud/capabilities"), this);
job->setTimeout(timeoutToUseMsec);
QObject::connect(job, SIGNAL(jsonReceived(QVariantMap, int)), this, SLOT(slotCapabilitiesRecieved(QVariantMap)));
job->start();
}
+71
Ver Arquivo
@@ -610,6 +610,74 @@ void DiscoveryJob::remote_vio_closedir_hook (csync_vio_handle_t *dhandle, void
}
}
static QString convertToRegexpSyntax(char *exclude)
{
//QString::fromUtf8(exclude);
QString s;
for (unsigned int i = 0; i < strlen(exclude); i++) {
char &c = exclude[i];
if (c == '*') s += ".*";
else if (c == '.') s += "\\.";
else if (c == '$') s += "\\$";
else if (c == '?') s += ".";
else s += c;
// FIXME: [ ] { } ( ) etc
}
qDebug() << s;
return s;
}
CSYNC_EXCLUDE_TYPE DiscoveryJob::excluded_traversal_hook (const char *path, int filetype, void *userdata)
{
DiscoveryJob *discoveryJob = static_cast<DiscoveryJob*>(userdata);
// FIXME: csync_e
// FIXME file match vs directory match?
qDebug() << discoveryJob->_exclude_traversel_regexp_exclude.isValid() << path << discoveryJob->_exclude_traversel_regexp_exclude.errorString();
if (discoveryJob->_exclude_traversel_regexp_exclude.pattern().length() == 0) {
// env QT_ENABLE_REGEXP_JIT 1
discoveryJob->_exclude_traversel_regexp_exclude.setPatternOptions(QRegularExpression::OptimizeOnFirstUsageOption);
discoveryJob->_exclude_traversel_regexp_exclude_and_remove.setPatternOptions(QRegularExpression::OptimizeOnFirstUsageOption);
QString _exclude_traversel_regexp_exclude;
QString _exclude_traversel_regexp_exclude_and_remove;
for (unsigned int i = 0; i < discoveryJob->_csync_ctx->excludes->count; i++) {
char *exclude = discoveryJob->_csync_ctx->excludes->vector[i];
QString *builderToUse = & _exclude_traversel_regexp_exclude;
if (exclude[0] == '\n') continue; // empty line
if (exclude[0] == '\r') continue; // empty line
if (exclude[0] == ']'){
exclude++;
builderToUse = &_exclude_traversel_regexp_exclude_and_remove;
}
if (builderToUse->size() > 0) {
builderToUse->append("|");
}
builderToUse->append(convertToRegexpSyntax(exclude));
}
qDebug() << _exclude_traversel_regexp_exclude;
qDebug() << _exclude_traversel_regexp_exclude_and_remove;
discoveryJob->_exclude_traversel_regexp_exclude.setPattern(_exclude_traversel_regexp_exclude);
discoveryJob->_exclude_traversel_regexp_exclude_and_remove.setPattern(_exclude_traversel_regexp_exclude_and_remove);
}
QString p = QString::fromUtf8(path);
if (discoveryJob->_exclude_traversel_regexp_exclude.match(p).hasMatch()) {
qDebug() << "WOULD EXCLUDE";
return CSYNC_FILE_EXCLUDE_LIST;
}
// FIXME
if (discoveryJob->_exclude_traversel_regexp_exclude_and_remove.match(p).hasMatch()) {
qDebug() << "WOULD EXCLUDE AND REMOVE";
return CSYNC_FILE_EXCLUDE_AND_REMOVE;
}
// FIXME
return CSYNC_NOT_EXCLUDED;
}
void DiscoveryJob::start() {
_selectiveSyncBlackList.sort();
_selectiveSyncWhiteList.sort();
@@ -623,6 +691,9 @@ void DiscoveryJob::start() {
_csync_ctx->callbacks.remote_closedir_hook = remote_vio_closedir_hook;
_csync_ctx->callbacks.vio_userdata = this;
_csync_ctx->callbacks.excluded_traversal_hook = excluded_traversal_hook;
_csync_ctx->callbacks.excluded_traversal_userdata = this;
csync_set_log_callback(_log_callback);
csync_set_log_level(_log_level);
csync_set_log_userdata(_log_userdata);
+5
Ver Arquivo
@@ -23,6 +23,7 @@
#include <QMutex>
#include <QWaitCondition>
#include <QLinkedList>
#include <QRegularExpression>
namespace OCC {
@@ -182,6 +183,10 @@ class DiscoveryJob : public QObject {
QMutex _vioMutex;
QWaitCondition _vioWaitCondition;
QRegularExpression _exclude_traversel_regexp_exclude;
QRegularExpression _exclude_traversel_regexp_exclude_and_remove;
static CSYNC_EXCLUDE_TYPE excluded_traversal_hook (const char *path, int filetype, void *userdata);
public:
explicit DiscoveryJob(CSYNC *ctx, QObject* parent = 0)
+1 -1
Ver Arquivo
@@ -42,7 +42,7 @@ ExcludedFiles& ExcludedFiles::instance()
void ExcludedFiles::addExcludeFilePath(const QString& path)
{
_excludeFiles.append(path);
_excludeFiles.insert(path);
}
bool ExcludedFiles::reloadExcludes()
+3 -2
Ver Arquivo
@@ -16,7 +16,8 @@
#include "owncloudlib.h"
#include <QObject>
#include <QStringList>
#include <QSet>
#include <QString>
extern "C" {
#include "std/c_string.h"
@@ -66,7 +67,7 @@ private:
// This is a pointer to the csync exclude list, its is owned by this class
// but the pointer can be in a csync_context so that it can itself also query the list.
c_strlist_t** _excludesPtr;
QStringList _excludeFiles;
QSet<QString> _excludeFiles;
};
} // namespace OCC
+43 -8
Ver Arquivo
@@ -43,6 +43,7 @@ extern "C" {
#include "csync.h"
#include "vio/csync_vio_local.h"
#include "std/c_path.h"
#include "std/c_string.h"
}
namespace OCC {
@@ -495,16 +496,16 @@ QString FileSystem::fileSystemForPath(const QString & path)
}
#endif
#define BUFSIZE 1024*1024*10
#define BUFSIZE qint64(500*1024) // 500 KiB
static QByteArray readToCrypto( const QString& filename, QCryptographicHash::Algorithm algo )
{
const qint64 bufSize = BUFSIZE;
QByteArray buf(bufSize,0);
QFile file(filename);
const qint64 bufSize = qMin(BUFSIZE, file.size() + 1);
QByteArray buf(bufSize, Qt::Uninitialized);
QByteArray arr;
QCryptographicHash crypto( algo );
QFile file(filename);
if (file.open(QIODevice::ReadOnly)) {
qint64 size;
while (!file.atEnd()) {
@@ -531,11 +532,11 @@ QByteArray FileSystem::calcSha1( const QString& filename )
#ifdef ZLIB_FOUND
QByteArray FileSystem::calcAdler32( const QString& filename )
{
unsigned int adler = adler32(0L, Z_NULL, 0);
const qint64 bufSize = BUFSIZE;
QByteArray buf(bufSize, 0);
QFile file(filename);
const qint64 bufSize = qMin(BUFSIZE, file.size() + 1);
QByteArray buf(bufSize, Qt::Uninitialized);
unsigned int adler = adler32(0L, Z_NULL, 0);
if (file.open(QIODevice::ReadOnly)) {
qint64 size;
while (!file.atEnd()) {
@@ -589,4 +590,38 @@ bool FileSystem::remove(const QString &fileName, QString *errorString)
return true;
}
bool FileSystem::isFileLocked(const QString& fileName)
{
#ifdef Q_OS_WIN
mbchar_t *wuri = c_utf8_path_to_locale(fileName.toUtf8());
// Check if file exists
DWORD attr = GetFileAttributesW(wuri);
if (attr != INVALID_FILE_ATTRIBUTES) {
// Try to open the file with as much access as possible..
HANDLE win_h = CreateFileW(
wuri,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
NULL);
c_free_locale_string(wuri);
if (win_h == INVALID_HANDLE_VALUE) {
/* could not be opened, so locked? */
/* 32 == ERROR_SHARING_VIOLATION */
return true;
} else {
CloseHandle(win_h);
}
} else {
c_free_locale_string(wuri);
}
#else
Q_UNUSED(fileName);
#endif
return false;
}
} // namespace OCC
+8 -3
Ver Arquivo
@@ -111,9 +111,9 @@ bool OWNCLOUDSYNC_EXPORT rename(const QString& originFileName,
*
* @return true if the file's mtime or size are not what is expected.
*/
bool fileChanged(const QString& fileName,
qint64 previousSize,
time_t previousMtime);
bool OWNCLOUDSYNC_EXPORT fileChanged(const QString& fileName,
qint64 previousSize,
time_t previousMtime);
/**
* @brief Like !fileChanged() but with verbose logging if the file *did* change.
@@ -182,6 +182,11 @@ QByteArray OWNCLOUDSYNC_EXPORT calcAdler32( const QString& fileName );
*/
QString OWNCLOUDSYNC_EXPORT makeConflictFileName(const QString &fn, const QDateTime &dt);
/**
* Returns true when a file is locked. (Windows only)
*/
bool OWNCLOUDSYNC_EXPORT isFileLocked(const QString& fileName);
}
/** @} */
+15 -1
Ver Arquivo
@@ -297,7 +297,12 @@ public:
QAtomicInt _abortRequested; // boolean set by the main thread to abort.
/* The list of currently active jobs */
/** The list of currently active jobs.
This list contains the jobs that are currently using ressources and is used purely to
know how many jobs there is currently running for the scheduler.
Jobs add themself to the list when they do an assynchronous operation.
Jobs can be several time on the list (example, when several chunks are uploaded in parallel)
*/
QList<PropagateItemJob*> _activeJobList;
/** We detected that another sync is required after this one */
@@ -369,6 +374,9 @@ signals:
void progress(const SyncFileItem&, quint64 bytes);
void finished();
/** Emitted when propagation has problems with a locked file. */
void seenLockedFile(const QString &fileName);
private:
AccountPtr _account;
@@ -376,6 +384,12 @@ private:
/** Stores the time since a job touched a file. */
QHash<QString, QElapsedTimer> _touchedFiles;
mutable QMutex _touchedFilesMutex;
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
// access to signals which are protected in Qt4
friend class PropagateDownloadFileQNAM;
friend class PropagateUploadFileQNAM;
#endif
};
+56 -10
Ver Arquivo
@@ -127,27 +127,65 @@ void ProgressDispatcher::setProgressInfo(const QString& folder, const ProgressIn
emit progressInfo( folder, progress );
}
void ProgressInfo::start()
ProgressInfo::ProgressInfo()
{
connect(&_updateEstimatesTimer, SIGNAL(timeout()), SLOT(updateEstimates()));
reset();
}
void ProgressInfo::reset()
{
_currentItems.clear();
_currentDiscoveredFolder.clear();
_sizeProgress = Progress();
_fileProgress = Progress();
_totalSizeOfCompletedJobs = 0;
_maxBytesPerSecond = 100000.0;
_maxFilesPerSecond = 2.0;
_updateEstimatesTimer.stop();
}
void ProgressInfo::startEstimateUpdates()
{
_updateEstimatesTimer.start(1000);
}
bool ProgressInfo::hasStarted() const
bool ProgressInfo::isUpdatingEstimates() const
{
return _updateEstimatesTimer.isActive();
}
static bool shouldCountProgress(const SyncFileItem &item)
{
const auto instruction = item._instruction;
// Don't worry about directories that won't have propagation
// jobs associated with them.
if (item._isDirectory
&& (instruction == CSYNC_INSTRUCTION_NONE
|| instruction == CSYNC_INSTRUCTION_SYNC
|| instruction == CSYNC_INSTRUCTION_CONFLICT)) {
return false;
}
// Skip any ignored or error files, we do nothing with them.
if (instruction == CSYNC_INSTRUCTION_IGNORE
|| instruction == CSYNC_INSTRUCTION_ERROR) {
return false;
}
return true;
}
void ProgressInfo::adjustTotalsForFile(const SyncFileItem &item)
{
if (!item._isDirectory) {
_fileProgress._total++;
if (isSizeDependent(item)) {
_sizeProgress._total += item._size;
}
} else if (item._instruction != CSYNC_INSTRUCTION_NONE) {
// Added or removed directories certainly count.
_fileProgress._total++;
if (!shouldCountProgress(item)) {
return;
}
_fileProgress._total += item._affectedItems;
if (isSizeDependent(item)) {
_sizeProgress._total += item._size;
}
}
@@ -178,6 +216,10 @@ quint64 ProgressInfo::completedSize() const
void ProgressInfo::setProgressComplete(const SyncFileItem &item)
{
if (!shouldCountProgress(item)) {
return;
}
_currentItems.remove(item._file);
_fileProgress.setCompleted(_fileProgress._completed + item._affectedItems);
if (ProgressInfo::isSizeDependent(item)) {
@@ -189,6 +231,10 @@ void ProgressInfo::setProgressComplete(const SyncFileItem &item)
void ProgressInfo::setProgressItem(const SyncFileItem &item, quint64 completed)
{
if (!shouldCountProgress(item)) {
return;
}
_currentItems[item._file]._item = item;
_currentItems[item._file]._progress._total = item._size;
_currentItems[item._file]._progress.setCompleted(completed);
+10 -10
Ver Arquivo
@@ -37,27 +37,27 @@ class OWNCLOUDSYNC_EXPORT ProgressInfo : public QObject
{
Q_OBJECT
public:
ProgressInfo()
: _totalSizeOfCompletedJobs(0)
, _maxFilesPerSecond(2.0)
, _maxBytesPerSecond(100000.0)
{}
ProgressInfo();
/** Resets for a new sync run.
*/
void reset();
/**
* Called when propagation starts.
*
* hasStarted() will return true afterwards.
* isUpdatingEstimates() will return true afterwards.
*/
void start();
void startEstimateUpdates();
/**
* Returns true when propagation has started (start() was called).
* Returns true when startEstimateUpdates() was called.
*
* This is used when the SyncEngine wants to indicate a new sync
* is about to start via the transmissionProgress() signal. The
* first ProgressInfo will have hasStarted() == false.
* first ProgressInfo will have isUpdatingEstimates() == false.
*/
bool hasStarted() const;
bool isUpdatingEstimates() const;
/**
* Increase the file and size totals by the amount indicated in item.
+24 -3
Ver Arquivo
@@ -546,6 +546,14 @@ void PropagateDownloadFileQNAM::slotGetFinished()
return;
}
if (_tmpFile.size() == 0 && _item->_size > 0) {
FileSystem::remove(_tmpFile.fileName());
done(SyncFileItem::NormalError,
tr("The downloaded file is empty despite the server announced it should have been %1.")
.arg(Utility::octetsToString(_item->_size)));
return;
}
// Do checksum validation for the download. If there is no checksum header, the validator
// will also emit the validated() signal to continue the flow in slot transmissionChecksumValidated()
// as this is (still) also correct.
@@ -646,7 +654,6 @@ static void preserveGroupOwnership(const QString& fileName, const QFileInfo& fi)
}
} // end namespace
void PropagateDownloadFileQNAM::transmissionChecksumValidated(const QByteArray &checksumType, const QByteArray &checksum)
{
const auto theContentChecksumType = contentChecksumType();
@@ -696,7 +703,14 @@ void PropagateDownloadFileQNAM::downloadFinished()
QString renameError;
QString conflictFileName = FileSystem::makeConflictFileName(fn, Utility::qDateTimeFromTime_t(_item->_modtime));
if (!FileSystem::rename(fn, conflictFileName, &renameError)) {
//If the rename fails, don't replace it.
// If the rename fails, don't replace it.
// If the file is locked, we want to retry this sync when it
// becomes available again.
if (FileSystem::isFileLocked(fn)) {
emit _propagator->seenLockedFile(fn);
}
done(SyncFileItem::SoftError, renameError);
return;
}
@@ -756,7 +770,14 @@ void PropagateDownloadFileQNAM::downloadFinished()
_propagator->_journal->commit("download finished");
}
_propagator->_anotherSyncNeeded = true;
// If the file is locked, we want to retry this sync when it
// becomes available again, otherwise try again directly
if (FileSystem::isFileLocked(fn)) {
emit _propagator->seenLockedFile(fn);
} else {
_propagator->_anotherSyncNeeded = true;
}
done(SyncFileItem::SoftError, error);
return;
}
+23 -5
Ver Arquivo
@@ -97,7 +97,9 @@ void PUTFileJob::start() {
}
void PUTFileJob::slotTimeout() {
qDebug() << "Timeout" << reply()->request().url();
qDebug() << "Timeout" << (reply() ? reply()->request().url() : path());
if (!reply())
return;
_errorString = tr("Connection Timeout");
reply()->abort();
}
@@ -209,8 +211,6 @@ void PropagateUploadFileQNAM::slotComputeContentChecksum()
return;
}
_propagator->_activeJobList.removeOne(this);
const QString filePath = _propagator->getFilePath(_item->_file);
// remember the modtime before checksumming to be able to detect a file
@@ -234,6 +234,8 @@ void PropagateUploadFileQNAM::slotComputeContentChecksum()
connect(computeChecksum, SIGNAL(done(QByteArray,QByteArray)),
SLOT(slotComputeTransmissionChecksum(QByteArray,QByteArray)));
connect(computeChecksum, SIGNAL(done(QByteArray,QByteArray)),
computeChecksum, SLOT(deleteLater()));
computeChecksum->start(filePath);
}
@@ -268,12 +270,18 @@ void PropagateUploadFileQNAM::slotComputeTransmissionChecksum(const QByteArray&
connect(computeChecksum, SIGNAL(done(QByteArray,QByteArray)),
SLOT(slotStartUpload(QByteArray,QByteArray)));
connect(computeChecksum, SIGNAL(done(QByteArray,QByteArray)),
computeChecksum, SLOT(deleteLater()));
const QString filePath = _propagator->getFilePath(_item->_file);
computeChecksum->start(filePath);
}
void PropagateUploadFileQNAM::slotStartUpload(const QByteArray& transmissionChecksumType, const QByteArray& transmissionChecksum)
{
// Remove ourselfs from the list of active job, before any posible call to done()
// When we start chunks, we will add it again, once for every chunks.
_propagator->_activeJobList.removeOne(this);
_transmissionChecksum = transmissionChecksum;
_transmissionChecksumType = transmissionChecksumType;
@@ -398,7 +406,7 @@ qint64 UploadDevice::readData(char* data, qint64 maxlen) {
if (isBandwidthLimited()) {
maxlen = qMin(maxlen, _bandwidthQuota);
if (maxlen <= 0) { // no quota
qDebug() << "no quota";
//qDebug() << "no quota";
return 0;
}
_bandwidthQuota -= maxlen;
@@ -544,8 +552,16 @@ void PropagateUploadFileQNAM::startNextChunk()
_transmissionChecksumType, _transmissionChecksum);
}
if (! device->prepareAndOpen(_propagator->getFilePath(_item->_file), chunkStart, currentChunkSize)) {
const QString fileName = _propagator->getFilePath(_item->_file);
if (! device->prepareAndOpen(fileName, chunkStart, currentChunkSize)) {
qDebug() << "ERR: Could not prepare upload device: " << device->errorString();
// If the file is currently locked, we want to retry the sync
// when it becomes available again.
if (FileSystem::isFileLocked(fileName)) {
emit _propagator->seenLockedFile(fileName);
}
// Soft error because this is likely caused by the user modifying his files while syncing
abortWithError( SyncFileItem::SoftError, device->errorString() );
delete device;
@@ -763,6 +779,8 @@ void PropagateUploadFileQNAM::slotPutFinished()
<< _stopWatch.durationOfLap(QLatin1String("ContentChecksum"))
<< _stopWatch.durationOfLap(QLatin1String("TransmissionChecksum"))
<< _item->_requestDuration;
// The job might stay alive for the whole sync, release this tiny bit of memory.
_stopWatch.reset();
finalize(*_item);
}
+26 -11
Ver Arquivo
@@ -101,10 +101,10 @@ SyncEngine::SyncEngine(AccountPtr account, const QString& localPath,
SyncEngine::~SyncEngine()
{
abort();
_excludedFiles.reset();
csync_destroy(_csync_ctx);
_thread.quit();
_thread.wait();
_excludedFiles.reset();
csync_destroy(_csync_ctx);
}
//Convert an error code from csync to a user readable string.
@@ -203,6 +203,12 @@ QString SyncEngine::csyncErrorToString(CSYNC_STATUS err)
}
/**
* Check if the item is in the blacklist.
* If it should not be sync'ed because of the blacklist, update the item with the error instruction
* and proper error message, and return true.
* If the item is not in the blacklist, or the blacklist is stale, return false.
*/
bool SyncEngine::checkErrorBlacklisting( SyncFileItem &item )
{
if( !_journal ) {
@@ -234,6 +240,9 @@ bool SyncEngine::checkErrorBlacklisting( SyncFileItem &item )
} else if( item._modtime != entry._lastTryModtime ) {
qDebug() << item._file << " is blacklisted, but has changed mtime!";
return false;
} else if( item._renameTarget != entry._renameTarget) {
qDebug() << item._file << " is blacklisted, but rename target changed from" << entry._renameTarget;
return false;
}
} else if( item._direction == SyncFileItem::Down ) {
// download, check the etag.
@@ -539,10 +548,10 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
bool directoryEtagUpdate = isDirectory && file->should_update_metadata;
bool localMetadataUpdate = !remote && file->should_update_metadata;
if (!directoryEtagUpdate) {
item->_isDirectory = isDirectory;
if (localMetadataUpdate) {
// Hack, we want a local metadata update to happen, but only if the
// remote tree doesn't ask us to do some kind of propagation.
item->_isDirectory = isDirectory;
_syncItemMap.insert(key, item);
}
emit syncItemDiscovered(*item);
@@ -571,7 +580,7 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
// An upload of an existing file means that the file was left unchanged on the server
// This counts as a NONE for detecting if all the files on the server were changed
_hasNoneFiles = true;
} else if (!item->_isDirectory) {
} else if (!isDirectory) {
if (std::difftime(file->modtime, file->other.modtime) < 0) {
// We are going back on time
_backInTimeFiles++;
@@ -673,6 +682,8 @@ void SyncEngine::startSync()
_syncRunning = true;
_anotherSyncNeeded = false;
_progressInfo->reset();
if (!QDir(_localPath).exists()) {
// No _tr, it should only occur in non-mirall
emit csyncError("Unable to find local sync folder.");
@@ -909,7 +920,7 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult)
emit aboutToPropagate(_syncedItems);
// it's important to do this before ProgressInfo::start(), to announce start of new sync
emit transmissionProgress(*_progressInfo);
_progressInfo->start();
_progressInfo->startEstimateUpdates();
// post update phase script: allow to tweak stuff by a custom script in debug mode.
if( !qgetenv("OWNCLOUD_POST_UPDATE_SCRIPT").isEmpty() ) {
@@ -933,6 +944,7 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult)
connect(_propagator.data(), SIGNAL(progress(const SyncFileItem &,quint64)),
this, SLOT(slotProgress(const SyncFileItem &,quint64)));
connect(_propagator.data(), SIGNAL(finished()), this, SLOT(slotFinished()), Qt::QueuedConnection);
connect(_propagator.data(), SIGNAL(seenLockedFile(QString)), SIGNAL(seenLockedFile(QString)));
// apply the network limits to the propagator
setNetworkLimits(_uploadLimit, _downloadLimit);
@@ -1243,15 +1255,18 @@ void SyncEngine::checkForPermission()
}
}
#if 0 /* We don't like the idea of renaming behind user's back, as the user may be working with the files */
if (!sourceOK && !destinationOK) {
#ifdef OWNCLOUD_RESTORE_RENAME /* We don't like the idea of renaming behind user's back, as the user may be working with the files */
if (!sourceOK && (!destinationOK || isRename)
// (not for directory because that's more complicated with the contents that needs to be adjusted)
&& !(*it)->_isDirectory) {
// Both the source and the destination won't allow move. Move back to the original
std::swap((*it)->_file, (*it)->_renameTarget);
(*it)->_direction = SyncFileItem::Down;
(*it)->_errorString = tr("Move not allowed, item restored");
(*it)->_isRestoration = true;
qDebug() << "checkForPermission: MOVING BACK" << (*it)->_file;
// in case something does wrong, we will not do it next time
_journal->avoidRenamesOnNextSync((*it)->_file);
} else
#endif
if (!sourceOK || !destinationOK) {
@@ -1341,7 +1356,7 @@ SyncFileItem* SyncEngine::findSyncItem(const QString &fileName) const
{
Q_FOREACH(const SyncFileItemPtr &item, _syncedItems) {
// Directories will appear in this list as well, and will get their status set once all children have been propagated
if ((item->_file == fileName || item->_renameTarget == fileName))
if ((item->_file == fileName || (!item->_renameTarget.isEmpty() && item->_renameTarget == fileName)))
return item.data();
}
return 0;
@@ -1364,13 +1379,13 @@ AccountPtr SyncEngine::account() const
void SyncEngine::abort()
{
// Sets a flag for the update phase
csync_request_abort(_csync_ctx);
qDebug() << Q_FUNC_INFO << _discoveryMainThread;
// Aborts the discovery phase job
if (_discoveryMainThread) {
_discoveryMainThread->abort();
}
// Sets a flag for the update phase
csync_request_abort(_csync_ctx);
// For the propagator
if(_propagator) {
_propagator->abort();
+6
Ver Arquivo
@@ -143,6 +143,12 @@ signals:
// A new folder was discovered and was not synced because of the confirmation feature
void newBigFolder(const QString &folder);
/** Emitted when propagation has problems with a locked file.
*
* Forwarded from OwncloudPropagator::seenLockedFile.
*/
void seenLockedFile(const QString &fileName);
private slots:
void slotRootEtagReceived(const QString &);
void slotItemCompleted(const SyncFileItem& item, const PropagatorJob & job);
+76 -82
Ver Arquivo
@@ -28,14 +28,15 @@ static SyncFileStatus::SyncFileStatusTag lookupProblem(const QString &pathToMatc
// qDebug() << Q_FUNC_INFO << pathToMatch << severity << problemPath;
if (problemPath == pathToMatch) {
return severity;
} else if (severity == SyncFileStatus::StatusError && problemPath.startsWith(pathToMatch) && problemPath.at(pathToMatch.size()) == '/') {
Q_ASSERT(!pathToMatch.endsWith('/'));
} else if (severity == SyncFileStatus::StatusError
&& problemPath.startsWith(pathToMatch)
&& (pathToMatch.isEmpty() || problemPath.at(pathToMatch.size()) == '/')) {
return SyncFileStatus::StatusWarning;
} else if (!problemPath.startsWith(pathToMatch)) {
// Starting at lower_bound we get the first path that is not smaller,
// since: "/a/" < "/a/aa" < "/a/aa/aaa" < "/a/ab/aba"
// If problemMap keys are ["/a/aa/aaa", "/a/ab/aba"] and pathToMatch == "/a/aa",
// lower_bound(pathToMatch) will point to "/a/aa/aaa", and the moment that
// since: "a/" < "a/aa" < "a/aa/aaa" < "a/ab/aba"
// If problemMap keys are ["a/aa/aaa", "a/ab/aba"] and pathToMatch == "a/aa",
// lower_bound(pathToMatch) will point to "a/aa/aaa", and the moment that
// problemPath.startsWith(pathToMatch) == false, we know that we've looked
// at everything that interest us.
break;
@@ -68,95 +69,79 @@ static inline bool showWarningInSocketApi(const SyncFileItem& item)
|| status == SyncFileItem::Restoration;
}
static inline bool showSyncInSocketApi( const SyncFileItem& item)
{
const auto inst = item._instruction;
return inst == CSYNC_INSTRUCTION_NEW;
}
SyncFileStatusTracker::SyncFileStatusTracker(SyncEngine *syncEngine)
: _syncEngine(syncEngine)
{
connect(syncEngine, SIGNAL(aboutToPropagate(SyncFileItemVector&)),
this, SLOT(slotAboutToPropagate(SyncFileItemVector&)));
SLOT(slotAboutToPropagate(SyncFileItemVector&)));
connect(syncEngine, SIGNAL(itemCompleted(const SyncFileItem&, const PropagatorJob&)),
this, SLOT(slotItemCompleted(const SyncFileItem&)));
SLOT(slotItemCompleted(const SyncFileItem&)));
connect(syncEngine, SIGNAL(started()), SLOT(slotSyncEngineRunningChanged()));
connect(syncEngine, SIGNAL(finished(bool)), SLOT(slotSyncEngineRunningChanged()));
}
SyncFileStatus SyncFileStatusTracker::rootStatus()
SyncFileItem SyncFileStatusTracker::rootSyncFileItem()
{
/* Possible values for the status:
enum SyncFileStatusTag {
StatusNone,
StatusSync,
StatusWarning,
StatusUpToDate,
StatusError,
};
*/
SyncFileStatus status = SyncFileStatus::StatusUpToDate;
if( !_syncEngine ) return SyncFileStatus::StatusNone;
if( _syncEngine->isSyncRunning() ) {
status = SyncFileStatus::StatusSync;
} else {
// sync is not running. Check dirty list and _syncProblems
int errs = 0;
for (auto it = _syncProblems.begin(); it != _syncProblems.end(); ++it) {
if( it->second == SyncFileStatus::StatusError ) {
errs ++;
break; // stop if an error found at all.
}
}
if( errs ) {
status = SyncFileStatus::StatusWarning; // some files underneath had errors
}
// Only warnings do not change the root emblem away from ok.
}
return status;
SyncFileItem fakeRootItem;
// It's is not entirely correct to use the sync's status as we'll show the root folder as
// syncing even though no child might end up being propagated, but will give us something
// better than always UpToDate for now.
fakeRootItem._status = _syncEngine->isSyncRunning() ? SyncFileItem::NoStatus : SyncFileItem::Success;
fakeRootItem._isDirectory = true;
return fakeRootItem;
}
SyncFileStatus SyncFileStatusTracker::fileStatus(const QString& systemFileName)
SyncFileStatus SyncFileStatusTracker::fileStatus(const QString& relativePath)
{
QString fileName = systemFileName.normalized(QString::NormalizationForm_C);
if( fileName.endsWith(QLatin1Char('/')) ) {
fileName.truncate(fileName.length()-1);
qDebug() << "Removed trailing slash: " << fileName;
// normalization is required for OS X to match file names properly
QString normalizedRelativePath = relativePath.normalized(QString::NormalizationForm_C);
Q_ASSERT(!normalizedRelativePath.endsWith(QLatin1Char('/')));
if (normalizedRelativePath.isEmpty()) {
// This is the root sync folder, it doesn't have an entry in the database and won't be walked by csync, so create one manually.
return syncFileItemStatus(rootSyncFileItem());
}
if( fileName.isEmpty() ) {
// this is the root sync folder.
return rootStatus();
}
// The SyncEngine won't notify us at all for CSYNC_FILE_SILENTLY_EXCLUDED
// and CSYNC_FILE_EXCLUDE_AND_REMOVE excludes. Even though it's possible
// that the status of CSYNC_FILE_EXCLUDE_LIST excludes will change if the user
// update the exclude list at runtime and doing it statically here removes
// our ability to notify changes through the fileStatusChanged signal,
// it's an acceptable compromize to treat all exclude types the same.
if( _syncEngine->excludedFiles().isExcluded(_syncEngine->localPath() + fileName,
if( _syncEngine->excludedFiles().isExcluded(_syncEngine->localPath() + normalizedRelativePath,
_syncEngine->localPath(),
_syncEngine->ignoreHiddenFiles()) ) {
return SyncFileStatus(SyncFileStatus::StatusWarning);
}
SyncFileItem* item = _syncEngine->findSyncItem(fileName);
if ( _dirtyPaths.contains(normalizedRelativePath) )
return SyncFileStatus::StatusSync;
SyncFileItem* item = _syncEngine->findSyncItem(normalizedRelativePath);
if (item) {
return fileStatus(*item);
return syncFileItemStatus(*item);
}
// If we're not currently syncing that file, look it up in the database to know if it's shared
SyncJournalFileRecord rec = _syncEngine->journal()->getFileRecord(fileName);
SyncJournalFileRecord rec = _syncEngine->journal()->getFileRecord(normalizedRelativePath);
if (rec.isValid()) {
return fileStatus(rec.toSyncFileItem());
return syncFileItemStatus(rec.toSyncFileItem());
}
// Must be a new file, wait for the filesystem watcher to trigger a sync
return SyncFileStatus();
}
void SyncFileStatusTracker::slotPathTouched(const QString& fileName)
{
QString folderPath = _syncEngine->localPath();
Q_ASSERT(fileName.startsWith(folderPath));
QString localPath = fileName.mid(folderPath.size());
_dirtyPaths.insert(localPath);
emit fileStatusChanged(fileName, SyncFileStatus::StatusSync);
}
void SyncFileStatusTracker::slotAboutToPropagate(SyncFileItemVector& items)
{
std::map<QString, SyncFileStatus::SyncFileStatusTag> oldProblems;
@@ -169,12 +154,19 @@ void SyncFileStatusTracker::slotAboutToPropagate(SyncFileItemVector& items)
_syncProblems[item->_file] = SyncFileStatus::StatusError;
} else if (showWarningInSocketApi(*item)) {
_syncProblems[item->_file] = SyncFileStatus::StatusWarning;
} else if( showSyncInSocketApi(*item)) {
_syncProblems[item->_file] = SyncFileStatus::StatusSync;
}
emit fileStatusChanged(getSystemDestination(*item), fileStatus(*item));
_dirtyPaths.remove(item->destination());
emit fileStatusChanged(getSystemDestination(item->destination()), syncFileItemStatus(*item));
}
// Some metadata status won't trigger files to be synced, make sure that we
// push the OK status for dirty files that don't need to be propagated.
// Swap into a copy since fileStatus() reads _dirtyPaths to determine the status
QSet<QString> oldDirtyPaths;
std::swap(_dirtyPaths, oldDirtyPaths);
for (auto it = oldDirtyPaths.begin(); it != oldDirtyPaths.end(); ++it)
emit fileStatusChanged(getSystemDestination(*it), fileStatus(*it));
// Make sure to push any status that might have been resolved indirectly since the last sync
// (like an error file being deleted from disk)
for (auto it = _syncProblems.begin(); it != _syncProblems.end(); ++it)
@@ -184,7 +176,7 @@ void SyncFileStatusTracker::slotAboutToPropagate(SyncFileItemVector& items)
SyncFileStatus::SyncFileStatusTag severity = it->second;
if (severity == SyncFileStatus::StatusError)
invalidateParentPaths(path);
emit fileStatusChanged(_syncEngine->localPath() + path, fileStatus(path));
emit fileStatusChanged(getSystemDestination(path), fileStatus(path));
}
}
@@ -197,22 +189,25 @@ void SyncFileStatusTracker::slotItemCompleted(const SyncFileItem &item)
invalidateParentPaths(item.destination());
} else if (showWarningInSocketApi(item)) {
_syncProblems[item._file] = SyncFileStatus::StatusWarning;
} else if (showSyncInSocketApi(item)) {
// new items that were in state sync can now be erased
_syncProblems.erase(item._file);
} else {
// There is currently no situation where an error status set during discovery/update is fixed by propagation.
Q_ASSERT(_syncProblems.find(item._file) == _syncProblems.end());
_syncProblems.erase(item._file);
}
emit fileStatusChanged(getSystemDestination(item), fileStatus(item));
emit fileStatusChanged(getSystemDestination(item.destination()), syncFileItemStatus(item));
}
SyncFileStatus SyncFileStatusTracker::fileStatus(const SyncFileItem& item)
void SyncFileStatusTracker::slotSyncEngineRunningChanged()
{
emit fileStatusChanged(_syncEngine->localPath(), syncFileItemStatus(rootSyncFileItem()));
}
SyncFileStatus SyncFileStatusTracker::syncFileItemStatus(const SyncFileItem& item)
{
// Hack to know if the item was taken from the sync engine (Sync), or from the database (UpToDate)
bool waitingForPropagation = item._direction != SyncFileItem::None && item._status == SyncFileItem::NoStatus;
// Mark any directory in the SyncEngine's items as syncing, this is currently how we mark parent directories
// of currently syncing items since the PropagateDirectory job will mark the directorie's SyncFileItem::_status as Success
// once all child jobs have been completed.
bool waitingForPropagation = (item._isDirectory || item._direction != SyncFileItem::None) && item._status == SyncFileItem::NoStatus;
SyncFileStatus status(SyncFileStatus::StatusUpToDate);
if (waitingForPropagation) {
status.set(SyncFileStatus::StatusSync);
@@ -239,20 +234,19 @@ void SyncFileStatusTracker::invalidateParentPaths(const QString& path)
QStringList splitPath = path.split('/', QString::SkipEmptyParts);
for (int i = 0; i < splitPath.size(); ++i) {
QString parentPath = QStringList(splitPath.mid(0, i)).join(QLatin1String("/"));
emit fileStatusChanged(_syncEngine->localPath() + parentPath, fileStatus(parentPath));
emit fileStatusChanged(getSystemDestination(parentPath), fileStatus(parentPath));
}
}
QString SyncFileStatusTracker::getSystemDestination(const SyncFileItem& item)
QString SyncFileStatusTracker::getSystemDestination(const QString& relativePath)
{
QString systemFileName = _syncEngine->localPath() + item.destination();
// the trailing slash for directories must be appended as the filenames coming in
// from the plugins have that too. Otherwise the matching entry item is not found
// in the plugin.
if( item._type == SyncFileItem::Type::Directory ) {
systemFileName += QLatin1Char('/');
QString systemPath = _syncEngine->localPath() + relativePath;
// SyncEngine::localPath() has a trailing slash, make sure to remove it if the
// destination is empty.
if( systemPath.endsWith(QLatin1Char('/')) ) {
systemPath.truncate(systemPath.length()-1);
}
return systemFileName;
return systemPath;
}
}
+10 -4
Ver Arquivo
@@ -19,6 +19,7 @@
#include "syncfileitem.h"
#include "syncfilestatus.h"
#include <map>
#include <QSet>
namespace OCC {
@@ -34,7 +35,10 @@ class OWNCLOUDSYNC_EXPORT SyncFileStatusTracker : public QObject
Q_OBJECT
public:
explicit SyncFileStatusTracker(SyncEngine* syncEngine);
SyncFileStatus fileStatus(const QString& systemFileName);
SyncFileStatus fileStatus(const QString& relativePath);
public slots:
void slotPathTouched(const QString& fileName);
signals:
void fileStatusChanged(const QString& systemFileName, SyncFileStatus fileStatus);
@@ -42,17 +46,19 @@ signals:
private slots:
void slotAboutToPropagate(SyncFileItemVector& items);
void slotItemCompleted(const SyncFileItem& item);
void slotSyncEngineRunningChanged();
private:
SyncFileStatus fileStatus(const SyncFileItem& item);
SyncFileStatus rootStatus();
SyncFileStatus syncFileItemStatus(const SyncFileItem& item);
SyncFileItem rootSyncFileItem();
void invalidateParentPaths(const QString& path);
QString getSystemDestination(const SyncFileItem& syncEnginePath);
QString getSystemDestination(const QString& relativePath);
SyncEngine* _syncEngine;
std::map<QString, SyncFileStatus::SyncFileStatusTag> _syncProblems;
QSet<QString> _dirtyPaths;
};
}
+15 -4
Ver Arquivo
@@ -409,7 +409,7 @@ bool SyncJournalDb::checkConnect()
_deleteFileRecordRecursively.reset(new SqlQuery(_db));
_deleteFileRecordRecursively->prepare("DELETE FROM metadata WHERE path LIKE(?||'/%')");
QString sql( "SELECT lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration "
QString sql( "SELECT lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration, renameTarget "
"FROM blacklist WHERE path=?1");
if( Utility::fsCasePreserving() ) {
// if the file system is case preserving we have to check the blacklist
@@ -421,8 +421,8 @@ bool SyncJournalDb::checkConnect()
_setErrorBlacklistQuery.reset(new SqlQuery(_db));
_setErrorBlacklistQuery->prepare("INSERT OR REPLACE INTO blacklist "
"(path, lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration) "
"VALUES ( ?1, ?2, ?3, ?4, ?5, ?6, ?7)");
"(path, lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration, renameTarget) "
"VALUES ( ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)");
_getSelectiveSyncListQuery.reset(new SqlQuery(_db));
_getSelectiveSyncListQuery->prepare("SELECT path FROM selectivesync WHERE type=?1");
@@ -612,6 +612,15 @@ bool SyncJournalDb::updateErrorBlacklistTableStructure()
}
commitInternal("update database structure: add lastTryTime, ignoreDuration cols");
}
if( columns.indexOf(QLatin1String("renameTarget")) == -1 ) {
SqlQuery query(_db);
query.prepare("ALTER TABLE blacklist ADD COLUMN renameTarget VARCHAR(4096);");
if( !query.exec() ) {
sqlFail("updateBlacklistTableStructure: Add renameTarget", query);
re = false;
}
commitInternal("update database structure: add lastTryTime, ignoreDuration cols");
}
SqlQuery query(_db);
query.prepare("CREATE INDEX IF NOT EXISTS blacklist_index ON blacklist(path collate nocase);");
@@ -1224,6 +1233,7 @@ SyncJournalErrorBlacklistRecord SyncJournalDb::errorBlacklistEntry( const QStrin
entry._errorString = _getErrorBlacklistQuery->stringValue(3);
entry._lastTryTime = _getErrorBlacklistQuery->int64Value(4);
entry._ignoreDuration = _getErrorBlacklistQuery->int64Value(5);
entry._renameTarget = _getErrorBlacklistQuery->stringValue(6);
entry._file = file;
}
_getErrorBlacklistQuery->reset_and_clear_bindings();
@@ -1335,13 +1345,14 @@ void SyncJournalDb::updateErrorBlacklistEntry( const SyncJournalErrorBlacklistRe
_setErrorBlacklistQuery->bindValue(5, item._errorString);
_setErrorBlacklistQuery->bindValue(6, QString::number(item._lastTryTime));
_setErrorBlacklistQuery->bindValue(7, QString::number(item._ignoreDuration));
_setErrorBlacklistQuery->bindValue(8, item._renameTarget);
if( !_setErrorBlacklistQuery->exec() ) {
QString bug = _setErrorBlacklistQuery->error();
qDebug() << "SQL exec blacklistitem insert or replace failed: "<< bug;
}
qDebug() << "set blacklist entry for " << item._file << item._retryCount
<< item._errorString << item._lastTryTime << item._ignoreDuration
<< item._lastTryModtime << item._lastTryEtag;
<< item._lastTryModtime << item._lastTryEtag << item._renameTarget ;
_setErrorBlacklistQuery->reset_and_clear_bindings();
}
+1
Ver Arquivo
@@ -151,6 +151,7 @@ SyncJournalErrorBlacklistRecord SyncJournalErrorBlacklistRecord::update(
// The factor of 5 feels natural: 25s, 2 min, 10 min, ~1h, ~5h, ~24h
entry._ignoreDuration = old._ignoreDuration * 5;
entry._file = item._file;
entry._renameTarget = item._renameTarget;
if( item._httpErrorCode == 403 ) {
qDebug() << "Probably firewall error: " << item._httpErrorCode << ", blacklisting up to 1h only";
+1
Ver Arquivo
@@ -89,6 +89,7 @@ public:
time_t _ignoreDuration;
QString _file;
QString _renameTarget;
bool isValid() const;
+12 -7
Ver Arquivo
@@ -306,17 +306,22 @@ namespace {
QString description(quint64 value) const
{
return QCoreApplication::translate(
"Utiliy", name, 0, QCoreApplication::UnicodeUTF8,
"Utility", name, 0, QCoreApplication::UnicodeUTF8,
value);
}
};
// QTBUG-3945 and issue #4855: QT_TRANSLATE_NOOP does not work with plural form because lupdate
// limitation unless we fake more arguments
// (it must be in the form ("context", "source", "comment", n)
#undef QT_TRANSLATE_NOOP
#define QT_TRANSLATE_NOOP(ctx, str, ...) str
Q_DECL_CONSTEXPR Period periods[] = {
{ QT_TRANSLATE_NOOP("Utility", "%Ln year(s)") , 365*24*3600*1000LL },
{ QT_TRANSLATE_NOOP("Utility", "%Ln month(s)") , 30*24*3600*1000LL },
{ QT_TRANSLATE_NOOP("Utility", "%Ln day(s)") , 24*3600*1000LL },
{ QT_TRANSLATE_NOOP("Utility", "%Ln hour(s)") , 3600*1000LL },
{ QT_TRANSLATE_NOOP("Utility", "%Ln minute(s)") , 60*1000LL },
{ QT_TRANSLATE_NOOP("Utility", "%Ln second(s)") , 1000LL },
{ QT_TRANSLATE_NOOP("Utility", "%n year(s)" , 0, _) , 365*24*3600*1000LL },
{ QT_TRANSLATE_NOOP("Utility", "%n month(s)", 0, _) , 30*24*3600*1000LL },
{ QT_TRANSLATE_NOOP("Utility", "%n day(s)", 0, _) , 24*3600*1000LL },
{ QT_TRANSLATE_NOOP("Utility", "%n hour(s)", 0, _) , 3600*1000LL },
{ QT_TRANSLATE_NOOP("Utility", "%n minute(s)", 0, _) , 60*1000LL },
{ QT_TRANSLATE_NOOP("Utility", "%n second(s)", 0, _ ), 1000LL },
{ 0, 0 }
};
} // anonymous namespace

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