Comparar commits

...

134 Commits

Autor SHA1 Mensagem Data
Olivier Goffart 172689d35c Merge remote-tracking branch 'origin/2.3' 2017-02-14 15:08:10 +01:00
Jocelyn Turcotte 60a4a742a3 Disable tests uncompatible with Qt4 for that build 2017-02-14 14:32:41 +01:00
Jocelyn Turcotte b26db062d2 Fix the UNIT_TESTING build on Windows
- Put all tests in the bin directory so that DLLs can be loaded
- Add missing exports
- Skip tests that use code depending on zlib
- The "GMT" timezone is named differently, use the int constructor instead

5 tests are still failing, it's not really worth fixing at the moment
since no developper is currently using Windows as its main platform.
2017-02-14 14:32:41 +01:00
Jocelyn Turcotte 611f633ba8 Fix FolderManTest on macOS
On macOS /var is a symlink to /private/var and we have to make sure that we
use the canonical path before and after it enters the code to make sure we
compare paths correctly.
2017-02-14 14:32:41 +01:00
Jocelyn Turcotte 3265948458 Fix ExcludedFilesTest on macOS
Use the same logic to find sync-exclude as check_csync_exclude.c
2017-02-14 14:32:41 +01:00
Jocelyn Turcotte 0e3e9d5991 Fix FileSystemTest on macOS 2017-02-14 14:32:41 +01:00
Jocelyn Turcotte 0be6cd3bf7 Fix FolderWatcherTest on macOS and Windows
- We need to use a QGuiApplication on macOS or else we don't get notifications
- Switch to use QSignalSpy rather than lists and sleeps
- Use system() for all modifications since we pass kFSEventStreamCreateFlagIgnoreSelf
- Keep using the local process on Windows since it catches its own events
2017-02-14 14:32:41 +01:00
Jocelyn Turcotte 867b78052d Fix UtilityTest on macOS 2017-02-14 14:32:41 +01:00
Olivier Goffart 058f7df635 Folder: remove unused variable 2017-02-14 10:10:07 +01:00
Jenkins for ownCloud c1552d7984 [tx-robot] updated from transifex 2017-02-14 02:18:27 +01:00
Markus Goetz 575b981542 Modify Jenkinsfile for 2.3 2017-02-13 14:47:51 +01:00
Jenkins for ownCloud 0d0af95956 [tx-robot] updated from transifex 2017-02-13 02:18:28 +01:00
Jenkins for ownCloud 6c5d873647 [tx-robot] updated from transifex 2017-02-12 02:18:28 +01:00
Jenkins for ownCloud 71187e1744 [tx-robot] updated from transifex 2017-02-11 02:18:34 +01:00
Christian Kamm 006ce854a6 Doc: For conflicts, the local file is renamed #5521 2017-02-10 12:50:35 +01:00
Jenkins for ownCloud 697178bab6 [tx-robot] updated from transifex 2017-02-10 02:18:29 +01:00
Jenkins for ownCloud d8a86da377 [tx-robot] updated from transifex 2017-02-09 02:18:33 +01:00
Jocelyn Turcotte d1dace9e7f Remove unneeded Q_DECLARE_METATYPE 2017-02-08 17:57:20 +01:00
Jocelyn Turcotte 1cec2ca13d Fix TestSyncEngine::abortAfterFailedMkdir
It could be possible that _firstJob is marked as finished if
aborted before its parent PropagateDirectory was marked as finished,
allowing a posted scheduleNextJob call to schedule the child job
in-between.
2017-02-08 17:32:04 +01:00
Jocelyn Turcotte 1d9e08d109 Skip TestSyncEngine::abortAfterFailedMkdir 2017-02-08 17:25:32 +01:00
ckamm 7879c470b3 Merge pull request #5518 from ckamm/asserts
Improve usage of asserts
2017-02-08 15:25:02 +01:00
Christian Kamm 3c7545a45f CMake: Don't force-enable asserts #5429
Should be safer now that we've gone through asserts and assured that
one ones that should be fatal continue to exist in release builds
independently of QT_NO_DEBUG.
2017-02-08 15:15:19 +01:00
Christian Kamm 4c1fdf1dee Double check usage of asserts #5429
A few are supposed to be fatal.
2017-02-08 15:15:19 +01:00
Christian Kamm 18e25122db Performance: reserve() _remotePerm #5496 2017-02-08 15:06:09 +01:00
Olivier Goffart 439e688906 Folder: Change the wording for the massive deletion message
Issue #5503
2017-02-08 14:30:14 +01:00
ckamm 4198d9f420 Settings: Don't migrate settings on access error #5499 (#5523)
Previously, we'd try migrating from legacy settings if reading
the settings failed with an error. Now, we try again after a
couple of seconds and eventually give up.
2017-02-08 14:28:50 +01:00
Olivier Goffart 06579a5c70 AccountManager: Fix small leak in the account migration code
The QSettings object was not deleted in every possible code paths
2017-02-08 12:31:07 +01:00
Markus Goetz df773ea8bb CentOS: More build fixes 2017-02-08 11:39:28 +01:00
Markus Goetz e7be4faac8 CentOS: Another attempt 2017-02-08 11:15:23 +01:00
Jenkins for ownCloud a184c6bec1 [tx-robot] updated from transifex 2017-02-08 02:18:27 +01:00
Markus Goetz 1102ac20ac Improve previous fix
After comment on https://github.com/owncloud/client/commit/78a798eef3eb8d04360c6d9542db55469f59cacd
2017-02-07 19:40:32 +01:00
Markus Goetz 6a4ae63f14 CentOS: Another fix for old compiler version (2) 2017-02-07 19:22:04 +01:00
Markus Goetz 6c6961e4d9 ChangeLog for 2.3 additions 2017-02-07 19:04:00 +01:00
Markus Goetz 78a798eef3 Old Qt: Another build fix 2017-02-07 18:54:40 +01:00
Markus Goetz 19dd656989 CentOS: Another fix for old compiler version 2017-02-07 18:32:34 +01:00
Markus Goetz d9fac50e9b CentOS: Fix build for old compiler version 2017-02-07 18:05:29 +01:00
Markus Goetz 9614a94035 Revert "Disable RTTI"
This reverts commit 85d3de1589.
This breaks our old Qt on CentOS.

We can re-introduce this with #5470
2017-02-07 17:35:04 +01:00
Jenkins for ownCloud 5002964546 [tx-robot] updated from transifex 2017-02-07 02:18:27 +01:00
Jenkins for ownCloud 4cca1ba55f [tx-robot] updated from transifex 2017-02-06 02:18:27 +01:00
Jenkins for ownCloud 3e99c32582 [tx-robot] updated from transifex 2017-02-05 02:18:27 +01:00
Jenkins for ownCloud 74ce597f8d [tx-robot] updated from transifex 2017-02-04 02:18:27 +01:00
Jenkins for ownCloud a27b2d94b3 [tx-robot] updated from transifex 2017-02-03 02:18:27 +01:00
Jenkins for ownCloud 890e771ec1 [tx-robot] updated from transifex 2017-02-02 02:18:27 +01:00
Jenkins for ownCloud 5df10cb8f8 [tx-robot] updated from transifex 2017-02-01 02:18:28 +01:00
Jenkins for ownCloud 9acc974268 [tx-robot] updated from transifex 2017-01-31 02:18:26 +01:00
Jenkins for ownCloud 42e64026ae [tx-robot] updated from transifex 2017-01-30 02:18:28 +01:00
Jenkins for ownCloud 78e7d13f9f [tx-robot] updated from transifex 2017-01-29 02:18:27 +01:00
Jenkins for ownCloud 2d55332a45 [tx-robot] updated from transifex 2017-01-28 02:18:34 +01:00
Jenkins for ownCloud 72cd9abd4a [tx-robot] updated from transifex 2017-01-28 01:15:15 +01:00
Olivier Goffart 0d16cf41fe Merge remote-tracking branch 'origin/master' into 2.3
We can do that because the only changes that were in master but not in 2.3 were the
translations change and documentation change, and the support for the 'M' permission
which we want in 2.3.
2017-01-27 17:45:05 +01:00
Olivier Goffart 65e4afedc4 Account Wizard: don't whitelist everything on the first sync if we still want to confirm big folder
Issue: https://github.com/owncloud/client/pull/5340#issuecomment-274564441
2017-01-27 15:59:59 +01:00
Olivier Goffart b76a9654cc General Settings: Make sure to reload the settings when an account is added
The Size limit, or confirmation checkboxes might have changed.

We need to guard against saving if the control changes while we are loading

Issue: https://github.com/owncloud/client/pull/5340#issuecomment-274878023
2017-01-27 15:59:59 +01:00
Olivier Goffart 38cf459b3e Confirm External Storage: adjust the notification message
We need to forward the information that the folder is an external storage
for the notification message.

Issue: https://github.com/owncloud/client/pull/5340#issuecomment-274878023
2017-01-27 15:59:59 +01:00
Olivier Goffart ed7416098e Wizard: Increase the size
The advanced page has become quite complex and does not fit on the screen
anymore if the fonts are too big
2017-01-27 15:59:59 +01:00
Olivier Goffart 517623e457 FolderStatusModel: Different icon for external storages
Issue: https://github.com/owncloud/client/pull/5340#issuecomment-274564441
2017-01-27 15:59:59 +01:00
Olivier Goffart f89bc09fd1 Discovery: Filter 'M' out of permissions for non root storage
The sync engine rely on the 'M' in premission to ask for confirmation
(As requested in issue #5340)
But we only want to ask the premission for the 'root' of the mounting point and not
for every subfolders within it.
So we change the discovery phase in a way that it does not keep the 'M' for
children within the external storage.
2017-01-27 15:59:59 +01:00
Olivier Goffart f854c5263b Wizard: Add options to ask confirmation for external storage
Added two checkboxes in the Account Wizard in the advanced page to change the first options.
Also added a checkbox in the general settings to ask for confirmation for external storages.

Theme options allow to hide the checkboxes in the wizard.

As described in issue #5340
2017-01-27 15:59:59 +01:00
Olivier Goffart 70da607e06 Discovery: Add branding option to disable default sync of 'M' directories
Issue #5331 and https://github.com/owncloud/enterprise/issues/1594
2017-01-27 15:59:59 +01:00
Jenkins for ownCloud 4f28b2daad [tx-robot] updated from transifex 2017-01-27 02:18:28 +01:00
Jocelyn Turcotte 8884fe7236 Remove PropagateDirectory::_runningNow
This variable isn't used anymore except in a stray Q_ASSERT.
2017-01-26 17:13:54 +01:00
Jocelyn Turcotte bb3efc5988 Clear SyncEngine::_remotePerms after the sync
Also make reuse the SyncFileItem::_remotePerm QByteArray allocation
instead of redoing the copy from the csync char*.
2017-01-26 17:13:54 +01:00
Jocelyn Turcotte f6665ccc81 Pack boolean members in PropagateUploadFileCommon #5457 2017-01-26 17:13:54 +01:00
Jocelyn Turcotte f1e9be4fa8 Don't use the StopWatch for each job in production builds #5456
This accounted for more than 10% of the peak memory usage while only
providing value through the debugging log.
2017-01-26 17:13:54 +01:00
Jocelyn Turcotte 9db23d4df1 Remove SyncFileItem::_requestDuration #5456
This will save a QElapsedTimer in each job that was used only for
.owncloudsync.log (for which the request duration doesn't bring much
value).
2017-01-26 17:13:54 +01:00
Jocelyn Turcotte 9d16ad844c Don't reallocate a QByteArray for each contentChecksumType call #5481 2017-01-26 17:13:54 +01:00
Jocelyn Turcotte b0700ebbab Remove duplicate SyncFileItem entries for the log
The accuracy of that log isn't as important as the few bytes those
fields take as hostage for the whole sync.
2017-01-26 17:13:54 +01:00
Markus Goetz 2bda55be81 Don't create legacy 'folders/' subdirectory 2017-01-26 12:29:58 +01:00
Markus Goetz e859d220be Cookies: Use different DB for different accounts (#5490)
This is a follow up to #5469
2017-01-26 10:54:03 +01:00
Piotr Mrówczyński c3ae5123cb Delete finished propagation jobs in PropagateDirectory #5269 (#5400) 2017-01-26 10:03:22 +01:00
Jenkins for ownCloud a1a5111a8a [tx-robot] updated from transifex 2017-01-26 02:18:40 +01:00
Jocelyn Turcotte ee211d7609 Release SyncFileItem objects with their job
We now delete subjobs as their propagation is complete. This allows us
to also release the item by making sure that nothing else is holding a
reference to it.

Remove the stored SyncFileItemVector from SyncEngine and SyncResult
and instead gather the needed info progressively as each itemCompleted
signal is emitted.

This frees some holes on the heap as propagation goes, allowing many
memory allocations without the need of requesting more virtual memory
from the OS, preventing the memory usage from increasingly growing.
2017-01-25 23:26:23 +01:00
Jocelyn Turcotte 1fc5a76622 Pass the SyncFileItem as SyncFileItemPtr in itemCompleted
This will allow us to keep a reference on the items in connected slots.
2017-01-25 23:26:23 +01:00
Jocelyn Turcotte a764d7eb86 Don't pass the PropagatorJob in itemCompleted
This was to catch duplicate emissions for PropagateDirectory but we
don't emit this signal anymore from there.
This fixes a warning about PropagatorJob not being a registered metatype.

This reverts commit fe42c1a818.
2017-01-25 23:26:23 +01:00
Jocelyn Turcotte 605a18ff73 Tests: Add a large sync benchmark
This simulates a ~50k files sync that can be used to measure memory
usage without having to wait for a server.
2017-01-25 23:26:23 +01:00
Jocelyn Turcotte 92e86641d1 Bring back the error message if the sync-exclude.lst file is missing
We unconditionnally add the file on startup, but don't check for errors.
During sync we check for errors, but only try loading the file if it
exists.
2017-01-25 23:26:23 +01:00
Markus Goetz c8cfb3160e Merge remote-tracking branch 'origin/selective-sync-big-folder' into 2.3 2017-01-25 19:45:20 +01:00
Olivier Goffart 268fc97a71 Merge pull request #5480 from owncloud/chunking-ng-cleanup
Chunking ng cleanup
2017-01-25 19:19:48 +01:00
Jenkins for ownCloud de2458d892 [tx-robot] updated from transifex 2017-01-25 02:18:34 +01:00
Matthew Setter d75b838897 Add extra note about deleting .csync_journal.db
This is added as per the recommendation from @guruz in #5252.
2017-01-24 16:18:21 +01:00
Carla Schroder 4df7cab72a add note about deleting .csync_journal.db for "CSync unknown error" 2017-01-24 16:18:21 +01:00
Christian Kamm 59c1fdbe05 Shib: Use different keychain entry per account #5469
Previously shib multiaccount didn't work at all because the
session cookie was stored in the same keychain entry.
2017-01-24 13:14:11 +01:00
Christian Kamm 26234dbf6c Folders: Adjust ui when account is disconnected #5477
Previously if you paused/unpaused a folder for a disconnected account
they would prepare to sync and thus display the 'Waiting...' text. With
this change, folders that can't possibly sync don't show text like
this.

When account connectivity changes, all unpaused folders will be
scheduled anyway.
2017-01-24 10:26:03 +01:00
Jenkins for ownCloud 05a254b527 [tx-robot] updated from transifex 2017-01-24 02:18:28 +01:00
Jenkins for ownCloud d282a8380e [tx-robot] updated from transifex 2017-01-23 11:11:23 +01:00
Jenkins for ownCloud 83dfbb933b [tx-robot] updated from transifex 2017-01-22 02:18:27 +01:00
Jenkins for ownCloud 100603fdc0 [tx-robot] updated from transifex 2017-01-21 02:18:28 +01:00
Olivier Goffart d6fdda8efa ChunkingNG: add '0' padding on the filename (#5476)
The server sorts the chunk by name alphabetically. So if we want to keep
the chunk in order, we need to add a few '0' in front of the chunk name
2017-01-20 16:03:50 +01:00
Markus Goetz faedaa5e09 Update issue_template.md 2017-01-20 16:00:50 +01:00
Olivier Goffart 8a70d22af7 ChunkingNG: Add some tests
- Test that we recover correctly if the chunks were removed on the server.
 - Test changing the file localy while uploading.
2017-01-20 14:48:53 +01:00
Olivier Goffart a63d970e5e ChunkingNG: remove stale chunks when cleaning the uploadInfo table
Stale chunks might be there because a file was removed or would just not
be uploaded, for any reason.
We just start the DeleteJob but we don't care if it success or not.

Relates to https://github.com/owncloud/core/issues/26981

One of the test is testing the case where the file is modified on the server
during the upload. So this test the precondition failed error.
The FakeGetReply logic was modified because resizing a 150MB big QByteArray
by increment of 16k just did not scale when downloading a big file.
2017-01-20 14:48:53 +01:00
Olivier Goffart f6c77fad17 ChunkingNG: delete stale chunks if the file was changed locally
Relates to https://github.com/owncloud/core/issues/26981

We do not track the success or error of the DeleteJob because it does not
matter. If it fails, it might be because the chunks were already removed.
If not, the chunks will be stale, but the server must anyway do a few
cleanup from time to time because we do not always remove the chunks
2017-01-20 14:48:53 +01:00
Jenkins for ownCloud 661c7f0558 [tx-robot] updated from transifex 2017-01-20 02:18:34 +01:00
Jenkins for ownCloud a7efe144fc [tx-robot] updated from transifex 2017-01-19 02:18:40 +01:00
Jocelyn Turcotte b68a28de8d StatusTracker: Emit OK for the last child before parents (#5467)
The current logic tried to avoid a DB lookup just to fetch whether
the file is shared or not since that info is already in the
SyncFileItem. The implementation would however need to decrease the
sync count for itself (and parents) before emitting the new status,
thus emitting the OK status for parents before that last child that
ended the propagation for that folder.

Change the implementation to achieve what we want: give the
possibility to decSyncCount to use a pre-fetched sharing state while
still doing the emission for all involved files. This ensures that
the leaf file also gets its status emitted before its parents.

Issue #4797
2017-01-18 15:40:52 +01:00
Samuel Alfageme 72a7b7ca42 Reference to build Qt5 with qtwebkit support in the docs #5129 (#5471)
This addresses the issue only on OS X. It should be stated though, that qtwebkit is not part of the qt5core lib and therefore a requirement for the projectto build in the rest of the OSS
2017-01-18 14:46:47 +01:00
Jocelyn Turcotte 166ef85a51 shell/Windows: Update binaries to build 44 2017-01-18 13:34:02 +01:00
Matthew Setter 1f60c61f87 Update the MacOS automatic update instructions
As requested in #5431, the automatic update instructions for MacOS X
have been simplified; removing the older, incorrect instructions.
2017-01-18 12:55:23 +01:00
Matthew Setter 30ef794fa1 Fix several typos in the client documentation 2017-01-18 12:53:33 +01:00
Jocelyn Turcotte 47fbfbc006 shell/Windows: Avoid memory allocations and copies when querying icons
IsMemberOf is called for every file (in the ownCloud directory or not) and
with every instance of OCOverlay (we have 5) when displaying a list of
files in Explorer.

Refactor the code to avoid copying the list of watched directories, as
well as creating a wstring from a PWWSTR for files outside watched
directories.

Also change some calls of begin_with to use isDescendantOf since it
properly handles parent paths not ending with a backslash, which could
lead to SocketAPI queries for sibling folders with a name that starts with
a watched folder name.
2017-01-18 12:15:52 +01:00
Jocelyn Turcotte e131c142ff shell/Windows: Fix the view not being updated on StateError
Since StateError == 0, if this was the status used when the path
isn't in the map already, the view would not be updated since the
new state would be the same as the default-constructed state in the
map. Fix by explicitly inserting in that case, this also avoid aving
to do two lookups in the map when a path already has an entry.
2017-01-18 12:15:52 +01:00
Jocelyn Turcotte 1b99ff2e91 shell/Windows: Remove the UPDATE_VIEW message handling
The client now tries to only push STATUS messages to connections
unless they previously requested it with a RETRIEVE_FILE_STATUS,
but this means that we now have to make sure that a new connection
will rerequest every icon that the user will see on files from that
point on.

To that end, we now send a SHChangeNotify for every file in the cache
when we lose the connection (or on UNREGISTER_PATH) to make sure that
what's on the screen matches what's in the cache. We also remove the
_oldCache logic that made this more difficult to enforce.

The client has been able to reliably push status updates on macOS
for a few versions now, and we don't need it on Windows either. The
_oldCache mechanism was to avoid sending to many update requests
when receiving an UPDATE_VIEW.

Also fixes #4766
2017-01-18 12:15:52 +01:00
Jocelyn Turcotte 3e85d47a57 shell/Windows: Convert tabs to space
It was a mix of both and the rest of the code uses spaces.
2017-01-18 12:15:52 +01:00
Jocelyn Turcotte e709d75d56 shell/Windows: Remove unused files
The real OCContextMenu.cpp is in the OCContextMenu folder.
2017-01-18 12:15:52 +01:00
Jocelyn Turcotte cb5cfb8cf6 shell/macOS: Make sure the root folder's cache is cleared on disconnect
The SocketAPI now only sends status pushes for paths requested by the
shell. We have to make sure that Finder doesn't just show the entry
from its cache after a reconnect.
2017-01-18 12:15:52 +01:00
Jocelyn Turcotte ebd2a15711 shell/macOS: Remove backslashes from the extension display name
Tell cmake not to escape shell strings adding backslashes before
spaces by passing the VERBATIM optiton. Also add the quotes to
whole command line arguments to prevent quotes from appearing on the
XCode side, because of the VERBATIM option.

This only affects themed clients since the default theme doesn't
have space in its APPLICATION_NAME.
2017-01-18 12:15:52 +01:00
Jocelyn Turcotte d3a0608bd5 SocketAPI: Only push status for files requested by the shell #5361
We currently push the SYNC status for all files that will be propagated,
and then the OK status when those files are propagated.
On top of this, we send those statuses to all clients connected, even
if the socket is kept open by an application that only needed to show
a file open dialog. On macOS we're also using an NSConnection which
means that we have to wait for the RPC call to return from the
extension, which makes bulk status changes possibly heavy.

Reduce the time spent needlessly sending status pushes by limiting
them to files requested through that socket since it connected.
To limit the data to store, only remember the parent directory of
files requested, and store those in a bloom filter.

Note that this adds a requirement to shell extensions: they should
make sure that the status cache only contains entries that have been
requested through the socket API. In other words, the status cache
must be empty when each socket client connects to the socket API.
Otherwise the cached icon type will be shown to the user, and the
SocketAPI won't push new status for that file if it didn't receive
a RETRIEVE_FILE_STATUS.
2017-01-18 12:15:52 +01:00
Jocelyn Turcotte c25b599bbb SocketApi::slotReadSocket: Small optimizations
- Use the looked-up method index also for the invocation
- Do the method name concatenation already on QByteArray since we'll
  convert anyway
- Use staticMetaObject instead of metaObject()
2017-01-18 12:15:52 +01:00
Jocelyn Turcotte a5ff9e58e3 SocketAPI: Remove unecessary null-checks
Those methods are private and there is only one call-site, we can
be sure that this parameter won't be null already.
2017-01-18 12:15:52 +01:00
Olivier Goffart 9b96899d75 Sync Engine: Specify what chars are not syncable in the error message #1733 (#5449) 2017-01-18 11:45:46 +01:00
Olivier Goffart b046cca010 Fix more compilation errors with Qt 4
Ammand last commit which was a fixup to the change from pull request #5468
for issue #5453
2017-01-18 10:19:51 +01:00
Olivier Goffart edf0a99a8a Fix compilation with Qt 4
Fixup to the change from pull request #5468 for issue #5453
2017-01-18 09:57:36 +01:00
Jenkins for ownCloud a4640b202f [tx-robot] updated from transifex 2017-01-18 02:18:27 +01:00
Markus Goetz 5ef2e88f00 NSIS: Adjust to 5.6.2 image 2017-01-17 17:35:32 +01:00
Christian Kamm 352f168313 Folder: Remove unused variable 2017-01-17 14:53:09 +01:00
Markus Goetz 85d3de1589 Disable RTTI
Shrinks owncloud binary by 24 KB and libowncloudsync by 14 KB.
I don't know if it has influence on memory usage or runtime speed though.

Was worth a try.
2017-01-17 14:52:10 +01:00
Markus Goetz 588a88fb63 Updater: Don't create instance for invalid URL
Also don't use dynamic_cast
For enterprise/#689
2017-01-17 14:52:10 +01:00
Christian Kamm cd9e88ad22 PropagatorJob: Remove unneccessary pointer #5453 2017-01-17 14:47:38 +01:00
Christian Kamm 29b39acfbe PropagatorJob: Access propagator through function #5453 2017-01-17 14:47:38 +01:00
Matthew Setter 7427be0062 Merge pull request #5466 from settermjd/add-directory-limit-to-faq
Add Sync Client's Directory Depth Limit To FAQ
2017-01-17 14:33:35 +01:00
Matthew Setter e7546903cc Add an FAQ entry about the sync client's sub-directory scan limit
As requested in #1067, this commit adds an entry to the FAQ to highlight
the fact that the sync client will never scan greater than 50
sub-directories.
2017-01-17 11:14:52 +01:00
Matthew Setter 78e3a7e897 Revise the FAQ entry style
This approach uses less content, and makes the content more prominent.
2017-01-17 10:36:42 +01:00
Jenkins for ownCloud 1a21b8698e [tx-robot] updated from transifex 2017-01-17 02:18:34 +01:00
Carlos Damken 280906eab9 Ignoring "System Volume Information"
Avoid to upload the "System Volume Information"
2017-01-16 19:11:56 +01:00
Markus Goetz 9d7425b201 DB: Also migrate -shm and -wal to new name #3764 #5045 (#5459) 2017-01-16 15:42:11 +01:00
Markus Goetz 7eb43d7f7e PropagateUploadFileNG: Delete unused map contents to free memory 2017-01-13 19:00:04 +01:00
ckamm d76e0ec6d8 Reset stuck chunked uploads eventually #5344 (#5443)
Previously this wasn't happening for errors that were not
NormalErrors because they don't end up in the blacklist.

This revises the resetting logic to be independent of the
error blacklist and make use of UploadInfo::errorCount
instead.

412 errors should reset chunked uploads because they might be
indicative of a checksum error.

Additionally, server bugs might require that additional
errors cause an upload reset. To allow that, a new capability
is added that can be used to advise the client about this.
2017-01-13 14:44:45 +01:00
Olivier Goffart 0249a68420 SelectiveSync: adjust the position of the "Loading" label
It should be parented to the treeview to be sure that is shows inside of it.
2017-01-13 10:55:45 +01:00
Christian Kamm aa6f041c36 wizardSelectiveSyncDefaultNothing applies to folder wizard #4581
Previous the Theme option only applied to the account setup wizard.
2017-01-13 10:52:39 +01:00
Christian Kamm dce3f8c4f6 Selective sync: Adjust widget common to folder/account wizards 2017-01-13 10:52:10 +01:00
Jenkins for ownCloud 4a83f976e1 [tx-robot] updated from transifex 2017-01-13 02:18:27 +01:00
Jenkins for ownCloud 23572aaf77 [tx-robot] updated from transifex 2017-01-12 02:18:33 +01:00
Christian Kamm 48655ff1ec Doc: Add forceSyncInterval and timeout config file flags 2017-01-11 11:34:36 +01:00
Christian Kamm ffbf34cb97 Log the auth type being used for accounts
There have been hard to track down bugs related to the wrong auth
type being used.
2017-01-11 09:30:59 +01:00
Jenkins for ownCloud fad690be11 [tx-robot] updated from transifex 2017-01-11 02:18:38 +01:00
183 arquivos alterados com 14646 adições e 11873 exclusões
+2 -3
Ver Arquivo
@@ -7,6 +7,8 @@ endif()
project(client)
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(OEM_THEME_DIR "" CACHE STRING "Define directory containing a custom theme")
if ( EXISTS ${OEM_THEME_DIR}/OEM.cmake )
include ( ${OEM_THEME_DIR}/OEM.cmake )
@@ -58,9 +60,6 @@ if( UNIX AND NOT APPLE )
endif()
####
# Enable Q_ASSERT etc. in all builds
add_definitions( -DQT_FORCE_ASSERTS )
include(GNUInstallDirs)
include(DefineInstallationPaths)
include(GenerateExportHeader)
+5 -4
Ver Arquivo
@@ -1,10 +1,11 @@
ChangeLog
=========
version 2.3.0 (2017-0x-xx)
* WiP!
* WiP Switch Windows and OS X build to 5.6.2
* WiP Performance improvements for exclude detection
version 2.3.0 (2017-02-xx)
* Decreased memory usage during sync
* Overlay icons: Lower CPU usage
* Allow to not sync the server's external storages by default
* Switch Windows and OS X build to 5.6.2
* Switch to new ownCloud server WebDAV endpoint
* Chunking NG: New file upload chunking algorithmn for ownCloud server 9.2
* Allow to sync a folder to multiple different servers (Filename change from .csync_journal.db to _sync_$HASH.db)
+1 -1
Ver Arquivo
@@ -39,7 +39,7 @@ node('CLIENT') {
stage 'Win32'
def win32 = docker.image('deepdiver/docker-owncloud-client-win32:latest')
def win32 = docker.image('guruz/docker-owncloud-client-win32:latest')
win32.pull() // make sure we have the latest available from Docker Hub
win32.inside {
sh '''
+1 -1
Ver Arquivo
@@ -3,7 +3,7 @@ StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Показати примітки
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Знайдено процес(и) ${APPLICATION_EXECUTABLE}, які необхідно зупинити.$\nХочете щоб програма установки зробила це самостійно?"
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Завершення процесів ${APPLICATION_EXECUTABLE}."
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Не знайдено процеси, які необхідно зупинити!"
StrCpy $PageReinstall_NEW_Field_1 "Знайдено застарілу версію програми ${APPLICATION_NAME}. Рекомендуємо її спочатку видалити. Оберіть подальшу дію та натисніть $\"Далі$\"."
StrCpy $PageReinstall_NEW_Field_1 "У вашої системі встановлена застаріла версія додатку ${APPLICATION_NAME}. Рекомендуємо видалити її перед початком встановлення поточної версії. Оберіть подальшу дію та натисніть $\"Далі$\"."
StrCpy $PageReinstall_NEW_Field_2 "Видалити перед установкою"
StrCpy $PageReinstall_NEW_Field_3 "Не видаляти"
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Установлено"
+1 -1
Submodule binary updated: 0d89ac7766...741b49156b
+8 -7
Ver Arquivo
@@ -418,10 +418,8 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
File "${QT_DLL_PATH}\Qt5Core.dll"
File "${QT_DLL_PATH}\Qt5Gui.dll"
File "${QT_DLL_PATH}\Qt5Network.dll"
File "${QT_DLL_PATH}\Qt5OpenGL.dll"
File "${QT_DLL_PATH}\Qt5PrintSupport.dll"
File "${QT_DLL_PATH}\Qt5Qml.dll"
File "${QT_DLL_PATH}\Qt5Quick.dll"
File "${QT_DLL_PATH}\Qt5Sql.dll"
File "${QT_DLL_PATH}\Qt5WebKit.dll"
File "${QT_DLL_PATH}\Qt5WebKitWidgets.dll"
@@ -435,9 +433,9 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
;Qt deps
File "${MING_BIN}\libpng16-16.dll"
File "${MING_BIN}\icudata53.dll"
File "${MING_BIN}\icui18n53.dll"
File "${MING_BIN}\icuuc53.dll"
File "${MING_BIN}\icudata56.dll"
File "${MING_BIN}\icui18n56.dll"
File "${MING_BIN}\icuuc56.dll"
File "${MING_BIN}\libEGL.dll"
File "${MING_BIN}\libGLESv2.dll"
File "${MING_BIN}\libjpeg-8.dll"
@@ -446,11 +444,14 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
File "${MING_BIN}\libcrypto-10.dll"
File "${MING_BIN}\libssl-10.dll"
File "${MING_BIN}\libstdc++-6.dll"
File "${MING_BIN}\libwebp-4.dll"
File "${MING_BIN}\libwebp-5.dll"
File "${MING_BIN}\libxslt-1.dll"
File "${MING_BIN}\libxml2-2.dll"
File "${MING_BIN}\zlib1.dll"
File "${MING_BIN}\libsqlite3-0.dll"
File "${MING_BIN}\libharfbuzz-0.dll"
File "${MING_BIN}\libfreetype-6.dll"
File "${MING_BIN}\libglib-2.0-0.dll"
File "${MING_BIN}\libintl-8.dll"
;QtKeyChain stuff
File "${MING_BIN}\libqt5keychain.dll"
+1 -2
Ver Arquivo
@@ -28,7 +28,6 @@ include(ConfigureChecks.cmake)
set(SOURCE_DIR ${CMAKE_SOURCE_DIR})
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
include_directories(${CMAKE_CURRENT_BINARY_DIR})
@@ -41,7 +40,7 @@ endif (MEM_NULL_TESTS)
add_subdirectory(src)
if (UNIT_TESTING)
set(WITH_UNIT_TESTING ON)
set(WITH_TESTING ON)
find_package(CMocka)
if (CMOCKA_FOUND)
+1 -1
Ver Arquivo
@@ -26,4 +26,4 @@
#cmakedefine HAVE___MINGW_ASPRINTF 1
#cmakedefine HAVE_ASPRINTF 1
#cmakedefine WITH_UNIT_TESTING 1
#cmakedefine WITH_TESTING 1
+1 -1
Ver Arquivo
@@ -45,7 +45,7 @@
#define CSYNC_LOG_CATEGORY_NAME "csync.exclude"
#include "csync_log.h"
#ifndef WITH_UNIT_TESTING
#ifndef WITH_TESTING
static
#endif
int _csync_exclude_add(c_strlist_t **inList, const char *string) {
+1 -1
Ver Arquivo
@@ -36,7 +36,7 @@ enum csync_exclude_type_e {
};
typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE;
#ifdef WITH_UNIT_TESTING
#ifdef WITH_TESTING
int OCSYNC_EXPORT _csync_exclude_add(c_strlist_t **inList, const char *string);
#endif
+2 -2
Ver Arquivo
@@ -89,7 +89,7 @@ struct csync_s {
/* hooks for checking the white list (uses the update_callback_userdata) */
int (*checkSelectiveSyncBlackListHook)(void*, const char*);
int (*checkSelectiveSyncNewFolderHook)(void*, const char*);
int (*checkSelectiveSyncNewFolderHook)(void*, const char* /* path */, const char* /* remotePerm */);
csync_vio_opendir_hook remote_opendir_hook;
@@ -207,7 +207,7 @@ __attribute__ ((packed))
#endif
;
void csync_file_stat_free(csync_file_stat_t *st);
OCSYNC_EXPORT void csync_file_stat_free(csync_file_stat_t *st);
/*
* context for the treewalk function
+5 -7
Ver Arquivo
@@ -56,17 +56,15 @@ int csync_get_statedb_exists(CSYNC *ctx);
*
* @return 0 on success, less than 0 if an error occurred with errno set.
*/
int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb);
OCSYNC_EXPORT int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb);
int csync_statedb_close(CSYNC *ctx);
OCSYNC_EXPORT int csync_statedb_close(CSYNC *ctx);
csync_file_stat_t *csync_statedb_get_stat_by_hash(CSYNC *ctx, uint64_t phash);
OCSYNC_EXPORT csync_file_stat_t *csync_statedb_get_stat_by_hash(CSYNC *ctx, uint64_t phash);
csync_file_stat_t *csync_statedb_get_stat_by_inode(CSYNC *ctx, uint64_t inode);
OCSYNC_EXPORT csync_file_stat_t *csync_statedb_get_stat_by_inode(CSYNC *ctx, uint64_t inode);
csync_file_stat_t *csync_statedb_get_stat_by_file_id(CSYNC *ctx, const char *file_id);
char *csync_statedb_get_etag(CSYNC *ctx, uint64_t jHash);
OCSYNC_EXPORT csync_file_stat_t *csync_statedb_get_stat_by_file_id(CSYNC *ctx, const char *file_id);
/**
* @brief Query all files metadata inside and below a path.
+1 -1
Ver Arquivo
@@ -436,7 +436,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
st->instruction = CSYNC_INSTRUCTION_NEW;
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)) {
if (ctx->callbacks.checkSelectiveSyncNewFolderHook(ctx->callbacks.update_callback_userdata, path, fs->remotePerm)) {
csync_file_stat_free(st);
return 1;
}
+11 -6
Ver Arquivo
@@ -77,7 +77,7 @@ a synchronization process.
Before the 1.3.0 release of the Desktop Client, the synchronization process
might create false conflict files if time deviates. Original and changed files
conflict only in their timestamp, but not in their content. This behaviour was
conflict only in their timestamp, but not in their content. This behavior was
changed to employ a binary check if files differ.
Like files, directories also hold a unique ID that changes whenever one of the
@@ -132,11 +132,16 @@ changed and no synchronization occurs.
In the event a file has changed on both the local and the remote repository
since the last sync run, it can not easily be decided which version of the file
is the one that should be used. However, changes to any side will not be lost. Instead,
a *conflict case* is created. The client resolves this conflict by creating a
conflict file of the older of the two files and saving the newer file under the
original file name. Conflict files are always created on the client and never
on the server. The conflict file uses the same name as the original file, but
is appended with the timestamp of the conflict detection.
a *conflict case* is created. The client resolves this conflict by renaming the
local file, appending a conflict label and timestamp, and saving the remote file
under the original file name.
Example: Assume there is a conflict in message.txt because its contents have
changed both locally and remotely since the last sync run. The local file with
the local changes will be renamed to message_conflict-20160101-153110.txt and
the remote file will be downloaded and saved as message.txt.
Conflict files are always created on the client and never on the server.
.. _ignored-files-label:
+3 -20
Ver Arquivo
@@ -3,7 +3,7 @@ The Automatic Updater
=====================
The Automatic Updater ensures that you always have the
latest features and bugfixes for your ownCloud synchronization client.
latest features and bug fixes for your ownCloud synchronization client.
The Automatic Updater updates only on Mac OS X and Windows computers; Linux
users only need to use their normal package managers. However, on Linux systems
@@ -49,7 +49,6 @@ the Linux operating system do not perform any updates on their own. The client
will inform you (``Settings -> General -> Updates``) when an update is
available.
Preventing Automatic Updates
----------------------------
@@ -110,24 +109,8 @@ To prevent automatic updates and disallow manual overrides:
Preventing Automatic Updates in Mac OS X Environments
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You can disable the automatic update mechanism in Mac OS X operating systems
using the system-wide ``.plist`` file. To access this file:
1. Go to this directory::
/Library/Preferences/
2. Locate and open the following file::
com.owncloud.desktopclient.plist
3. Add a new root level item of type ``bool``.
4. Name the item ``skipUpdateCheck``.
5. Set the item to ``true``.
Alternatively, you can copy the file
You can disable the automatic update mechanism, in the Mac OS X operating system,
by copying the file
``owncloud.app/Contents/Resources/deny_autoupdate_com.owncloud.desktopclient.plist``
to ``/Library/Preferences/com.owncloud.desktopclient.plist``.
+12 -8
Ver Arquivo
@@ -54,7 +54,7 @@ distribution. Make sure the repositories for source packages are enabled.
Mac OS X
--------
In additon to needing XCode (along with the command line tools), developing in
In addition to needing XCode (along with the command line tools), developing in
the Mac OS X environment requires extra dependencies. You can install these
dependencies through MacPorts_ or Homebrew_. These dependencies are required
only on the build machine, because non-standard libs are deployed in the app
@@ -77,25 +77,29 @@ To set up your build environment for development using HomeBrew_:
brew tap owncloud/owncloud
5. Install any missing dependencies::
5. Install a Qt5 version with qtwebkit support::
brew install qt5 --with-qtwebkit
6. Install any missing dependencies::
brew install $(brew deps owncloud-client)
3. Add Qt from brew to the path::
7. Add Qt from brew to the path::
export PATH=/usr/local/Cellar/qt5/5.x.y/bin:$PATH
Where ``x.z`` is the current version of Qt 5 that brew has installed
Where ``x.y`` is the current version of Qt 5 that brew has installed
on your machine.
4. Install qtkeychain from here: git clone https://github.com/frankosterfeld/qtkeychain.git
8. Install qtkeychain from here: git clone https://github.com/frankosterfeld/qtkeychain.git
make sure you make the same install prefix as later while building the client e.g. -
``DCMAKE_INSTALL_PREFIX=/Path/to/client-install``
5. For compilation of the client, follow the :ref:`generic-build-instructions`.
9. For compilation of the client, follow the :ref:`generic-build-instructions`.
6. Install the Packages_ package creation tool.
10. Install the Packages_ package creation tool.
7. In the build directory, run ``admin/osx/create_mac.sh <build_dir>
11. In the build directory, run ``admin/osx/create_mac.sh <build_dir>
<install_dir>``. If you have a developer signing certificate, you can specify
its Common Name as a third parameter (use quotes) to have the package
signed automatically.
+8 -3
Ver Arquivo
@@ -16,15 +16,20 @@ format. You can overwrite changes using the ownCloud configuration dialog.
.. note:: Use caution when making changes to the ownCloud Client configuration
file. Incorrect settings can produce unintended results.
You can change the following configuration settings (must be under the ``[ownCloud]`` section)
You can change the following configuration settings in the ``[ownCloud]`` section:
- ``remotePollInterval`` (default: ``30000``) -- Specifies the poll time for the remote repository in milliseconds.
- ``maxLogLines`` (default: ``20000``) -- Specifies the maximum number of log lines displayed in the log window.
- ``forceSyncInterval`` (default: ``7200000``) -- The duration of no activity after which a synchronization run shall be triggered automatically.
- ``notificationRefreshInterval`` (default: ``300000``) -- Specifies the default interval of checking for new server notifications in milliseconds.
You can change the following configuration settings in the ``[General]`` section:
- ``chunkSize`` (default: ``5242880``) -- Specifies the chunk size of uploaded files in bytes.
- ``promptDeleteAllFiles`` (default: ``true``) -- If a UI prompt should ask for confirmation if it was detected that all files and folders were deleted.
- ``notificationRefreshInterval`` (default``300,000``) -- Specifies the default interval of checking for new server notifications in milliseconds.
- ``maxLogLines`` (default: ``20000``) -- Specifies the maximum number of log lines displayed in the log window.
- ``timeout`` (default: ``300``) -- The timeout for network connections in seconds.
+9 -6
Ver Arquivo
@@ -1,17 +1,20 @@
FAQ
===
**Issue:**
Some files are continuously uploaded to the server, even when they are not modified.
**Resolution:**
------------------------------------------------------------------------------------
It is possible that another program is changing the modification date of the file.
If the file is uses the ``.eml`` extension, Windows automatically and
continually changes all files, unless you remove
``\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\PropertySystem\PropertyHandlers``
from the windows registry.
See http://petersteier.wordpress.com/2011/10/22/windows-indexer-changes-modification-dates-of-eml-files/ for more information.
Syncing breaks when attempting to sync deeper than 50 sub-directories, but the sync client does not report an error (RC=0)
--------------------------------------------------------------------------------------------------------------------------
The sync client has been intentionally limited to sync no deeper than
fifty sub-directories, to help prevent memory problems.
Unfortunately, it, *currently*, does not report an error when this occurs.
However, a UI notification is planned for a future release of ownCloud.
+15
Ver Arquivo
@@ -50,6 +50,21 @@ Identifying Basic Functionality Problems
As an example, after installing the ``cadaver`` app, you can issue the
``propget`` command to obtain various properties pertaining to the current
directory and also verify WebDAV server connection.
"CSync unknown error"
---------------------
If you see this error message stop your client, delete the
``.csync_journal.db`` file, and then restart your client.
There is a ``.csync_journal.db`` file inside the folder of every account
configured on your client.
.. NOTE::
Please note that this will also erase some of your settings about which
files to download.
See https://github.com/owncloud/client/issues/5226 for more discussion of this
issue.
Isolating other issues
+2 -2
Ver Arquivo
@@ -138,7 +138,7 @@ Network
.. index:: proxy settings, SOCKS, bandwith, throttling, limiting
This tab consollidates ``Proxy Settings`` and ``Bandwith Limiting``:
This tab consolidates ``Proxy Settings`` and ``Bandwith Limiting``:
.. image:: images/settings_network.png
:scale: 50 %
@@ -152,7 +152,7 @@ Proxy Settings
On Linux, this will only pick up the value of the variable ``http_proxy``.
* ``Specify proxy manually as``: Allows to specify custom proxy settings.
If you require to go through a HTTP(S) proxy server such as Squid or Microsoft
Forefront TMG, pick ``HTTP(S)``. ``SOCKSv5`` on the other hand is particulary
Forefront TMG, pick ``HTTP(S)``. ``SOCKSv5`` on the other hand is particularly
useful in special company LAN setups, or in combination with the OpenSSH
dynamic application level forwarding feature (see ``ssh -D``).
* ``Host``: Enter the host name or IP address of your proxy server, followed
+4
Ver Arquivo
@@ -37,6 +37,10 @@ Operating system:
OS language:
Qt version used by client package (Linux only, see also Settings dialog):
Client package (From ownCloud or distro) (Linux only):
Installation path of client:
### Logs
+107 -8
Ver Arquivo
@@ -625,6 +625,96 @@ X-GNOME-Autostart-Delay=3
# 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
# Translations
# Translations
Comment[oc]=@APPLICATION_NAME@ sincronizacion del client
GenericName[oc]=Dorsièr de Sincronizacion
@@ -650,7 +740,9 @@ Comment[ja_JP]=@APPLICATION_NAME@ デスクトップ同期クライアント
GenericName[ja_JP]=フォルダー同期
Name[ja_JP]=@APPLICATION_NAME@ デスクトップ同期クライアント
Icon[ja_JP]=@APPLICATION_EXECUTABLE@
Comment[el]=@ΟΝΟΜΑ_ΕΦΑΡΜΟΓΗΣ@ συγχρονισμός επιφάνειας εργασίας πελάτη
GenericName[el]=Συγχρονισμός φακέλου
Name[el]=@ΟΝΟΜΑ_ΕΦΑΡΜΟΓΗΣ@ συγχρονισμός επιφάνειας εργασίας πελάτη
Icon[el]=@APPLICATION_EXECUTABLE@
Comment[en_GB]=@APPLICATION_NAME@ desktop synchronisation client
GenericName[en_GB]=Folder Sync
@@ -664,10 +756,13 @@ 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[pl]=@APPLICATION_NAME@ klient synchronizacji dla komputerów stacjonarnych
GenericName[pl]=Folder Synchronizacji
Name[pl]=@APPLICATION_NAME@ klient synchronizacji dla komputerów stacjonarnych
Icon[pl]=@APPLICATION_EXECUTABLE@
Comment[bg_BG]=@APPLICATION_NAME@ клиент за десктоп синхронизация
GenericName[bg_BG]=Синхронизиране на папката
Name[bg_BG]=@APPLICATION_NAME@ клиент десктоп синхронизация
Icon[bg_BG]=@APPLICATION_EXECUTABLE@
GenericName[fa]=همسان سازی پوشه‌ها
Name[fa]=@APPLICATION_EXECUTABLE@ نسخه‌ی همسان سازی مشتری
Icon[fa]=@APPLICATION_EXECUTABLE@
Comment[fr]=@APPLICATION_NAME@ synchronisation du client
GenericName[fr]=Dossier de Synchronisation
Name[fr]=@APPLICATION_NAME@ synchronisation du client
@@ -676,6 +771,10 @@ Comment[he]=@APPLICATION_NAME@ לקוח סנכון שולחן עבודה
GenericName[he]=סנכון תיקייה
Name[he]=@APPLICATION_NAME@ לקוח סנכרון שולחן עבודה
Icon[he]=@APPLICATION_EXECUTABLE@
Comment[ia]=@APPLICATION_NAME@ cliente de synchronisation pro scriptorio
GenericName[ia]=Synchronisar Dossier
Name[ia]=@APPLICATION_NAME@ cliente de synchronisation pro scriptorio
Icon[ia]=@APPLICATION_EXECUTABLE@
Comment[id]=Klien sinkronisasi desktop @APPLICATION_NAME@
GenericName[id]=Folder Sync
Name[id]=Klien sync desktop @APPLICATION_NAME@
@@ -703,10 +802,10 @@ Comment[et_EE]=@APPLICATION_NAME@ sünkroonimise klient töölauale
GenericName[et_EE]=Kaustade sünkroonimine
Name[et_EE]=@APPLICATION_NAME@ sünkroonimise klient töölauale
Icon[et_EE]=@APPLICATION_EXECUTABLE@
Comment[bg_BG]=@APPLICATION_NAME@ клиент за десктоп синхронизация
GenericName[bg_BG]=Синхронизиране на папката
Name[bg_BG]=@APPLICATION_NAME@ клиент десктоп синхронизация
Icon[bg_BG]=@APPLICATION_EXECUTABLE@
Comment[pl]=@APPLICATION_NAME@ klient synchronizacji dla komputerów stacjonarnych
GenericName[pl]=Folder Synchronizacji
Name[pl]=@APPLICATION_NAME@ klient synchronizacji dla komputerów stacjonarnych
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
+7 -6
Ver Arquivo
@@ -16,12 +16,13 @@ set(OC_OEM_SHARE_ICNS "${CMAKE_BINARY_DIR}/src/gui/ownCloud.icns")
# those user-defined settings to build the plist.
add_custom_target( mac_overlayplugin ALL
xcodebuild -project ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj
-target FinderSyncExt -configuration Release SYMROOT=${CMAKE_CURRENT_BINARY_DIR}
OC_OEM_SHARE_ICNS=${OC_OEM_SHARE_ICNS}
OC_APPLICATION_NAME="${APPLICATION_NAME}"
OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}
OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}
COMMENT building Mac Overlay icons)
-target FinderSyncExt -configuration Release "SYMROOT=${CMAKE_CURRENT_BINARY_DIR}"
"OC_OEM_SHARE_ICNS=${OC_OEM_SHARE_ICNS}"
"OC_APPLICATION_NAME=${APPLICATION_NAME}"
"OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}"
"OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}"
COMMENT building Mac Overlay icons
VERBATIM)
add_dependencies(mac_overlayplugin ${APPLICATION_EXECUTABLE}) # for the ownCloud.icns to be generated
@@ -155,9 +155,13 @@
{
_shareMenuTitle = nil;
[_registeredDirectories removeAllObjects];
// For some reason the FIFinderSync cache doesn't seem to be cleared for the root item when
// we reset the directoryURLs (seen on macOS 10.12 at least).
// First setting it to the FS root and then setting it to nil seems to work around the issue.
[FIFinderSyncController defaultController].directoryURLs = [NSSet setWithObject:[NSURL fileURLWithPath:@"/"]];
// This will tell Finder that this extension isn't attached to any directory
// until we can reconnect to the sync client.
[_registeredDirectories removeAllObjects];
[FIFinderSyncController defaultController].directoryURLs = nil;
}
@@ -36,54 +36,54 @@ using namespace std;
OCClientInterface::ContextMenuInfo OCClientInterface::FetchInfo()
{
auto pipename = CommunicationSocket::DefaultPipePath();
auto pipename = CommunicationSocket::DefaultPipePath();
CommunicationSocket socket;
if (!WaitNamedPipe(pipename.data(), PIPE_TIMEOUT)) {
return {};
}
if (!socket.Connect(pipename)) {
return {};
}
socket.SendMsg(L"SHARE_MENU_TITLE\n");
CommunicationSocket socket;
if (!WaitNamedPipe(pipename.data(), PIPE_TIMEOUT)) {
return {};
}
if (!socket.Connect(pipename)) {
return {};
}
socket.SendMsg(L"SHARE_MENU_TITLE\n");
ContextMenuInfo info;
std::wstring response;
int sleptCount = 0;
while (sleptCount < 5) {
if (socket.ReadLine(&response)) {
if (StringUtil::begins_with(response, wstring(L"REGISTER_PATH:"))) {
wstring responsePath = response.substr(14); // length of REGISTER_PATH
info.watchedDirectories.push_back(responsePath);
}
else if (StringUtil::begins_with(response, wstring(L"SHARE_MENU_TITLE:"))) {
info.shareMenuTitle = response.substr(17); // length of SHARE_MENU_TITLE:
break; // Stop once we received the last sent request
}
}
else {
Sleep(50);
++sleptCount;
}
}
return info;
ContextMenuInfo info;
std::wstring response;
int sleptCount = 0;
while (sleptCount < 5) {
if (socket.ReadLine(&response)) {
if (StringUtil::begins_with(response, wstring(L"REGISTER_PATH:"))) {
wstring responsePath = response.substr(14); // length of REGISTER_PATH
info.watchedDirectories.push_back(responsePath);
}
else if (StringUtil::begins_with(response, wstring(L"SHARE_MENU_TITLE:"))) {
info.shareMenuTitle = response.substr(17); // length of SHARE_MENU_TITLE:
break; // Stop once we received the last sent request
}
}
else {
Sleep(50);
++sleptCount;
}
}
return info;
}
void OCClientInterface::ShareObject(const std::wstring &path)
{
auto pipename = CommunicationSocket::DefaultPipePath();
auto pipename = CommunicationSocket::DefaultPipePath();
CommunicationSocket socket;
if (!WaitNamedPipe(pipename.data(), PIPE_TIMEOUT)) {
return;
}
if (!socket.Connect(pipename)) {
return;
}
CommunicationSocket socket;
if (!WaitNamedPipe(pipename.data(), PIPE_TIMEOUT)) {
return;
}
if (!socket.Connect(pipename)) {
return;
}
wchar_t msg[SOCK_BUFFER] = { 0 };
if (SUCCEEDED(StringCchPrintf(msg, SOCK_BUFFER, L"SHARE:%s\n", path.c_str())))
{
socket.SendMsg(msg);
}
wchar_t msg[SOCK_BUFFER] = { 0 };
if (SUCCEEDED(StringCchPrintf(msg, SOCK_BUFFER, L"SHARE:%s\n", path.c_str())))
{
socket.SendMsg(msg);
}
}
@@ -43,12 +43,12 @@ class CommunicationSocket;
class OCClientInterface
{
public:
struct ContextMenuInfo {
std::vector<std::wstring> watchedDirectories;
std::wstring shareMenuTitle;
};
static ContextMenuInfo FetchInfo();
static void ShareObject(const std::wstring &path);
struct ContextMenuInfo {
std::vector<std::wstring> watchedDirectories;
std::wstring shareMenuTitle;
};
static ContextMenuInfo FetchInfo();
static void ShareObject(const std::wstring &path);
};
#endif //ABSTRACTSOCKETHANDLER_H
@@ -30,27 +30,27 @@ extern long g_cDllRef;
OCContextMenu::OCContextMenu(void)
: m_cRef(1)
, m_pszMenuText(L"&Share")
, m_pszVerb("ocshare")
, m_pwszVerb(L"ocshare")
, m_pszVerbCanonicalName("OCShareViaOC")
, m_pwszVerbCanonicalName(L"OCShareViaOC")
, m_pszVerbHelpText("Share via ownCloud")
, m_pwszVerbHelpText(L"Share via ownCloud")
: m_cRef(1)
, m_pszMenuText(L"&Share")
, m_pszVerb("ocshare")
, m_pwszVerb(L"ocshare")
, m_pszVerbCanonicalName("OCShareViaOC")
, m_pwszVerbCanonicalName(L"OCShareViaOC")
, m_pszVerbHelpText("Share via ownCloud")
, m_pwszVerbHelpText(L"Share via ownCloud")
{
InterlockedIncrement(&g_cDllRef);
InterlockedIncrement(&g_cDllRef);
}
OCContextMenu::~OCContextMenu(void)
{
InterlockedDecrement(&g_cDllRef);
InterlockedDecrement(&g_cDllRef);
}
void OCContextMenu::OnVerbDisplayFileName(HWND hWnd)
{
OCClientInterface::ShareObject(std::wstring(m_szSelectedFile));
OCClientInterface::ShareObject(std::wstring(m_szSelectedFile));
}
@@ -59,30 +59,30 @@ void OCContextMenu::OnVerbDisplayFileName(HWND hWnd)
// Query to the interface the component supported.
IFACEMETHODIMP OCContextMenu::QueryInterface(REFIID riid, void **ppv)
{
static const QITAB qit[] =
{
QITABENT(OCContextMenu, IContextMenu),
QITABENT(OCContextMenu, IShellExtInit),
{ 0 },
};
return QISearch(this, qit, riid, ppv);
static const QITAB qit[] =
{
QITABENT(OCContextMenu, IContextMenu),
QITABENT(OCContextMenu, IShellExtInit),
{ 0 },
};
return QISearch(this, qit, riid, ppv);
}
// Increase the reference count for an interface on an object.
IFACEMETHODIMP_(ULONG) OCContextMenu::AddRef()
{
return InterlockedIncrement(&m_cRef);
return InterlockedIncrement(&m_cRef);
}
// Decrease the reference count for an interface on an object.
IFACEMETHODIMP_(ULONG) OCContextMenu::Release()
{
ULONG cRef = InterlockedDecrement(&m_cRef);
if (0 == cRef) {
delete this;
}
ULONG cRef = InterlockedDecrement(&m_cRef);
if (0 == cRef) {
delete this;
}
return cRef;
return cRef;
}
#pragma endregion
@@ -92,40 +92,40 @@ IFACEMETHODIMP_(ULONG) OCContextMenu::Release()
// Initialize the context menu handler.
IFACEMETHODIMP OCContextMenu::Initialize(
LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hKeyProgID)
LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hKeyProgID)
{
if (!pDataObj) {
return E_INVALIDARG;
}
if (!pDataObj) {
return E_INVALIDARG;
}
HRESULT hr = E_FAIL;
HRESULT hr = E_FAIL;
FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stm;
FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stm;
if (SUCCEEDED(pDataObj->GetData(&fe, &stm))) {
// Get an HDROP handle.
HDROP hDrop = static_cast<HDROP>(GlobalLock(stm.hGlobal));
if (hDrop) {
// Ignore multi-selections
UINT nFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
if (nFiles == 1) {
// Get the path of the file.
if (0 != DragQueryFile(hDrop, 0, m_szSelectedFile, ARRAYSIZE(m_szSelectedFile)))
{
hr = S_OK;
}
}
if (SUCCEEDED(pDataObj->GetData(&fe, &stm))) {
// Get an HDROP handle.
HDROP hDrop = static_cast<HDROP>(GlobalLock(stm.hGlobal));
if (hDrop) {
// Ignore multi-selections
UINT nFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
if (nFiles == 1) {
// Get the path of the file.
if (0 != DragQueryFile(hDrop, 0, m_szSelectedFile, ARRAYSIZE(m_szSelectedFile)))
{
hr = S_OK;
}
}
GlobalUnlock(stm.hGlobal);
}
GlobalUnlock(stm.hGlobal);
}
ReleaseStgMedium(&stm);
}
ReleaseStgMedium(&stm);
}
// If any value other than S_OK is returned from the method, the context
// menu item is not displayed.
return hr;
// If any value other than S_OK is returned from the method, the context
// menu item is not displayed.
return hr;
}
#pragma endregion
@@ -135,135 +135,136 @@ IFACEMETHODIMP OCContextMenu::Initialize(
void InsertSeperator(HMENU hMenu, UINT indexMenu)
{
// Add a separator.
MENUITEMINFO sep = { sizeof(sep) };
sep.fMask = MIIM_TYPE;
sep.fType = MFT_SEPARATOR;
InsertMenuItem(hMenu, indexMenu, TRUE, &sep);
// Add a separator.
MENUITEMINFO sep = { sizeof(sep) };
sep.fMask = MIIM_TYPE;
sep.fType = MFT_SEPARATOR;
InsertMenuItem(hMenu, indexMenu, TRUE, &sep);
}
IFACEMETHODIMP OCContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
// If uFlags include CMF_DEFAULTONLY then we should not do anything.
if (CMF_DEFAULTONLY & uFlags)
{
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
}
// If uFlags include CMF_DEFAULTONLY then we should not do anything.
if (CMF_DEFAULTONLY & uFlags)
{
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
}
OCClientInterface::ContextMenuInfo info = OCClientInterface::FetchInfo();
bool skip = true;
for (const std::wstring path : info.watchedDirectories) {
if (StringUtil::begins_with(std::wstring(m_szSelectedFile), path)) {
skip = false;
break;
}
}
OCClientInterface::ContextMenuInfo info = OCClientInterface::FetchInfo();
bool skip = true;
size_t selectedFileLength = wcslen(m_szSelectedFile);
for (const std::wstring path : info.watchedDirectories) {
if (StringUtil::isDescendantOf(m_szSelectedFile, selectedFileLength, path)) {
skip = false;
break;
}
}
if (skip) {
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
}
if (skip) {
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
}
InsertSeperator(hMenu, indexMenu);
indexMenu++;
InsertSeperator(hMenu, indexMenu);
indexMenu++;
assert(!info.shareMenuTitle.empty());
MENUITEMINFO mii = { sizeof(mii) };
mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_STATE;
mii.wID = idCmdFirst + IDM_SHARE;
mii.fType = MFT_STRING;
mii.dwTypeData = &info.shareMenuTitle[0];
mii.fState = MFS_ENABLED;
if (!InsertMenuItem(hMenu, indexMenu, TRUE, &mii))
{
return HRESULT_FROM_WIN32(GetLastError());
}
assert(!info.shareMenuTitle.empty());
MENUITEMINFO mii = { sizeof(mii) };
mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_STATE;
mii.wID = idCmdFirst + IDM_SHARE;
mii.fType = MFT_STRING;
mii.dwTypeData = &info.shareMenuTitle[0];
mii.fState = MFS_ENABLED;
if (!InsertMenuItem(hMenu, indexMenu, TRUE, &mii))
{
return HRESULT_FROM_WIN32(GetLastError());
}
indexMenu++;
InsertSeperator(hMenu, indexMenu);
indexMenu++;
InsertSeperator(hMenu, indexMenu);
// Return an HRESULT value with the severity set to SEVERITY_SUCCESS.
// Set the code value to the offset of the largest command identifier
// that was assigned, plus one (1).
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(IDM_SHARE + 1));
// Return an HRESULT value with the severity set to SEVERITY_SUCCESS.
// Set the code value to the offset of the largest command identifier
// that was assigned, plus one (1).
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(IDM_SHARE + 1));
}
IFACEMETHODIMP OCContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
{
// For the Unicode case, if the high-order word is not zero, the
// command's verb string is in lpcmi->lpVerbW.
if (HIWORD(((CMINVOKECOMMANDINFOEX*)pici)->lpVerbW))
{
// Is the verb supported by this context menu extension?
if (StrCmpIW(((CMINVOKECOMMANDINFOEX*)pici)->lpVerbW, m_pwszVerb) == 0)
{
OnVerbDisplayFileName(pici->hwnd);
}
else
{
// If the verb is not recognized by the context menu handler, it
// must return E_FAIL to allow it to be passed on to the other
// context menu handlers that might implement that verb.
return E_FAIL;
}
}
// For the Unicode case, if the high-order word is not zero, the
// command's verb string is in lpcmi->lpVerbW.
if (HIWORD(((CMINVOKECOMMANDINFOEX*)pici)->lpVerbW))
{
// Is the verb supported by this context menu extension?
if (StrCmpIW(((CMINVOKECOMMANDINFOEX*)pici)->lpVerbW, m_pwszVerb) == 0)
{
OnVerbDisplayFileName(pici->hwnd);
}
else
{
// If the verb is not recognized by the context menu handler, it
// must return E_FAIL to allow it to be passed on to the other
// context menu handlers that might implement that verb.
return E_FAIL;
}
}
// If the command cannot be identified through the verb string, then
// check the identifier offset.
else
{
// Is the command identifier offset supported by this context menu
// extension?
if (LOWORD(pici->lpVerb) == IDM_SHARE)
{
OnVerbDisplayFileName(pici->hwnd);
}
else
{
// If the verb is not recognized by the context menu handler, it
// must return E_FAIL to allow it to be passed on to the other
// context menu handlers that might implement that verb.
return E_FAIL;
}
}
// If the command cannot be identified through the verb string, then
// check the identifier offset.
else
{
// Is the command identifier offset supported by this context menu
// extension?
if (LOWORD(pici->lpVerb) == IDM_SHARE)
{
OnVerbDisplayFileName(pici->hwnd);
}
else
{
// If the verb is not recognized by the context menu handler, it
// must return E_FAIL to allow it to be passed on to the other
// context menu handlers that might implement that verb.
return E_FAIL;
}
}
return S_OK;
return S_OK;
}
IFACEMETHODIMP OCContextMenu::GetCommandString(UINT_PTR idCommand,
UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax)
UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax)
{
HRESULT hr = E_INVALIDARG;
HRESULT hr = E_INVALIDARG;
if (idCommand == IDM_SHARE)
{
switch (uFlags)
{
case GCS_HELPTEXTW:
// Only useful for pre-Vista versions of Windows that have a
// Status bar.
hr = StringCchCopy(reinterpret_cast<PWSTR>(pszName), cchMax,
m_pwszVerbHelpText);
break;
if (idCommand == IDM_SHARE)
{
switch (uFlags)
{
case GCS_HELPTEXTW:
// Only useful for pre-Vista versions of Windows that have a
// Status bar.
hr = StringCchCopy(reinterpret_cast<PWSTR>(pszName), cchMax,
m_pwszVerbHelpText);
break;
case GCS_VERBW:
// GCS_VERBW is an optional feature that enables a caller to
// discover the canonical name for the verb passed in through
// idCommand.
hr = StringCchCopy(reinterpret_cast<PWSTR>(pszName), cchMax,
m_pwszVerbCanonicalName);
break;
case GCS_VERBW:
// GCS_VERBW is an optional feature that enables a caller to
// discover the canonical name for the verb passed in through
// idCommand.
hr = StringCchCopy(reinterpret_cast<PWSTR>(pszName), cchMax,
m_pwszVerbCanonicalName);
break;
default:
hr = S_OK;
}
}
default:
hr = S_OK;
}
}
// If the command (idCommand) is not supported by this context menu
// extension handler, return E_INVALIDARG.
// If the command (idCommand) is not supported by this context menu
// extension handler, return E_INVALIDARG.
return hr;
return hr;
}
#pragma endregion
@@ -26,12 +26,12 @@ extern long g_cDllRef;
OCContextMenuFactory::OCContextMenuFactory() : m_cRef(1)
{
InterlockedIncrement(&g_cDllRef);
InterlockedIncrement(&g_cDllRef);
}
OCContextMenuFactory::~OCContextMenuFactory()
{
InterlockedDecrement(&g_cDllRef);
InterlockedDecrement(&g_cDllRef);
}
@@ -39,22 +39,22 @@ OCContextMenuFactory::~OCContextMenuFactory()
IFACEMETHODIMP OCContextMenuFactory::QueryInterface(REFIID riid, void **ppv)
{
static const QITAB qit[] = { QITABENT(OCContextMenuFactory, IClassFactory), { 0 }, };
return QISearch(this, qit, riid, ppv);
static const QITAB qit[] = { QITABENT(OCContextMenuFactory, IClassFactory), { 0 }, };
return QISearch(this, qit, riid, ppv);
}
IFACEMETHODIMP_(ULONG) OCContextMenuFactory::AddRef()
{
return InterlockedIncrement(&m_cRef);
return InterlockedIncrement(&m_cRef);
}
IFACEMETHODIMP_(ULONG) OCContextMenuFactory::Release()
{
ULONG cRef = InterlockedDecrement(&m_cRef);
if (0 == cRef) {
delete this;
}
return cRef;
ULONG cRef = InterlockedDecrement(&m_cRef);
if (0 == cRef) {
delete this;
}
return cRef;
}
@@ -62,30 +62,30 @@ IFACEMETHODIMP_(ULONG) OCContextMenuFactory::Release()
IFACEMETHODIMP OCContextMenuFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv)
{
HRESULT hr = CLASS_E_NOAGGREGATION;
HRESULT hr = CLASS_E_NOAGGREGATION;
// pUnkOuter is used for aggregation. We do not support it in the sample.
if (pUnkOuter == NULL) {
hr = E_OUTOFMEMORY;
// pUnkOuter is used for aggregation. We do not support it in the sample.
if (pUnkOuter == NULL) {
hr = E_OUTOFMEMORY;
// Create the COM component.
OCContextMenu *pExt = new (std::nothrow) OCContextMenu();
if (pExt) {
// Query the specified interface.
hr = pExt->QueryInterface(riid, ppv);
pExt->Release();
}
}
// Create the COM component.
OCContextMenu *pExt = new (std::nothrow) OCContextMenu();
if (pExt) {
// Query the specified interface.
hr = pExt->QueryInterface(riid, ppv);
pExt->Release();
}
}
return hr;
return hr;
}
IFACEMETHODIMP OCContextMenuFactory::LockServer(BOOL fLock)
{
if (fLock) {
InterlockedIncrement(&g_cDllRef);
} else {
InterlockedDecrement(&g_cDllRef);
}
return S_OK;
if (fLock) {
InterlockedIncrement(&g_cDllRef);
} else {
InterlockedDecrement(&g_cDllRef);
}
return S_OK;
}
@@ -23,20 +23,20 @@
class OCContextMenuFactory : public IClassFactory
{
public:
// IUnknown
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv);
IFACEMETHODIMP_(ULONG) AddRef();
IFACEMETHODIMP_(ULONG) Release();
// IUnknown
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv);
IFACEMETHODIMP_(ULONG) AddRef();
IFACEMETHODIMP_(ULONG) Release();
// IClassFactory
IFACEMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv);
IFACEMETHODIMP LockServer(BOOL fLock);
// IClassFactory
IFACEMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv);
IFACEMETHODIMP LockServer(BOOL fLock);
OCContextMenuFactory();
OCContextMenuFactory();
private:
~OCContextMenuFactory();
long m_cRef;
~OCContextMenuFactory();
long m_cRef;
};
#endif //OCCONTEXTMENUFACTORY_H
@@ -23,196 +23,196 @@ namespace {
HRESULT SetHKCRRegistryKeyAndValue(PCWSTR pszSubKey, PCWSTR pszValueName, PCWSTR pszData)
{
HRESULT hr;
HKEY hKey = NULL;
HRESULT hr;
HKEY hKey = NULL;
// Creates the specified registry key. If the key already exists, the
// function opens it.
hr = HRESULT_FROM_WIN32(RegCreateKeyEx(HKEY_CLASSES_ROOT, pszSubKey, 0,
NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL));
// Creates the specified registry key. If the key already exists, the
// function opens it.
hr = HRESULT_FROM_WIN32(RegCreateKeyEx(HKEY_CLASSES_ROOT, pszSubKey, 0,
NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL));
if (SUCCEEDED(hr))
{
if (pszData != NULL)
{
// Set the specified value of the key.
DWORD cbData = lstrlen(pszData) * sizeof(*pszData);
hr = HRESULT_FROM_WIN32(RegSetValueEx(hKey, pszValueName, 0,
REG_SZ, reinterpret_cast<const BYTE *>(pszData), cbData));
}
if (SUCCEEDED(hr))
{
if (pszData != NULL)
{
// Set the specified value of the key.
DWORD cbData = lstrlen(pszData) * sizeof(*pszData);
hr = HRESULT_FROM_WIN32(RegSetValueEx(hKey, pszValueName, 0,
REG_SZ, reinterpret_cast<const BYTE *>(pszData), cbData));
}
RegCloseKey(hKey);
}
RegCloseKey(hKey);
}
return hr;
return hr;
}
HRESULT GetHKCRRegistryKeyAndValue(PCWSTR pszSubKey, PCWSTR pszValueName, PWSTR pszData, DWORD cbData)
{
HRESULT hr;
HKEY hKey = NULL;
HRESULT hr;
HKEY hKey = NULL;
// Try to open the specified registry key.
hr = HRESULT_FROM_WIN32(RegOpenKeyEx(HKEY_CLASSES_ROOT, pszSubKey, 0,
KEY_READ, &hKey));
// Try to open the specified registry key.
hr = HRESULT_FROM_WIN32(RegOpenKeyEx(HKEY_CLASSES_ROOT, pszSubKey, 0,
KEY_READ, &hKey));
if (SUCCEEDED(hr))
{
// Get the data for the specified value name.
hr = HRESULT_FROM_WIN32(RegQueryValueEx(hKey, pszValueName, NULL,
NULL, reinterpret_cast<LPBYTE>(pszData), &cbData));
if (SUCCEEDED(hr))
{
// Get the data for the specified value name.
hr = HRESULT_FROM_WIN32(RegQueryValueEx(hKey, pszValueName, NULL,
NULL, reinterpret_cast<LPBYTE>(pszData), &cbData));
RegCloseKey(hKey);
}
RegCloseKey(hKey);
}
return hr;
return hr;
}
}
HRESULT OCContextMenuRegHandler::RegisterInprocServer(PCWSTR pszModule, const CLSID& clsid, PCWSTR pszFriendlyName, PCWSTR pszThreadModel)
{
if (pszModule == NULL || pszThreadModel == NULL)
{
return E_INVALIDARG;
}
if (pszModule == NULL || pszThreadModel == NULL)
{
return E_INVALIDARG;
}
HRESULT hr;
HRESULT hr;
wchar_t szCLSID[MAX_PATH];
StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
wchar_t szCLSID[MAX_PATH];
StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
wchar_t szSubkey[MAX_PATH];
wchar_t szSubkey[MAX_PATH];
// Create the HKCR\CLSID\{<CLSID>} key.
hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey), L"CLSID\\%s", szCLSID);
if (SUCCEEDED(hr))
{
hr = SetHKCRRegistryKeyAndValue(szSubkey, NULL, pszFriendlyName);
// Create the HKCR\CLSID\{<CLSID>} key.
hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey), L"CLSID\\%s", szCLSID);
if (SUCCEEDED(hr))
{
hr = SetHKCRRegistryKeyAndValue(szSubkey, NULL, pszFriendlyName);
// Create the HKCR\CLSID\{<CLSID>}\InprocServer32 key.
if (SUCCEEDED(hr))
{
hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
L"CLSID\\%s\\InprocServer32", szCLSID);
if (SUCCEEDED(hr))
{
// Set the default value of the InprocServer32 key to the
// path of the COM module.
hr = SetHKCRRegistryKeyAndValue(szSubkey, NULL, pszModule);
if (SUCCEEDED(hr))
{
// Set the threading model of the component.
hr = SetHKCRRegistryKeyAndValue(szSubkey,
L"ThreadingModel", pszThreadModel);
}
}
}
}
// Create the HKCR\CLSID\{<CLSID>}\InprocServer32 key.
if (SUCCEEDED(hr))
{
hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
L"CLSID\\%s\\InprocServer32", szCLSID);
if (SUCCEEDED(hr))
{
// Set the default value of the InprocServer32 key to the
// path of the COM module.
hr = SetHKCRRegistryKeyAndValue(szSubkey, NULL, pszModule);
if (SUCCEEDED(hr))
{
// Set the threading model of the component.
hr = SetHKCRRegistryKeyAndValue(szSubkey,
L"ThreadingModel", pszThreadModel);
}
}
}
}
return hr;
return hr;
}
HRESULT OCContextMenuRegHandler::UnregisterInprocServer(const CLSID& clsid)
{
HRESULT hr = S_OK;
HRESULT hr = S_OK;
wchar_t szCLSID[MAX_PATH];
StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
wchar_t szCLSID[MAX_PATH];
StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
wchar_t szSubkey[MAX_PATH];
wchar_t szSubkey[MAX_PATH];
// Delete the HKCR\CLSID\{<CLSID>} key.
hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey), L"CLSID\\%s", szCLSID);
if (SUCCEEDED(hr))
{
hr = HRESULT_FROM_WIN32(RegDelnode(HKEY_CLASSES_ROOT, szSubkey));
}
// Delete the HKCR\CLSID\{<CLSID>} key.
hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey), L"CLSID\\%s", szCLSID);
if (SUCCEEDED(hr))
{
hr = HRESULT_FROM_WIN32(RegDelnode(HKEY_CLASSES_ROOT, szSubkey));
}
return hr;
return hr;
}
HRESULT OCContextMenuRegHandler::RegisterShellExtContextMenuHandler(
PCWSTR pszFileType, const CLSID& clsid, PCWSTR pszFriendlyName)
PCWSTR pszFileType, const CLSID& clsid, PCWSTR pszFriendlyName)
{
if (pszFileType == NULL)
{
return E_INVALIDARG;
}
if (pszFileType == NULL)
{
return E_INVALIDARG;
}
HRESULT hr;
HRESULT hr;
wchar_t szCLSID[MAX_PATH];
StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
wchar_t szCLSID[MAX_PATH];
StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
wchar_t szSubkey[MAX_PATH];
wchar_t szSubkey[MAX_PATH];
// If pszFileType starts with '.', try to read the default value of the
// HKCR\<File Type> key which contains the ProgID to which the file type
// is linked.
if (*pszFileType == L'.')
{
wchar_t szDefaultVal[260];
hr = GetHKCRRegistryKeyAndValue(pszFileType, NULL, szDefaultVal,
sizeof(szDefaultVal));
// If pszFileType starts with '.', try to read the default value of the
// HKCR\<File Type> key which contains the ProgID to which the file type
// is linked.
if (*pszFileType == L'.')
{
wchar_t szDefaultVal[260];
hr = GetHKCRRegistryKeyAndValue(pszFileType, NULL, szDefaultVal,
sizeof(szDefaultVal));
// If the key exists and its default value is not empty, use the
// ProgID as the file type.
if (SUCCEEDED(hr) && szDefaultVal[0] != L'\0')
{
pszFileType = szDefaultVal;
}
}
// If the key exists and its default value is not empty, use the
// ProgID as the file type.
if (SUCCEEDED(hr) && szDefaultVal[0] != L'\0')
{
pszFileType = szDefaultVal;
}
}
// Create the key HKCR\<File Type>\shellex\ContextMenuHandlers\{friendlyName>}
hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
L"%s\\shellex\\ContextMenuHandlers\\%s", pszFileType, pszFriendlyName);
if (SUCCEEDED(hr))
{
// Set the default value of the key.
hr = SetHKCRRegistryKeyAndValue(szSubkey, NULL, szCLSID);
}
// Create the key HKCR\<File Type>\shellex\ContextMenuHandlers\{friendlyName>}
hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
L"%s\\shellex\\ContextMenuHandlers\\%s", pszFileType, pszFriendlyName);
if (SUCCEEDED(hr))
{
// Set the default value of the key.
hr = SetHKCRRegistryKeyAndValue(szSubkey, NULL, szCLSID);
}
return hr;
return hr;
}
HRESULT OCContextMenuRegHandler::UnregisterShellExtContextMenuHandler(
PCWSTR pszFileType, PCWSTR pszFriendlyName)
PCWSTR pszFileType, PCWSTR pszFriendlyName)
{
if (pszFileType == NULL)
{
return E_INVALIDARG;
}
if (pszFileType == NULL)
{
return E_INVALIDARG;
}
HRESULT hr;
wchar_t szSubkey[MAX_PATH];
HRESULT hr;
wchar_t szSubkey[MAX_PATH];
// If pszFileType starts with '.', try to read the default value of the
// HKCR\<File Type> key which contains the ProgID to which the file type
// is linked.
if (*pszFileType == L'.')
{
wchar_t szDefaultVal[260];
hr = GetHKCRRegistryKeyAndValue(pszFileType, NULL, szDefaultVal,
sizeof(szDefaultVal));
// If pszFileType starts with '.', try to read the default value of the
// HKCR\<File Type> key which contains the ProgID to which the file type
// is linked.
if (*pszFileType == L'.')
{
wchar_t szDefaultVal[260];
hr = GetHKCRRegistryKeyAndValue(pszFileType, NULL, szDefaultVal,
sizeof(szDefaultVal));
// If the key exists and its default value is not empty, use the
// ProgID as the file type.
if (SUCCEEDED(hr) && szDefaultVal[0] != L'\0')
{
pszFileType = szDefaultVal;
}
}
// If the key exists and its default value is not empty, use the
// ProgID as the file type.
if (SUCCEEDED(hr) && szDefaultVal[0] != L'\0')
{
pszFileType = szDefaultVal;
}
}
// Remove the HKCR\<File Type>\shellex\ContextMenuHandlers\{friendlyName} key.
hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
L"%s\\shellex\\ContextMenuHandlers\\%s", pszFileType, pszFriendlyName);
if (SUCCEEDED(hr))
{
hr = HRESULT_FROM_WIN32(RegDelnode(HKEY_CLASSES_ROOT, szSubkey));
}
// Remove the HKCR\<File Type>\shellex\ContextMenuHandlers\{friendlyName} key.
hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
L"%s\\shellex\\ContextMenuHandlers\\%s", pszFileType, pszFriendlyName);
if (SUCCEEDED(hr))
{
hr = HRESULT_FROM_WIN32(RegDelnode(HKEY_CLASSES_ROOT, szSubkey));
}
return hr;
return hr;
}
@@ -23,16 +23,16 @@
class __declspec(dllexport) OCContextMenuRegHandler
{
public:
static HRESULT MakeRegistryEntries(const CLSID& clsid, PCWSTR fileType);
static HRESULT RegisterCOMObject(PCWSTR modulePath, PCWSTR friendlyName, const CLSID& clsid);
static HRESULT RemoveRegistryEntries(PCWSTR friendlyName);
static HRESULT UnregisterCOMObject(const CLSID& clsid);
static HRESULT MakeRegistryEntries(const CLSID& clsid, PCWSTR fileType);
static HRESULT RegisterCOMObject(PCWSTR modulePath, PCWSTR friendlyName, const CLSID& clsid);
static HRESULT RemoveRegistryEntries(PCWSTR friendlyName);
static HRESULT UnregisterCOMObject(const CLSID& clsid);
static HRESULT RegisterInprocServer(PCWSTR pszModule, const CLSID& clsid, PCWSTR pszFriendlyName, PCWSTR pszThreadModel);
static HRESULT UnregisterInprocServer(const CLSID& clsid);
static HRESULT RegisterInprocServer(PCWSTR pszModule, const CLSID& clsid, PCWSTR pszFriendlyName, PCWSTR pszThreadModel);
static HRESULT UnregisterInprocServer(const CLSID& clsid);
static HRESULT RegisterShellExtContextMenuHandler(PCWSTR pszFileType, const CLSID& clsid, PCWSTR pszFriendlyName);
static HRESULT UnregisterShellExtContextMenuHandler(PCWSTR pszFileType, PCWSTR pszFriendlyName);
static HRESULT RegisterShellExtContextMenuHandler(PCWSTR pszFileType, const CLSID& clsid, PCWSTR pszFriendlyName);
static HRESULT UnregisterShellExtContextMenuHandler(PCWSTR pszFileType, PCWSTR pszFriendlyName);
};
#endif //OCCONTEXTMENUREGHANDLER_H
+94 -94
Ver Arquivo
@@ -23,142 +23,142 @@ long dllReferenceCount = 0;
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
instanceHandle = hModule;
DisableThreadLibraryCalls(hModule);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
instanceHandle = hModule;
DisableThreadLibraryCalls(hModule);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
return TRUE;
}
HRESULT CreateFactory(REFIID riid, void **ppv, int state)
{
HRESULT hResult = E_OUTOFMEMORY;
HRESULT hResult = E_OUTOFMEMORY;
OCOverlayFactory* ocOverlayFactory = new OCOverlayFactory(state);
OCOverlayFactory* ocOverlayFactory = new OCOverlayFactory(state);
if (ocOverlayFactory) {
hResult = ocOverlayFactory->QueryInterface(riid, ppv);
ocOverlayFactory->Release();
}
return hResult;
if (ocOverlayFactory) {
hResult = ocOverlayFactory->QueryInterface(riid, ppv);
ocOverlayFactory->Release();
}
return hResult;
}
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
{
HRESULT hResult = CLASS_E_CLASSNOTAVAILABLE;
GUID guid;
GUID guid;
hResult = CLSIDFromString(OVERLAY_GUID_ERROR, (LPCLSID)&guid);
if (!SUCCEEDED(hResult)) { return hResult; }
if (IsEqualCLSID(guid, rclsid)) { return CreateFactory(riid, ppv, State_Error); }
hResult = CLSIDFromString(OVERLAY_GUID_ERROR, (LPCLSID)&guid);
if (!SUCCEEDED(hResult)) { return hResult; }
if (IsEqualCLSID(guid, rclsid)) { return CreateFactory(riid, ppv, State_Error); }
hResult = CLSIDFromString(OVERLAY_GUID_OK, (LPCLSID)&guid);
if (!SUCCEEDED(hResult)) { return hResult; }
if (IsEqualCLSID(guid, rclsid)) { return CreateFactory(riid, ppv, State_OK); }
hResult = CLSIDFromString(OVERLAY_GUID_OK, (LPCLSID)&guid);
if (!SUCCEEDED(hResult)) { return hResult; }
if (IsEqualCLSID(guid, rclsid)) { return CreateFactory(riid, ppv, State_OK); }
hResult = CLSIDFromString(OVERLAY_GUID_OK_SHARED, (LPCLSID)&guid);
if (!SUCCEEDED(hResult)) { return hResult; }
if (IsEqualCLSID(guid, rclsid)) { return CreateFactory(riid, ppv, State_OKShared); }
hResult = CLSIDFromString(OVERLAY_GUID_OK_SHARED, (LPCLSID)&guid);
if (!SUCCEEDED(hResult)) { return hResult; }
if (IsEqualCLSID(guid, rclsid)) { return CreateFactory(riid, ppv, State_OKShared); }
hResult = CLSIDFromString(OVERLAY_GUID_SYNC, (LPCLSID)&guid);
if (!SUCCEEDED(hResult)) { return hResult; }
if (IsEqualCLSID(guid, rclsid)) { return CreateFactory(riid, ppv, State_Sync); }
hResult = CLSIDFromString(OVERLAY_GUID_SYNC, (LPCLSID)&guid);
if (!SUCCEEDED(hResult)) { return hResult; }
if (IsEqualCLSID(guid, rclsid)) { return CreateFactory(riid, ppv, State_Sync); }
hResult = CLSIDFromString(OVERLAY_GUID_WARNING, (LPCLSID)&guid);
if (!SUCCEEDED(hResult)) { return hResult; }
if (IsEqualCLSID(guid, rclsid)) { return CreateFactory(riid, ppv, State_Warning); }
hResult = CLSIDFromString(OVERLAY_GUID_WARNING, (LPCLSID)&guid);
if (!SUCCEEDED(hResult)) { return hResult; }
if (IsEqualCLSID(guid, rclsid)) { return CreateFactory(riid, ppv, State_Warning); }
return CLASS_E_CLASSNOTAVAILABLE;
return CLASS_E_CLASSNOTAVAILABLE;
}
STDAPI DllCanUnloadNow(void)
{
return dllReferenceCount > 0 ? S_FALSE : S_OK;
return S_FALSE;
return S_FALSE;
}
HRESULT RegisterCLSID(LPCOLESTR guidStr, PCWSTR overlayStr, PCWSTR szModule)
{
HRESULT hResult = S_OK;
HRESULT hResult = S_OK;
GUID guid;
hResult = CLSIDFromString(guidStr, (LPCLSID)&guid);
GUID guid;
hResult = CLSIDFromString(guidStr, (LPCLSID)&guid);
if (hResult != S_OK) {
return hResult;
}
if (hResult != S_OK) {
return hResult;
}
hResult = OCOverlayRegistrationHandler::RegisterCOMObject(szModule, OVERLAY_GENERIC_NAME, guid);
hResult = OCOverlayRegistrationHandler::RegisterCOMObject(szModule, OVERLAY_GENERIC_NAME, guid);
if (!SUCCEEDED(hResult)) {
return hResult;
}
if (!SUCCEEDED(hResult)) {
return hResult;
}
hResult = OCOverlayRegistrationHandler::MakeRegistryEntries(guid, overlayStr);
hResult = OCOverlayRegistrationHandler::MakeRegistryEntries(guid, overlayStr);
return hResult;
return hResult;
}
HRESULT UnregisterCLSID(LPCOLESTR guidStr, PCWSTR overlayStr)
{
HRESULT hResult = S_OK;
GUID guid;
HRESULT hResult = S_OK;
GUID guid;
hResult = CLSIDFromString(guidStr, (LPCLSID)&guid);
hResult = CLSIDFromString(guidStr, (LPCLSID)&guid);
if (hResult != S_OK) {
return hResult;
}
if (hResult != S_OK) {
return hResult;
}
hResult = OCOverlayRegistrationHandler::UnregisterCOMObject(guid);
hResult = OCOverlayRegistrationHandler::UnregisterCOMObject(guid);
if (!SUCCEEDED(hResult)) {
return hResult;
}
if (!SUCCEEDED(hResult)) {
return hResult;
}
hResult = OCOverlayRegistrationHandler::RemoveRegistryEntries(overlayStr);
hResult = OCOverlayRegistrationHandler::RemoveRegistryEntries(overlayStr);
return hResult;
return hResult;
}
HRESULT _stdcall DllRegisterServer(void)
{
HRESULT hResult = S_OK;
HRESULT hResult = S_OK;
wchar_t szModule[MAX_PATH];
wchar_t szModule[MAX_PATH];
if (GetModuleFileName(instanceHandle, szModule, ARRAYSIZE(szModule)) == 0) {
hResult = HRESULT_FROM_WIN32(GetLastError());
return hResult;
}
if (GetModuleFileName(instanceHandle, szModule, ARRAYSIZE(szModule)) == 0) {
hResult = HRESULT_FROM_WIN32(GetLastError());
return hResult;
}
// Unregister any obsolete CLSID when we register here
// Those CLSID were removed in 2.1, but we need to make sure to prevent any previous version
// of the extension on the system from loading at the same time as a new version to avoid crashing explorer.
UnregisterCLSID(OVERLAY_GUID_ERROR_SHARED, OVERLAY_NAME_ERROR_SHARED);
UnregisterCLSID(OVERLAY_GUID_SYNC_SHARED, OVERLAY_NAME_SYNC_SHARED);
UnregisterCLSID(OVERLAY_GUID_WARNING_SHARED, OVERLAY_NAME_WARNING_SHARED);
// Unregister any obsolete CLSID when we register here
// Those CLSID were removed in 2.1, but we need to make sure to prevent any previous version
// of the extension on the system from loading at the same time as a new version to avoid crashing explorer.
UnregisterCLSID(OVERLAY_GUID_ERROR_SHARED, OVERLAY_NAME_ERROR_SHARED);
UnregisterCLSID(OVERLAY_GUID_SYNC_SHARED, OVERLAY_NAME_SYNC_SHARED);
UnregisterCLSID(OVERLAY_GUID_WARNING_SHARED, OVERLAY_NAME_WARNING_SHARED);
hResult = RegisterCLSID(OVERLAY_GUID_ERROR, OVERLAY_NAME_ERROR, szModule);
if (!SUCCEEDED(hResult)) { return hResult; }
hResult = RegisterCLSID(OVERLAY_GUID_OK, OVERLAY_NAME_OK, szModule);
if (!SUCCEEDED(hResult)) { return hResult; }
hResult = RegisterCLSID(OVERLAY_GUID_OK_SHARED, OVERLAY_NAME_OK_SHARED, szModule);
if (!SUCCEEDED(hResult)) { return hResult; }
hResult = RegisterCLSID(OVERLAY_GUID_SYNC, OVERLAY_NAME_SYNC, szModule);
if (!SUCCEEDED(hResult)) { return hResult; }
hResult = RegisterCLSID(OVERLAY_GUID_WARNING, OVERLAY_NAME_WARNING, szModule);
hResult = RegisterCLSID(OVERLAY_GUID_ERROR, OVERLAY_NAME_ERROR, szModule);
if (!SUCCEEDED(hResult)) { return hResult; }
hResult = RegisterCLSID(OVERLAY_GUID_OK, OVERLAY_NAME_OK, szModule);
if (!SUCCEEDED(hResult)) { return hResult; }
hResult = RegisterCLSID(OVERLAY_GUID_OK_SHARED, OVERLAY_NAME_OK_SHARED, szModule);
if (!SUCCEEDED(hResult)) { return hResult; }
hResult = RegisterCLSID(OVERLAY_GUID_SYNC, OVERLAY_NAME_SYNC, szModule);
if (!SUCCEEDED(hResult)) { return hResult; }
hResult = RegisterCLSID(OVERLAY_GUID_WARNING, OVERLAY_NAME_WARNING, szModule);
return hResult;
return hResult;
}
STDAPI DllUnregisterServer(void)
@@ -167,21 +167,21 @@ STDAPI DllUnregisterServer(void)
wchar_t szModule[MAX_PATH];
if (GetModuleFileNameW(instanceHandle, szModule, ARRAYSIZE(szModule)) == 0)
if (GetModuleFileNameW(instanceHandle, szModule, ARRAYSIZE(szModule)) == 0)
{
hResult = HRESULT_FROM_WIN32(GetLastError());
return hResult;
}
hResult = UnregisterCLSID(OVERLAY_GUID_ERROR, OVERLAY_NAME_ERROR);
if (!SUCCEEDED(hResult)) { return hResult; }
hResult = UnregisterCLSID(OVERLAY_GUID_OK, OVERLAY_NAME_OK);
if (!SUCCEEDED(hResult)) { return hResult; }
hResult = UnregisterCLSID(OVERLAY_GUID_OK_SHARED, OVERLAY_NAME_OK_SHARED);
if (!SUCCEEDED(hResult)) { return hResult; }
hResult = UnregisterCLSID(OVERLAY_GUID_SYNC, OVERLAY_NAME_SYNC);
if (!SUCCEEDED(hResult)) { return hResult; }
hResult = UnregisterCLSID(OVERLAY_GUID_WARNING, OVERLAY_NAME_WARNING);
hResult = UnregisterCLSID(OVERLAY_GUID_ERROR, OVERLAY_NAME_ERROR);
if (!SUCCEEDED(hResult)) { return hResult; }
hResult = UnregisterCLSID(OVERLAY_GUID_OK, OVERLAY_NAME_OK);
if (!SUCCEEDED(hResult)) { return hResult; }
hResult = UnregisterCLSID(OVERLAY_GUID_OK_SHARED, OVERLAY_NAME_OK_SHARED);
if (!SUCCEEDED(hResult)) { return hResult; }
hResult = UnregisterCLSID(OVERLAY_GUID_SYNC, OVERLAY_NAME_SYNC);
if (!SUCCEEDED(hResult)) { return hResult; }
hResult = UnregisterCLSID(OVERLAY_GUID_WARNING, OVERLAY_NAME_WARNING);
return hResult;
}
@@ -1,131 +0,0 @@
/**
* Copyright (c) 2015 Daniel Molkentin <danimo@owncloud.com>. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
#include "OCContextMenu.h"
#include "stdafx.h"
#define IDM_SHARE 0
OCContextMenu::OCContextMenu()
: m_pwszVerb(0)
, m_referenceCount(0)
{
}
OCContextMenu::~OCContextMenu()
{
}
IFACEMETHODIMP_(ULONG) OCContextMenu::AddRef()
{
return InterlockedIncrement(&m_referenceCount);
}
IFACEMETHODIMP_(ULONG) OCContextMenu::Release()
{
ULONG cRef = InterlockedDecrement(&m_referenceCount);
if (0 == cRef)
{
delete this;
}
return cRef;
}
IFACEMETHODIMP OCContextMenu::QueryInterface(REFIID riid, void **ppv)
{
HRESULT hr = S_OK;
if (IsEqualIID(IID_IUnknown, riid) || IsEqualIID(IID_IContextMenu, riid))
{
*ppv = static_cast<IContextMenu *>(this);
}
else
{
hr = E_NOINTERFACE;
*ppv = NULL;
}
if (*ppv)
{
AddRef();
}
return hr;
}
IFACEMETHODIMP OCContextMenu::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax)
{
HRESULT hr = E_INVALIDARG;
if (idCmd == IDM_SHARE)
{
switch (uFlags)
{
case GCS_HELPTEXTW:
hr = StringCchCopyW(reinterpret_cast<PWSTR>(pszName), cchMax, L"Shares file or directory with ownCloud");
break;
case GCS_VERBW:
// GCS_VERBW is an optional feature that enables a caller
// to discover the canonical name for the verb that is passed in
// through idCommand.
hr = StringCchCopyW(reinterpret_cast<PWSTR>(pszName), cchMax, L"ownCloudShare");
break;
}
}
return hr;
}
IFACEMETHODIMP OCContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
{
if (pici->cbSize == sizeof(CMINVOKECOMMANDINFOEX) &&
(pici->fMask & CMIC_MASK_UNICODE))
{
return E_FAIL;
}
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
if (HIWORD(((CMINVOKECOMMANDINFOEX *)pici)->lpVerbW))
{
if (StrCmpIW(((CMINVOKECOMMANDINFOEX *)pici)->lpVerbW, m_pwszVerb))
{
return E_FAIL;
}
}
if (LOWORD(pici->lpVerb) != IDM_SHARE) {
return E_FAIL;
}
MessageBox(pici->hwnd,
L"ownCloud was here",
L"ownCloud was here",
MB_OK | MB_ICONINFORMATION);
}
IFACEMETHODIMP OCContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
HRESULT hr;
if (!(CMF_DEFAULTONLY & uFlags))
{
InsertMenu(hMenu, indexMenu, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SHARE, L"&Share with ownCloud");
}
hr = StringCbCopyW(m_pwszVerb, sizeof(m_pwszVerb), L"ownCloudShare");
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(IDM_SHARE + 1));
}
@@ -1,43 +0,0 @@
/**
* Copyright (c) 2015 Daniel Molkentin <danimo@owncloud.com>. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
#ifndef OCCONTEXTMENU_H
#define OCCONTEXTMENU_H
#pragma once
#include "ShObjIdl.h"
#include "memory"
class OCContextMenu :public IContextMenu
{
public:
OCContextMenu();
~OCContextMenu();
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv);
IFACEMETHODIMP_(ULONG) AddRef();
IFACEMETHODIMP_(ULONG) Release();
IFACEMETHODIMP GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax);
IFACEMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO pici);
IFACEMETHODIMP QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
private:
TCHAR* m_pwszVerb;
long m_referenceCount;
};
#endif //OCCONTEXTMENU_H
+57 -72
Ver Arquivo
@@ -45,19 +45,19 @@ unique_ptr<RemotePathChecker> s_instance;
RemotePathChecker *getGlobalChecker()
{
// On Vista we'll run into issue #2680 if we try to create the thread+pipe connection
// on any DllGetClassObject of our registered classes.
// Work around the issue by creating the static RemotePathChecker only once actually needed.
static once_flag s_onceFlag;
call_once(s_onceFlag, [] { s_instance.reset(new RemotePathChecker); });
// On Vista we'll run into issue #2680 if we try to create the thread+pipe connection
// on any DllGetClassObject of our registered classes.
// Work around the issue by creating the static RemotePathChecker only once actually needed.
static once_flag s_onceFlag;
call_once(s_onceFlag, [] { s_instance.reset(new RemotePathChecker); });
return s_instance.get();
return s_instance.get();
}
}
OCOverlay::OCOverlay(int state)
: _referenceCount(1)
, _state(state)
: _referenceCount(1)
, _state(state)
{
}
@@ -89,7 +89,7 @@ IFACEMETHODIMP OCOverlay::QueryInterface(REFIID riid, void **ppv)
{
AddRef();
}
return hr;
}
@@ -106,80 +106,65 @@ IFACEMETHODIMP_(ULONG) OCOverlay::Release()
IFACEMETHODIMP OCOverlay::GetPriority(int *pPriority)
{
// this defines which handler has prededence, so
// we order this in terms of likelyhood
switch (_state) {
case State_OK:
*pPriority = 0; break;
case State_OKShared:
*pPriority = 1; break;
case State_Warning:
*pPriority = 2; break;
case State_Sync:
*pPriority = 3; break;
case State_Error:
*pPriority = 4; break;
default:
*pPriority = 5; break;
}
// this defines which handler has prededence, so
// we order this in terms of likelyhood
switch (_state) {
case State_OK:
*pPriority = 0; break;
case State_OKShared:
*pPriority = 1; break;
case State_Warning:
*pPriority = 2; break;
case State_Sync:
*pPriority = 3; break;
case State_Error:
*pPriority = 4; break;
default:
*pPriority = 5; break;
}
return S_OK;
return S_OK;
}
IFACEMETHODIMP OCOverlay::IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib)
IFACEMETHODIMP OCOverlay::IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib)
{
RemotePathChecker* checker = getGlobalChecker();
auto watchedDirectories = checker->WatchedDirectories();
RemotePathChecker* checker = getGlobalChecker();
std::shared_ptr<const std::vector<std::wstring>> watchedDirectories = checker->WatchedDirectories();
wstring wpath(pwszPath);
wpath.append(L"\\");
vector<wstring>::iterator it;
bool watched = false;
for (it = watchedDirectories.begin(); it != watchedDirectories.end(); ++it) {
if (StringUtil::begins_with(wpath, *it)) {
watched = true;
}
}
if (watchedDirectories->empty()) {
return MAKE_HRESULT(S_FALSE, 0, 0);
}
if (!watched) {
return MAKE_HRESULT(S_FALSE, 0, 0);
}
bool watched = false;
size_t pathLength = wcslen(pwszPath);
for (auto it = watchedDirectories->begin(); it != watchedDirectories->end(); ++it) {
if (StringUtil::isDescendantOf(pwszPath, pathLength, *it)) {
watched = true;
}
}
int state = 0;
if (!checker->IsMonitoredPath(pwszPath, &state)) {
return MAKE_HRESULT(S_FALSE, 0, 0);
}
return MAKE_HRESULT(state == _state ? S_OK : S_FALSE, 0, 0);
if (!watched) {
return MAKE_HRESULT(S_FALSE, 0, 0);
}
int state = 0;
if (!checker->IsMonitoredPath(pwszPath, &state)) {
return MAKE_HRESULT(S_FALSE, 0, 0);
}
return MAKE_HRESULT(state == _state ? S_OK : S_FALSE, 0, 0);
}
IFACEMETHODIMP OCOverlay::GetOverlayInfo(PWSTR pwszIconFile, int cchMax, int *pIndex, DWORD *pdwFlags)
{
*pIndex = 0;
*pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;
*pIndex = _state;
*pIndex = 0;
*pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;
*pIndex = _state;
if (GetModuleFileName(instanceHandle, pwszIconFile, cchMax) == 0) {
HRESULT hResult = HRESULT_FROM_WIN32(GetLastError());
wcerr << L"IsOK? " << (hResult == S_OK) << L" with path " << pwszIconFile << L", index " << *pIndex << endl;
return hResult;
}
if (GetModuleFileName(instanceHandle, pwszIconFile, cchMax) == 0) {
HRESULT hResult = HRESULT_FROM_WIN32(GetLastError());
wcerr << L"IsOK? " << (hResult == S_OK) << L" with path " << pwszIconFile << L", index " << *pIndex << endl;
return hResult;
}
return S_OK;
return S_OK;
}
bool OCOverlay::_IsOverlaysEnabled()
{
//int enable;
bool success = false;
//if(RegistryUtil::ReadRegistry(REGISTRY_ROOT_KEY, REGISTRY_ENABLE_OVERLAY, &enable))
//{
// if(enable) {
// success = true;
// }
//}
return success;
}
@@ -21,22 +21,21 @@ class OCOverlay : public IShellIconOverlayIdentifier
{
public:
OCOverlay(int state);
OCOverlay(int state);
IFACEMETHODIMP_(ULONG) AddRef();
IFACEMETHODIMP GetOverlayInfo(PWSTR pwszIconFile, int cchMax, int *pIndex, DWORD *pdwFlags);
IFACEMETHODIMP GetPriority(int *pPriority);
IFACEMETHODIMP IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib);
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv);
IFACEMETHODIMP_(ULONG) AddRef();
IFACEMETHODIMP GetOverlayInfo(PWSTR pwszIconFile, int cchMax, int *pIndex, DWORD *pdwFlags);
IFACEMETHODIMP GetPriority(int *pPriority);
IFACEMETHODIMP IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib);
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv);
IFACEMETHODIMP_(ULONG) Release();
protected:
~OCOverlay();
private:
bool _IsOverlaysEnabled();
long _referenceCount;
int _state;
int _state;
};
#endif
@@ -20,7 +20,7 @@
extern long dllReferenceCount;
OCOverlayFactory::OCOverlayFactory(int state)
: _referenceCount(1), _state(state)
: _referenceCount(1), _state(state)
{
InterlockedIncrement(&dllReferenceCount);
}
@@ -32,7 +32,7 @@ OCOverlayFactory::~OCOverlayFactory()
IFACEMETHODIMP OCOverlayFactory::QueryInterface(REFIID riid, void **ppv)
{
HRESULT hResult = S_OK;
HRESULT hResult = S_OK;
if (IsEqualIID(IID_IUnknown, riid) ||
IsEqualIID(IID_IClassFactory, riid))
@@ -66,20 +66,20 @@ IFACEMETHODIMP_(ULONG) OCOverlayFactory::Release()
}
IFACEMETHODIMP OCOverlayFactory::CreateInstance(
IUnknown *pUnkOuter, REFIID riid, void **ppv)
IUnknown *pUnkOuter, REFIID riid, void **ppv)
{
HRESULT hResult = CLASS_E_NOAGGREGATION;
HRESULT hResult = CLASS_E_NOAGGREGATION;
if (pUnkOuter != NULL) { return hResult; }
hResult = E_OUTOFMEMORY;
hResult = E_OUTOFMEMORY;
OCOverlay *lrOverlay = new (std::nothrow) OCOverlay(_state);
if (!lrOverlay) { return hResult; }
if (!lrOverlay) { return hResult; }
hResult = lrOverlay->QueryInterface(riid, ppv);
lrOverlay->Release();
lrOverlay->Release();
return hResult;
return hResult;
}
IFACEMETHODIMP OCOverlayFactory::LockServer(BOOL fLock)
@@ -18,20 +18,20 @@
#pragma once
enum State {
State_Error = 0,
State_OK, State_OKShared,
State_Sync,
State_Warning
State_Error = 0,
State_OK, State_OKShared,
State_Sync,
State_Warning
};
class OCOverlayFactory : public IClassFactory
{
public:
OCOverlayFactory(int state);
OCOverlayFactory(int state);
IFACEMETHODIMP_(ULONG) AddRef();
IFACEMETHODIMP_(ULONG) AddRef();
IFACEMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv);
IFACEMETHODIMP LockServer(BOOL fLock);
IFACEMETHODIMP LockServer(BOOL fLock);
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv);
IFACEMETHODIMP_(ULONG) Release();
@@ -40,7 +40,7 @@ protected:
private:
long _referenceCount;
int _state;
int _state;
};
#endif
@@ -23,52 +23,52 @@ using namespace std;
HRESULT OCOverlayRegistrationHandler::MakeRegistryEntries(const CLSID& clsid, PCWSTR friendlyName)
{
HRESULT hResult;
HKEY shellOverlayKey = NULL;
// the key may not exist yet
hResult = HRESULT_FROM_WIN32(RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_OVERLAY_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &shellOverlayKey, NULL));
if (!SUCCEEDED(hResult)) {
hResult = RegCreateKey(HKEY_LOCAL_MACHINE, REGISTRY_OVERLAY_KEY, &shellOverlayKey);
if(!SUCCEEDED(hResult)) {
return hResult;
}
}
HRESULT hResult;
HKEY shellOverlayKey = NULL;
// the key may not exist yet
hResult = HRESULT_FROM_WIN32(RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_OVERLAY_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &shellOverlayKey, NULL));
if (!SUCCEEDED(hResult)) {
hResult = RegCreateKey(HKEY_LOCAL_MACHINE, REGISTRY_OVERLAY_KEY, &shellOverlayKey);
if(!SUCCEEDED(hResult)) {
return hResult;
}
}
HKEY syncExOverlayKey = NULL;
hResult = HRESULT_FROM_WIN32(RegCreateKeyEx(shellOverlayKey, friendlyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &syncExOverlayKey, NULL));
HKEY syncExOverlayKey = NULL;
hResult = HRESULT_FROM_WIN32(RegCreateKeyEx(shellOverlayKey, friendlyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &syncExOverlayKey, NULL));
if (!SUCCEEDED(hResult)) {
return hResult;
}
if (!SUCCEEDED(hResult)) {
return hResult;
}
wchar_t stringCLSID[MAX_PATH];
wchar_t stringCLSID[MAX_PATH];
StringFromGUID2(clsid, stringCLSID, ARRAYSIZE(stringCLSID));
LPCTSTR value = stringCLSID;
hResult = RegSetValueEx(syncExOverlayKey, NULL, 0, REG_SZ, (LPBYTE)value, (DWORD)((wcslen(value)+1) * sizeof(TCHAR)));
if (!SUCCEEDED(hResult)) {
return hResult;
}
LPCTSTR value = stringCLSID;
hResult = RegSetValueEx(syncExOverlayKey, NULL, 0, REG_SZ, (LPBYTE)value, (DWORD)((wcslen(value)+1) * sizeof(TCHAR)));
if (!SUCCEEDED(hResult)) {
return hResult;
}
return hResult;
return hResult;
}
HRESULT OCOverlayRegistrationHandler::RemoveRegistryEntries(PCWSTR friendlyName)
{
HRESULT hResult;
HKEY shellOverlayKey = NULL;
hResult = HRESULT_FROM_WIN32(RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_OVERLAY_KEY, 0, KEY_WRITE, &shellOverlayKey));
HRESULT hResult;
HKEY shellOverlayKey = NULL;
hResult = HRESULT_FROM_WIN32(RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_OVERLAY_KEY, 0, KEY_WRITE, &shellOverlayKey));
if (!SUCCEEDED(hResult)) {
return hResult;
}
if (!SUCCEEDED(hResult)) {
return hResult;
}
HKEY syncExOverlayKey = NULL;
hResult = HRESULT_FROM_WIN32(RegDeleteKey(shellOverlayKey, friendlyName));
if (!SUCCEEDED(hResult)) {
return hResult;
}
HKEY syncExOverlayKey = NULL;
hResult = HRESULT_FROM_WIN32(RegDeleteKey(shellOverlayKey, friendlyName));
if (!SUCCEEDED(hResult)) {
return hResult;
}
return hResult;
return hResult;
}
HRESULT OCOverlayRegistrationHandler::RegisterCOMObject(PCWSTR modulePath, PCWSTR friendlyName, const CLSID& clsid)
@@ -79,45 +79,45 @@ HRESULT OCOverlayRegistrationHandler::RegisterCOMObject(PCWSTR modulePath, PCWST
wchar_t stringCLSID[MAX_PATH];
StringFromGUID2(clsid, stringCLSID, ARRAYSIZE(stringCLSID));
HRESULT hResult;
HKEY hKey = NULL;
HRESULT hResult;
HKEY hKey = NULL;
hResult = HRESULT_FROM_WIN32(RegOpenKeyEx(HKEY_CLASSES_ROOT, REGISTRY_CLSID, 0, KEY_WRITE, &hKey));
if (!SUCCEEDED(hResult)) {
return hResult;
}
hResult = HRESULT_FROM_WIN32(RegOpenKeyEx(HKEY_CLASSES_ROOT, REGISTRY_CLSID, 0, KEY_WRITE, &hKey));
if (!SUCCEEDED(hResult)) {
return hResult;
}
HKEY clsidKey = NULL;
hResult = HRESULT_FROM_WIN32(RegCreateKeyEx(hKey, stringCLSID, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &clsidKey, NULL));
if(!SUCCEEDED(hResult)) {
return hResult;
}
HKEY clsidKey = NULL;
hResult = HRESULT_FROM_WIN32(RegCreateKeyEx(hKey, stringCLSID, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &clsidKey, NULL));
if(!SUCCEEDED(hResult)) {
return hResult;
}
hResult = HRESULT_FROM_WIN32(RegSetValue(clsidKey, NULL, REG_SZ, friendlyName, (DWORD) wcslen(friendlyName)));
hResult = HRESULT_FROM_WIN32(RegSetValue(clsidKey, NULL, REG_SZ, friendlyName, (DWORD) wcslen(friendlyName)));
HKEY inprocessKey = NULL;
hResult = HRESULT_FROM_WIN32(RegCreateKeyEx(clsidKey, REGISTRY_IN_PROCESS, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &inprocessKey, NULL));
if(!SUCCEEDED(hResult)) {
return hResult;
}
HKEY inprocessKey = NULL;
hResult = HRESULT_FROM_WIN32(RegCreateKeyEx(clsidKey, REGISTRY_IN_PROCESS, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &inprocessKey, NULL));
if(!SUCCEEDED(hResult)) {
return hResult;
}
hResult = HRESULT_FROM_WIN32(RegSetValue(inprocessKey, NULL, REG_SZ, modulePath, (DWORD) wcslen(modulePath)));
hResult = HRESULT_FROM_WIN32(RegSetValue(inprocessKey, NULL, REG_SZ, modulePath, (DWORD) wcslen(modulePath)));
if(!SUCCEEDED(hResult)) {
return hResult;
}
if(!SUCCEEDED(hResult)) {
return hResult;
}
hResult = HRESULT_FROM_WIN32(RegSetValueEx(inprocessKey, REGISTRY_THREADING, 0, REG_SZ, (LPBYTE)REGISTRY_APARTMENT, (DWORD)((wcslen(REGISTRY_APARTMENT)+1) * sizeof(TCHAR))));
if(!SUCCEEDED(hResult)) {
return hResult;
}
if(!SUCCEEDED(hResult)) {
return hResult;
}
hResult = HRESULT_FROM_WIN32(RegSetValueEx(inprocessKey, REGISTRY_VERSION, 0, REG_SZ, (LPBYTE)REGISTRY_VERSION_NUMBER, (DWORD)(wcslen(REGISTRY_VERSION_NUMBER)+1) * sizeof(TCHAR)));
if(!SUCCEEDED(hResult)) {
return hResult;
}
hResult = HRESULT_FROM_WIN32(RegSetValueEx(inprocessKey, REGISTRY_VERSION, 0, REG_SZ, (LPBYTE)REGISTRY_VERSION_NUMBER, (DWORD)(wcslen(REGISTRY_VERSION_NUMBER)+1) * sizeof(TCHAR)));
if(!SUCCEEDED(hResult)) {
return hResult;
}
return S_OK;
return S_OK;
}
HRESULT OCOverlayRegistrationHandler::UnregisterCOMObject(const CLSID& clsid)
@@ -125,28 +125,28 @@ HRESULT OCOverlayRegistrationHandler::UnregisterCOMObject(const CLSID& clsid)
wchar_t stringCLSID[MAX_PATH];
StringFromGUID2(clsid, stringCLSID, ARRAYSIZE(stringCLSID));
HRESULT hResult;
HKEY hKey = NULL;
hResult = HRESULT_FROM_WIN32(RegOpenKeyEx(HKEY_CLASSES_ROOT, REGISTRY_CLSID, 0, DELETE, &hKey));
if (!SUCCEEDED(hResult)) {
return hResult;
}
HRESULT hResult;
HKEY hKey = NULL;
hResult = HRESULT_FROM_WIN32(RegOpenKeyEx(HKEY_CLASSES_ROOT, REGISTRY_CLSID, 0, DELETE, &hKey));
if (!SUCCEEDED(hResult)) {
return hResult;
}
HKEY clsidKey = NULL;
hResult = HRESULT_FROM_WIN32(RegOpenKeyEx(hKey, stringCLSID, 0, DELETE, &clsidKey));
if(!SUCCEEDED(hResult)) {
return hResult;
}
HKEY clsidKey = NULL;
hResult = HRESULT_FROM_WIN32(RegOpenKeyEx(hKey, stringCLSID, 0, DELETE, &clsidKey));
if(!SUCCEEDED(hResult)) {
return hResult;
}
hResult = HRESULT_FROM_WIN32(RegDeleteKey(clsidKey, REGISTRY_IN_PROCESS));
if(!SUCCEEDED(hResult)) {
return hResult;
}
hResult = HRESULT_FROM_WIN32(RegDeleteKey(clsidKey, REGISTRY_IN_PROCESS));
if(!SUCCEEDED(hResult)) {
return hResult;
}
hResult = HRESULT_FROM_WIN32(RegDeleteKey(hKey, stringCLSID));
if(!SUCCEEDED(hResult)) {
return hResult;
}
hResult = HRESULT_FROM_WIN32(RegDeleteKey(hKey, stringCLSID));
if(!SUCCEEDED(hResult)) {
return hResult;
}
return S_OK;
return S_OK;
}
@@ -19,11 +19,11 @@
class __declspec(dllexport) OCOverlayRegistrationHandler
{
public:
static HRESULT MakeRegistryEntries(const CLSID& clsid, PCWSTR fileType);
static HRESULT RegisterCOMObject(PCWSTR modulePath, PCWSTR friendlyName, const CLSID& clsid);
static HRESULT RemoveRegistryEntries(PCWSTR friendlyName);
static HRESULT UnregisterCOMObject(const CLSID& clsid);
public:
static HRESULT MakeRegistryEntries(const CLSID& clsid, PCWSTR fileType);
static HRESULT RegisterCOMObject(PCWSTR modulePath, PCWSTR friendlyName, const CLSID& clsid);
static HRESULT RemoveRegistryEntries(PCWSTR friendlyName);
static HRESULT UnregisterCOMObject(const CLSID& clsid);
};
#endif
@@ -13,38 +13,38 @@
*/
#define OVERLAY_GUID_ERROR L"{0960F090-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_GUID_ERROR_SHARED L"{0960F091-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_GUID_OK L"{0960F092-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_GUID_OK_SHARED L"{0960F093-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_GUID_SYNC L"{0960F094-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_GUID_SYNC_SHARED L"{0960F095-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_GUID_WARNING L"{0960F096-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_GUID_ERROR L"{0960F090-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_GUID_ERROR_SHARED L"{0960F091-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_GUID_OK L"{0960F092-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_GUID_OK_SHARED L"{0960F093-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_GUID_SYNC L"{0960F094-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_GUID_SYNC_SHARED L"{0960F095-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_GUID_WARNING L"{0960F096-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_GUID_WARNING_SHARED L"{0960F097-F328-48A3-B746-276B1E3C3722}"
#define OVERLAY_GENERIC_NAME L"OC Overlay Handler"
// two spaces to put us ahead of the competition :/
#define OVERLAY_NAME_ERROR L" OCError"
#define OVERLAY_NAME_ERROR_SHARED L" OCErrorShared"
#define OVERLAY_NAME_OK L" OCOK"
#define OVERLAY_NAME_OK_SHARED L" OCOKShared"
#define OVERLAY_NAME_SYNC L" OCSync"
#define OVERLAY_NAME_SYNC_SHARED L" OCSyncShared"
#define OVERLAY_NAME_WARNING L" OCWarning"
#define OVERLAY_NAME_WARNING_SHARED L" OCWarningShared"
#define OVERLAY_NAME_ERROR L" OCError"
#define OVERLAY_NAME_ERROR_SHARED L" OCErrorShared"
#define OVERLAY_NAME_OK L" OCOK"
#define OVERLAY_NAME_OK_SHARED L" OCOKShared"
#define OVERLAY_NAME_SYNC L" OCSync"
#define OVERLAY_NAME_SYNC_SHARED L" OCSyncShared"
#define OVERLAY_NAME_WARNING L" OCWarning"
#define OVERLAY_NAME_WARNING_SHARED L" OCWarningShared"
#define REGISTRY_OVERLAY_KEY L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers"
#define REGISTRY_CLSID L"CLSID"
#define REGISTRY_IN_PROCESS L"InprocServer32"
#define REGISTRY_THREADING L"ThreadingModel"
#define REGISTRY_APARTMENT L"Apartment"
#define REGISTRY_VERSION L"Version"
#define REGISTRY_VERSION_NUMBER L"1.0"
#define REGISTRY_OVERLAY_KEY L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers"
#define REGISTRY_CLSID L"CLSID"
#define REGISTRY_IN_PROCESS L"InprocServer32"
#define REGISTRY_THREADING L"ThreadingModel"
#define REGISTRY_APARTMENT L"Apartment"
#define REGISTRY_VERSION L"Version"
#define REGISTRY_VERSION_NUMBER L"1.0"
//Registry values for running
#define REGISTRY_ENABLE_OVERLAY L"EnableOverlay"
#define REGISTRY_ENABLE_OVERLAY L"EnableOverlay"
#define GET_FILE_OVERLAY_ID L"getFileIconId"
#define GET_FILE_OVERLAY_ID L"getFileIconId"
#define PORT 34001
#define PORT 34001
@@ -31,23 +31,23 @@ using namespace std;
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();
}
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;
auto pipename = std::wstring(L"\\\\.\\pipe\\");
pipename += L"ownCloud-";
pipename += getUserName();
return pipename;
}
CommunicationSocket::CommunicationSocket()
@@ -57,23 +57,23 @@ CommunicationSocket::CommunicationSocket()
CommunicationSocket::~CommunicationSocket()
{
Close();
Close();
}
bool CommunicationSocket::Close()
{
if (_pipe == INVALID_HANDLE_VALUE) {
return false;
}
CloseHandle(_pipe);
_pipe = INVALID_HANDLE_VALUE;
return true;
if (_pipe == INVALID_HANDLE_VALUE) {
return false;
}
CloseHandle(_pipe);
_pipe = INVALID_HANDLE_VALUE;
return true;
}
bool CommunicationSocket::Connect(const std::wstring &pipename)
{
_pipe = CreateFile(pipename.data(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
_pipe = CreateFile(pipename.data(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (_pipe == INVALID_HANDLE_VALUE) {
return false;
@@ -84,7 +84,7 @@ bool CommunicationSocket::Connect(const std::wstring &pipename)
bool CommunicationSocket::SendMsg(const wchar_t* message) const
{
auto utf8_msg = StringUtil::toUtf8(message);
auto utf8_msg = StringUtil::toUtf8(message);
DWORD numBytesWritten = 0;
auto result = WriteFile( _pipe, utf8_msg.c_str(), DWORD(utf8_msg.size()), &numBytesWritten, NULL);
@@ -92,7 +92,7 @@ bool CommunicationSocket::SendMsg(const wchar_t* message) const
if (result) {
return true;
} else {
const_cast<CommunicationSocket*>(this)->Close();
const_cast<CommunicationSocket*>(this)->Close();
return false;
}
@@ -100,9 +100,9 @@ bool CommunicationSocket::SendMsg(const wchar_t* message) const
bool CommunicationSocket::ReadLine(wstring* response)
{
if (!response) {
return false;
}
if (!response) {
return false;
}
response->clear();
@@ -110,7 +110,7 @@ bool CommunicationSocket::ReadLine(wstring* response)
return false;
}
while (true) {
while (true) {
int lbPos = 0;
auto it = std::find(_buffer.begin() + lbPos, _buffer.end(), '\n');
if (it != _buffer.end()) {
@@ -121,24 +121,24 @@ bool CommunicationSocket::ReadLine(wstring* response)
std::array<char, 128> resp_utf8;
DWORD numBytesRead = 0;
DWORD totalBytesAvailable = 0;
DWORD totalBytesAvailable = 0;
if (!PeekNamedPipe(_pipe, NULL, 0, 0, &totalBytesAvailable, 0)) {
Close();
return false;
}
if (totalBytesAvailable == 0) {
return false;
}
if (!PeekNamedPipe(_pipe, NULL, 0, 0, &totalBytesAvailable, 0)) {
Close();
return false;
}
if (totalBytesAvailable == 0) {
return false;
}
if (!ReadFile(_pipe, resp_utf8.data(), DWORD(resp_utf8.size()), &numBytesRead, NULL)) {
if (!ReadFile(_pipe, resp_utf8.data(), DWORD(resp_utf8.size()), &numBytesRead, NULL)) {
Close();
return false;
}
if (numBytesRead <= 0) {
return false;
}
_buffer.insert(_buffer.end(), resp_utf8.begin(), resp_utf8.begin()+numBytesRead);
_buffer.insert(_buffer.end(), resp_utf8.begin(), resp_utf8.begin()+numBytesRead);
continue;
}
}
}
@@ -26,22 +26,22 @@
class __declspec(dllexport) CommunicationSocket
{
public:
static std::wstring DefaultPipePath();
static std::wstring DefaultPipePath();
CommunicationSocket();
~CommunicationSocket();
CommunicationSocket();
~CommunicationSocket();
bool Connect(const std::wstring& pipename);
bool Close();
bool Connect(const std::wstring& pipename);
bool Close();
bool SendMsg(const wchar_t*) const;
bool ReadLine(std::wstring*);
bool SendMsg(const wchar_t*) const;
bool ReadLine(std::wstring*);
HANDLE Event() { return _pipe; }
private:
HANDLE _pipe;
std::vector<char> _buffer;
private:
HANDLE _pipe;
std::vector<char> _buffer;
bool _connected;
};
+41 -41
Ver Arquivo
@@ -22,65 +22,65 @@ using namespace std;
bool FileUtil::IsChildFile(const wchar_t* rootFolder, vector<wstring>* files)
{
for(vector<wstring>::iterator it = files->begin(); it != files->end(); it++)
{
wstring file = *it;
for(vector<wstring>::iterator it = files->begin(); it != files->end(); it++)
{
wstring file = *it;
size_t found = file.find(rootFolder);
size_t found = file.find(rootFolder);
if(found != string::npos)
{
return true;
}
}
if(found != string::npos)
{
return true;
}
}
return false;
return false;
}
bool FileUtil::IsChildFile(const wchar_t* rootFolder, const wchar_t* file)
{
wstring* f = new wstring(file);
wstring* f = new wstring(file);
size_t found = f->find(rootFolder);
size_t found = f->find(rootFolder);
if(found != string::npos)
{
return true;
}
return false;
if(found != string::npos)
{
return true;
}
return false;
}
bool FileUtil::IsChildFileOfRoot(std::vector<std::wstring>* files)
{
wstring* rootFolder = new wstring();
bool needed = false;
wstring* rootFolder = new wstring();
bool needed = false;
if(RegistryUtil::ReadRegistry(REGISTRY_ROOT_KEY, REGISTRY_FILTER_FOLDER, rootFolder))
{
if(IsChildFile(rootFolder->c_str(), files))
{
needed = true;
}
}
if(RegistryUtil::ReadRegistry(REGISTRY_ROOT_KEY, REGISTRY_FILTER_FOLDER, rootFolder))
{
if(IsChildFile(rootFolder->c_str(), files))
{
needed = true;
}
}
delete rootFolder;
return needed;
delete rootFolder;
return needed;
}
bool FileUtil::IsChildFileOfRoot(const wchar_t* filePath)
{
wstring* rootFolder = new wstring();
bool needed = false;
if(RegistryUtil::ReadRegistry(REGISTRY_ROOT_KEY, REGISTRY_FILTER_FOLDER, rootFolder))
{
if(FileUtil::IsChildFile(rootFolder->c_str(), filePath))
{
needed = true;
}
}
wstring* rootFolder = new wstring();
bool needed = false;
if(RegistryUtil::ReadRegistry(REGISTRY_ROOT_KEY, REGISTRY_FILTER_FOLDER, rootFolder))
{
if(FileUtil::IsChildFile(rootFolder->c_str(), filePath))
{
needed = true;
}
}
delete rootFolder;
return needed;
delete rootFolder;
return needed;
}
+7 -7
Ver Arquivo
@@ -25,16 +25,16 @@
class __declspec(dllexport) FileUtil
{
public:
FileUtil();
FileUtil();
~FileUtil();
~FileUtil();
static bool IsChildFile(const wchar_t*, std::vector<std::wstring>*);
static bool IsChildFile(const wchar_t*, const wchar_t*);
static bool IsChildFileOfRoot(std::vector<std::wstring>*);
static bool IsChildFileOfRoot(const wchar_t*);
static bool IsChildFile(const wchar_t*, std::vector<std::wstring>*);
static bool IsChildFile(const wchar_t*, const wchar_t*);
static bool IsChildFileOfRoot(std::vector<std::wstring>*);
static bool IsChildFileOfRoot(const wchar_t*);
private:
private:
};
#endif
+21 -21
Ver Arquivo
@@ -25,8 +25,8 @@ using namespace std;
OCMessage::OCMessage(void)
{
_command = new wstring();
_value = new wstring();
_command = new wstring();
_value = new wstring();
}
OCMessage::~OCMessage(void)
@@ -35,40 +35,40 @@ OCMessage::~OCMessage(void)
bool OCMessage::InitFromMessage(const wstring* message)
{
if(message->length() == 0)
{
return false;
}
if(!ParserUtil::GetItem(COMMAND, message, _command))
{
return false;
}
if(message->length() == 0)
{
return false;
}
if(!ParserUtil::GetItem(COMMAND, message, _command))
{
return false;
}
if(!ParserUtil::GetItem(VALUE, message, _value))
{
return false;
}
if(!ParserUtil::GetItem(VALUE, message, _value))
{
return false;
}
return true;
return true;
}
std::wstring* OCMessage::GetCommand()
{
return _command;
return _command;
}
std::wstring* OCMessage::GetValue()
{
return _value;
return _value;
}
void OCMessage::SetCommand(std::wstring* command)
{
_command = command;
_command = command;
}
void OCMessage::SetValue(std::wstring* value)
{
_value = value;
_value = value;
}
+7 -7
Ver Arquivo
@@ -23,20 +23,20 @@ class __declspec(dllexport) OCMessage
{
public:
OCMessage(void);
~OCMessage(void);
~OCMessage(void);
bool InitFromMessage(const std::wstring*);
bool InitFromMessage(const std::wstring*);
std::wstring* GetCommand();
std::wstring* GetValue();
std::wstring* GetCommand();
std::wstring* GetValue();
void SetCommand(std::wstring*);
void SetValue(std::wstring*);
void SetCommand(std::wstring*);
void SetValue(std::wstring*);
private:
std::wstring* _command;
std::wstring* _value;
std::wstring* _value;
};
#endif
+247 -247
Ver Arquivo
@@ -21,369 +21,369 @@ using namespace std;
bool ParserUtil::GetItem(const wchar_t* item, const wstring* message, wstring* result)
{
size_t start = message->find(item, 0);
size_t start = message->find(item, 0);
if(start == string::npos)
{
return false;
}
if(start == string::npos)
{
return false;
}
size_t end = message->find(COLON, start);
size_t end = message->find(COLON, start);
if(end == string::npos)
{
return false;
}
if(end == string::npos)
{
return false;
}
//Move to next character after :
end += 1;
//Move to next character after :
end += 1;
wchar_t c = message->at(end);
wchar_t c = message->at(end);
//Move to the next character, which is the start of the value
end += 1;
if(c == '[')
{
return GetList(end - 1, message, result);
}
else
{
return GetValue(end, message, result);
}
//Move to the next character, which is the start of the value
end += 1;
if(c == '[')
{
return GetList(end - 1, message, result);
}
else
{
return GetValue(end, message, result);
}
}
bool ParserUtil::GetList(size_t start, const wstring* message, wstring* result)
{
size_t end = start + 1;
size_t end = start + 1;
int openBraceCount = 1;
int openBraceCount = 1;
while(openBraceCount > 0)
{
size_t closeBraceLocation = message->find(CLOSE_BRACE, end);
size_t openBraceLocation = message->find(OPEN_BRACE, end);
while(openBraceCount > 0)
{
size_t closeBraceLocation = message->find(CLOSE_BRACE, end);
size_t openBraceLocation = message->find(OPEN_BRACE, end);
if(closeBraceLocation < openBraceLocation)
{
openBraceCount--;
end = closeBraceLocation + 1;
}
else if(openBraceLocation < closeBraceLocation)
{
openBraceCount++;
end = openBraceLocation + 1;
}
if(closeBraceLocation < openBraceLocation)
{
openBraceCount--;
end = closeBraceLocation + 1;
}
else if(openBraceLocation < closeBraceLocation)
{
openBraceCount++;
end = openBraceLocation + 1;
}
}
size_t length = end - start;
}
size_t length = end - start;
return GetString(start, end, message, result);
return GetString(start, end, message, result);
}
size_t ParserUtil::GetNextStringItemInList(const wstring* message, size_t start, wstring* result)
{
size_t end = string::npos;
size_t commaLocation = message->find(COMMA, start);
size_t end = string::npos;
size_t commaLocation = message->find(COMMA, start);
if(commaLocation == string::npos)
{
end = message->find(CLOSE_BRACE, start);
if(end == string::npos)
{
end = message->length();
}
else
{
end = end - 1;
}
}
else
{
end = commaLocation - 1;
}
if(commaLocation == string::npos)
{
end = message->find(CLOSE_BRACE, start);
if(end == string::npos)
{
end = message->length();
}
else
{
end = end - 1;
}
}
else
{
end = commaLocation - 1;
}
if(!GetString(start + 2, end, message, result))
{
return string::npos;
}
if(!GetString(start + 2, end, message, result))
{
return string::npos;
}
return end + 2;
return end + 2;
}
size_t ParserUtil::GetNextOCItemInList(const wstring* message, size_t start, wstring* result)
{
size_t end = message->find(OPEN_CURLY_BRACE, start) + 1;
size_t end = message->find(OPEN_CURLY_BRACE, start) + 1;
int openBraceCount = 1;
int openBraceCount = 1;
while(openBraceCount > 0)
{
size_t closeBraceLocation = message->find(CLOSE_CURLY_BRACE, end);
size_t openBraceLocation = message->find(OPEN_CURLY_BRACE, end);
while(openBraceCount > 0)
{
size_t closeBraceLocation = message->find(CLOSE_CURLY_BRACE, end);
size_t openBraceLocation = message->find(OPEN_CURLY_BRACE, end);
if(closeBraceLocation < openBraceLocation)
{
openBraceCount--;
end = closeBraceLocation + 1;
}
else if(openBraceLocation < closeBraceLocation)
{
openBraceCount++;
end = openBraceLocation + 1;
}
}
if(closeBraceLocation < openBraceLocation)
{
openBraceCount--;
end = closeBraceLocation + 1;
}
else if(openBraceLocation < closeBraceLocation)
{
openBraceCount++;
end = openBraceLocation + 1;
}
}
size_t length = end - start;
size_t length = end - start;
if(!GetString(start, end, message, result))
{
return string::npos;
}
if(!GetString(start, end, message, result))
{
return string::npos;
}
return end;
return end;
}
bool ParserUtil::GetValue(size_t start, const wstring* message, wstring* result)
{
if(message->at(start - 1) == '\"')
{
size_t end = message->find(QUOTE, start);
return GetString(start, end, message, result);
}
else
{
start = start - 1;
if(message->at(start - 1) == '\"')
{
size_t end = message->find(QUOTE, start);
return GetString(start, end, message, result);
}
else
{
start = start - 1;
size_t end = message->find(COMMA, start);
result->append(message->substr(start, end-start));
}
size_t end = message->find(COMMA, start);
result->append(message->substr(start, end-start));
}
return true;
return true;
}
bool ParserUtil::GetString(size_t start, size_t end, const wstring* message, wstring* result)
{
if(end == string::npos)
{
return false;
}
if(end == string::npos)
{
return false;
}
size_t length = end - start;
size_t length = end - start;
if(length > 0)
{
result->append(message->substr(start, length));
}
else
{
result->append(L"");
}
if(length > 0)
{
result->append(message->substr(start, length));
}
else
{
result->append(L"");
}
return true;
return true;
}
bool ParserUtil::IsList(wstring* message)
{
wchar_t c = message->at(0);
if(c == '[')
{
return true;
}
wchar_t c = message->at(0);
if(c == '[')
{
return true;
}
return false;
return false;
}
bool ParserUtil::ParseJsonList(wstring* message, vector<wstring*>* items)
{
size_t currentLocation = message->find(OPEN_BRACE, 0);
size_t currentLocation = message->find(OPEN_BRACE, 0);
while(currentLocation < message->size())
{
wstring* item = new wstring();
while(currentLocation < message->size())
{
wstring* item = new wstring();
currentLocation = ParserUtil::GetNextStringItemInList(message, currentLocation, item);
currentLocation = ParserUtil::GetNextStringItemInList(message, currentLocation, item);
if(currentLocation == string::npos)
{
return false;
}
if(currentLocation == string::npos)
{
return false;
}
items->push_back(item);
}
items->push_back(item);
}
return true;
return true;
}
bool ParserUtil::ParseOCList(wstring* message, vector<wstring*>* items)
{
size_t currentLocation = message->find(OPEN_CURLY_BRACE, 0);
size_t currentLocation = message->find(OPEN_CURLY_BRACE, 0);
while(currentLocation < message->size())
{
wstring* item = new wstring();
while(currentLocation < message->size())
{
wstring* item = new wstring();
currentLocation = ParserUtil::GetNextOCItemInList(message, currentLocation, item);
currentLocation = ParserUtil::GetNextOCItemInList(message, currentLocation, item);
if(currentLocation == string::npos)
{
return false;
}
if(currentLocation == string::npos)
{
return false;
}
items->push_back(item);
}
items->push_back(item);
}
return true;
return true;
}
bool ParserUtil::ParseOCMessageList(wstring* message, vector<OCMessage*>* messages)
{
vector<wstring*>* items = new vector<wstring*>();
vector<wstring*>* items = new vector<wstring*>();
if(!ParseOCList(message, items))
{
return false;
}
if(!ParseOCList(message, items))
{
return false;
}
for(vector<wstring*>::iterator it = items->begin(); it != items->end(); it++)
{
wstring* temp = *it;
for(vector<wstring*>::iterator it = items->begin(); it != items->end(); it++)
{
wstring* temp = *it;
OCMessage* message = new OCMessage();
message->InitFromMessage(temp);
OCMessage* message = new OCMessage();
message->InitFromMessage(temp);
messages->push_back(message);
}
messages->push_back(message);
}
return true;
return true;
}
bool ParserUtil::SerializeList(std::vector<std::wstring>* list, std::wstring* result, bool escapeQuotes)
{
if(result == 0)
{
return false;
}
if(result == 0)
{
return false;
}
result->append(OPEN_BRACE);
result->append(OPEN_BRACE);
for(vector<wstring>::iterator it = list->begin(); it != list->end(); it++)
{
wstring value = *it;
for(vector<wstring>::iterator it = list->begin(); it != list->end(); it++)
{
wstring value = *it;
if(escapeQuotes)
{
result->append(BACK_SLASH);
}
if(escapeQuotes)
{
result->append(BACK_SLASH);
}
result->append(QUOTE);
result->append(value.c_str());
result->append(QUOTE);
result->append(value.c_str());
if(escapeQuotes)
{
result->append(BACK_SLASH);
}
if(escapeQuotes)
{
result->append(BACK_SLASH);
}
result->append(QUOTE);
result->append(COMMA);
}
result->append(QUOTE);
result->append(COMMA);
}
//Erase last comma
result->erase(result->size() - 1, 1);
//Erase last comma
result->erase(result->size() - 1, 1);
result->append(CLOSE_BRACE);
result->append(CLOSE_BRACE);
return true;
return true;
}
bool ParserUtil::SerializeMessage(std::map<std::wstring*, std::wstring*>* arguments, std::wstring* result, bool escapeQuotes)
{
if(result == 0)
{
return false;
}
if(result == 0)
{
return false;
}
result->append(OPEN_CURLY_BRACE);
result->append(OPEN_CURLY_BRACE);
for(map<wstring*, wstring*>::iterator it = arguments->begin(); it != arguments->end(); it++)
{
wstring key = *it->first;
wstring value = *it->second;
for(map<wstring*, wstring*>::iterator it = arguments->begin(); it != arguments->end(); it++)
{
wstring key = *it->first;
wstring value = *it->second;
if(escapeQuotes)
{
result->append(BACK_SLASH);
}
if(escapeQuotes)
{
result->append(BACK_SLASH);
}
result->append(QUOTE);
result->append(key.c_str());
result->append(QUOTE);
result->append(key.c_str());
if(escapeQuotes)
{
result->append(BACK_SLASH);
}
if(escapeQuotes)
{
result->append(BACK_SLASH);
}
result->append(QUOTE);
result->append(COLON);
result->append(value.c_str());
result->append(COMMA);
}
result->append(QUOTE);
result->append(COLON);
result->append(value.c_str());
result->append(COMMA);
}
//Erase last comma
result->erase(result->size() - 1, 1);
//Erase last comma
result->erase(result->size() - 1, 1);
result->append(CLOSE_CURLY_BRACE);
result->append(CLOSE_CURLY_BRACE);
return true;
return true;
}
bool ParserUtil::SerializeMessage(OCMessage* OCMessage, std::wstring* result)
{
if(result == 0)
{
return false;
}
if(result == 0)
{
return false;
}
result->append(OPEN_CURLY_BRACE);
result->append(OPEN_CURLY_BRACE);
result->append(QUOTE);
result->append(COMMAND);
result->append(QUOTE);
result->append(QUOTE);
result->append(COMMAND);
result->append(QUOTE);
result->append(COLON);
result->append(COLON);
result->append(QUOTE);
result->append(OCMessage->GetCommand()->c_str());
result->append(QUOTE);
result->append(QUOTE);
result->append(OCMessage->GetCommand()->c_str());
result->append(QUOTE);
result->append(COMMA);
result->append(QUOTE);
result->append(VALUE);
result->append(QUOTE);
result->append(COMMA);
result->append(QUOTE);
result->append(VALUE);
result->append(QUOTE);
result->append(COLON);
if(!IsList(OCMessage->GetValue()))
{
result->append(QUOTE);
}
result->append(OCMessage->GetValue()->c_str());
if(!IsList(OCMessage->GetValue()))
{
result->append(QUOTE);
}
result->append(COLON);
if(!IsList(OCMessage->GetValue()))
{
result->append(QUOTE);
}
result->append(OCMessage->GetValue()->c_str());
if(!IsList(OCMessage->GetValue()))
{
result->append(QUOTE);
}
result->append(CLOSE_CURLY_BRACE);
result->append(CLOSE_CURLY_BRACE);
return true;
return true;
}
+28 -28
Ver Arquivo
@@ -22,49 +22,49 @@ using namespace std;
bool RegistryUtil::ReadRegistry(const wchar_t* key, const wchar_t* name, int* result)
{
wstring* strResult = new wstring();
wstring* strResult = new wstring();
if(!ReadRegistry(key, name, strResult))
{
return false;
}
if(!ReadRegistry(key, name, strResult))
{
return false;
}
*result = stoi( strResult->c_str() );
*result = stoi( strResult->c_str() );
return true;
return true;
}
bool RegistryUtil::ReadRegistry(const wchar_t* key, const wchar_t* name, wstring* result)
{
HRESULT hResult;
HRESULT hResult;
HKEY rootKey = NULL;
HKEY rootKey = NULL;
hResult = HRESULT_FROM_WIN32(RegOpenKeyEx(HKEY_CURRENT_USER, (LPCWSTR)key, NULL, KEY_READ, &rootKey));
hResult = HRESULT_FROM_WIN32(RegOpenKeyEx(HKEY_CURRENT_USER, (LPCWSTR)key, NULL, KEY_READ, &rootKey));
if(!SUCCEEDED(hResult))
{
return false;
}
if(!SUCCEEDED(hResult))
{
return false;
}
wchar_t value[SIZE];
DWORD value_length = SIZE;
wchar_t value[SIZE];
DWORD value_length = SIZE;
hResult = RegQueryValueEx(rootKey, (LPCWSTR)name, NULL, NULL, (LPBYTE)value, &value_length );
if(!SUCCEEDED(hResult))
{
return false;
}
if(!SUCCEEDED(hResult))
{
return false;
}
result->append(value);
result->append(value);
HRESULT hResult2 = RegCloseKey(rootKey);
HRESULT hResult2 = RegCloseKey(rootKey);
if (!SUCCEEDED(hResult2))
{
return false;
}
if (!SUCCEEDED(hResult2))
{
return false;
}
return true;
return true;
}
+4 -4
Ver Arquivo
@@ -24,12 +24,12 @@
class __declspec(dllexport) RegistryUtil
{
public:
RegistryUtil();
RegistryUtil();
~RegistryUtil();
~RegistryUtil();
static bool ReadRegistry(const wchar_t*, const wchar_t*, int*);
static bool ReadRegistry(const wchar_t*, const wchar_t*, std::wstring*);
static bool ReadRegistry(const wchar_t*, const wchar_t*, int*);
static bool ReadRegistry(const wchar_t*, const wchar_t*, std::wstring*);
};
#endif
@@ -40,7 +40,7 @@ void RemotePathChecker::workerThreadLoop()
std::unordered_set<std::wstring> asked;
while(!_stop) {
Sleep(50);
Sleep(50);
if (!connected) {
asked.clear();
@@ -72,33 +72,42 @@ void RemotePathChecker::workerThreadLoop()
std::wstring response;
while (!_stop && socket.ReadLine(&response)) {
if (StringUtil::begins_with(response, wstring(L"REGISTER_PATH:"))) {
wstring responsePath = response.substr(14); // length of REGISTER_PATH:
if (StringUtil::begins_with(response, wstring(L"REGISTER_PATH:"))) {
wstring responsePath = response.substr(14); // length of REGISTER_PATH:
{ std::unique_lock<std::mutex> lock(_mutex);
_watchedDirectories.push_back(responsePath);
}
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATH | SHCNF_FLUSHNOWAIT, responsePath.data(), NULL);
} else if (StringUtil::begins_with(response, wstring(L"UNREGISTER_PATH:"))) {
auto sharedPtrCopy = atomic_load(&_watchedDirectories);
auto vectorCopy = make_shared<vector<wstring>>(*sharedPtrCopy);
vectorCopy->push_back(responsePath);
atomic_store(&_watchedDirectories, shared_ptr<const vector<wstring>>(vectorCopy));
// We don't keep track of all files and can't know which file is currently visible
// to the user, but at least reload the root dir so that any shortcut to the root
// is updated without the user needing to refresh.
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATH | SHCNF_FLUSHNOWAIT, responsePath.data(), NULL);
} else if (StringUtil::begins_with(response, wstring(L"UNREGISTER_PATH:"))) {
wstring responsePath = response.substr(16); // length of UNREGISTER_PATH:
{ std::unique_lock<std::mutex> lock(_mutex);
_watchedDirectories.erase(
std::remove(_watchedDirectories.begin(), _watchedDirectories.end(), responsePath),
_watchedDirectories.end());
auto sharedPtrCopy = atomic_load(&_watchedDirectories);
auto vectorCopy = make_shared<vector<wstring>>(*sharedPtrCopy);
vectorCopy->erase(
std::remove(vectorCopy->begin(), vectorCopy->end(), responsePath),
vectorCopy->end());
atomic_store(&_watchedDirectories, shared_ptr<const vector<wstring>>(vectorCopy));
vector<wstring> removedPaths;
{ std::unique_lock<std::mutex> lock(_mutex);
// Remove any item from the cache
for (auto it = _cache.begin(); it != _cache.end() ; ) {
if (StringUtil::begins_with(it->first, responsePath)) {
if (StringUtil::isDescendantOf(it->first, responsePath)) {
removedPaths.emplace_back(move(it->first));
it = _cache.erase(it);
} else {
++it;
}
}
// Assume that we won't need this at this point, UNREGISTER_PATH is rare
_oldCache.clear();
}
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATH | SHCNF_FLUSHNOWAIT, responsePath.data(), NULL);
for (auto& path : removedPaths)
SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH | SHCNF_FLUSHNOWAIT, path.data(), NULL);
} else if (StringUtil::begins_with(response, wstring(L"STATUS:")) ||
StringUtil::begins_with(response, wstring(L"BROADCAST:"))) {
@@ -116,57 +125,57 @@ void RemotePathChecker::workerThreadLoop()
auto state = _StrToFileState(responseStatus);
bool wasAsked = asked.erase(responsePath) > 0;
bool changed = false;
bool updateView = false;
{ std::unique_lock<std::mutex> lock(_mutex);
bool wasCached = _cache.find(responsePath) != _cache.end();
if (wasAsked || wasCached) {
auto &it = _cache[responsePath];
changed = (it != state);
it = state;
auto it = _cache.find(responsePath);
if (it == _cache.end()) {
// The client only approximates requested files, if the bloom
// filter becomes saturated after navigating multiple directories we'll start getting
// status pushes that we never requested and fill our cache. Ignore those.
if (!wasAsked) {
continue;
}
it = _cache.insert(make_pair(responsePath, StateNone)).first;
}
updateView = it->second != state;
it->second = state;
}
if (changed) {
if (updateView) {
SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH | SHCNF_FLUSHNOWAIT, responsePath.data(), NULL);
}
}
else if (StringUtil::begins_with(response, wstring(L"UPDATE_VIEW"))) {
std::unique_lock<std::mutex> lock(_mutex);
// Keep the old states to continue having something to display while the new state is
// requested from the client, triggered by clearing _cache.
_oldCache.insert(_cache.cbegin(), _cache.cend());
// Swap to make a copy of the cache under the mutex and clear the one stored.
std::unordered_map<std::wstring, FileState> cache;
swap(cache, _cache);
lock.unlock();
// Let explorer know about the invalidated cache entries, it will re-request the ones it needs.
for (auto it = cache.begin(); it != cache.end(); ++it) {
SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH | SHCNF_FLUSHNOWAIT, it->first.data(), NULL);
}
}
}
}
if (socket.Event() == INVALID_HANDLE_VALUE) {
std::unique_lock<std::mutex> lock(_mutex);
_cache.clear();
_oldCache.clear();
_watchedDirectories.clear();
_connected = connected = false;
}
if (socket.Event() == INVALID_HANDLE_VALUE) {
atomic_store(&_watchedDirectories, make_shared<const vector<wstring>>());
std::unique_lock<std::mutex> lock(_mutex);
_connected = connected = false;
if (_stop) return;
// Swap to make a copy of the cache under the mutex and clear the one stored.
std::unordered_map<std::wstring, FileState> cache;
swap(cache, _cache);
lock.unlock();
// Let explorer know about each invalidated cache entry that needs to get its icon removed.
for (auto it = cache.begin(); it != cache.end(); ++it) {
SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH | SHCNF_FLUSHNOWAIT, it->first.data(), NULL);
}
}
HANDLE handles[2] = { _newQueries, socket.Event() };
WaitForMultipleObjects(2, handles, false, 0);
if (_stop) return;
HANDLE handles[2] = { _newQueries, socket.Event() };
WaitForMultipleObjects(2, handles, false, 0);
}
}
RemotePathChecker::RemotePathChecker()
: _connected(false)
: _watchedDirectories(make_shared<const vector<wstring>>())
, _connected(false)
, _newQueries(CreateEvent(NULL, true, true, NULL))
, _thread([this]{ this->workerThreadLoop(); })
, _thread([this]{ this->workerThreadLoop(); })
{
}
@@ -179,10 +188,9 @@ RemotePathChecker::~RemotePathChecker()
CloseHandle(_newQueries);
}
vector<wstring> RemotePathChecker::WatchedDirectories()
std::shared_ptr<const std::vector<std::wstring>> RemotePathChecker::WatchedDirectories() const
{
std::unique_lock<std::mutex> lock(_mutex);
return _watchedDirectories;
return atomic_load(&_watchedDirectories);
}
bool RemotePathChecker::IsMonitoredPath(const wchar_t* filePath, int* state)
@@ -198,44 +206,39 @@ bool RemotePathChecker::IsMonitoredPath(const wchar_t* filePath, int* state)
auto it = _cache.find(path);
if (it != _cache.end()) {
// The path is in our cache, and we'll get updates pushed if the status changes.
*state = it->second;
return true;
}
// Re-request the status while we display what we have in _oldCache
_pending.push(filePath);
it = _oldCache.find(path);
bool foundInOldCache = it != _oldCache.end();
if (foundInOldCache)
*state = it->second;
lock.unlock();
SetEvent(_newQueries);
return foundInOldCache;
return false;
}
RemotePathChecker::FileState RemotePathChecker::_StrToFileState(const std::wstring &str)
{
if (str == L"NOP" || str == L"NONE") {
return StateNone;
} else if (str == L"SYNC" || str == L"NEW") {
return StateSync;
} else if (str == L"SYNC+SWM" || str == L"NEW+SWM") {
return StateSync;
} else if (str == L"OK") {
return StateOk;
} else if (str == L"OK+SWM") {
return StateOkSWM;
} else if (str == L"IGNORE") {
return StateWarning;
} else if (str == L"IGNORE+SWM") {
return StateWarning;
} else if (str == L"ERROR") {
return StateError;
} else if (str == L"ERROR+SWM") {
return StateError;
}
if (str == L"NOP" || str == L"NONE") {
return StateNone;
} else if (str == L"SYNC" || str == L"NEW") {
return StateSync;
} else if (str == L"SYNC+SWM" || str == L"NEW+SWM") {
return StateSync;
} else if (str == L"OK") {
return StateOk;
} else if (str == L"OK+SWM") {
return StateOkSWM;
} else if (str == L"IGNORE") {
return StateWarning;
} else if (str == L"IGNORE+SWM") {
return StateWarning;
} else if (str == L"ERROR") {
return StateError;
} else if (str == L"ERROR+SWM") {
return StateError;
}
return StateNone;
return StateNone;
}
@@ -19,6 +19,7 @@
#include <unordered_map>
#include <queue>
#include <thread>
#include <memory>
#include <mutex>
#include <atomic>
#include <condition_variable>
@@ -27,21 +28,21 @@
class __declspec(dllexport) RemotePathChecker {
public:
enum FileState {
// Order synced with OCOverlay
StateError = 0,
StateOk, StateOkSWM,
StateSync,
StateWarning,
StateNone
};
RemotePathChecker();
enum FileState {
// Order synced with OCOverlay
StateError = 0,
StateOk, StateOkSWM,
StateSync,
StateWarning,
StateNone
};
RemotePathChecker();
~RemotePathChecker();
std::vector<std::wstring> WatchedDirectories();
bool IsMonitoredPath(const wchar_t* filePath, int* state);
std::shared_ptr<const std::vector<std::wstring>> WatchedDirectories() const;
bool IsMonitoredPath(const wchar_t* filePath, int* state);
private:
FileState _StrToFileState(const std::wstring &str);
FileState _StrToFileState(const std::wstring &str);
std::mutex _mutex;
std::atomic<bool> _stop;
@@ -52,8 +53,9 @@ private:
std::queue<std::wstring> _pending;
std::unordered_map<std::wstring, FileState> _cache;
std::unordered_map<std::wstring, FileState> _oldCache;
std::vector<std::wstring> _watchedDirectories;
// The vector is const since it will be accessed from multiple threads through OCOverlay::IsMemberOf.
// Each modification needs to be made onto a copy and then atomically replaced in the shared_ptr.
std::shared_ptr<const std::vector<std::wstring>> _watchedDirectories;
bool _connected;
@@ -61,7 +63,7 @@ private:
//std::condition_variable _newQueries;
HANDLE _newQueries;
std::thread _thread;
std::thread _thread;
void workerThreadLoop();
};
+7 -7
Ver Arquivo
@@ -21,18 +21,18 @@
std::string StringUtil::toUtf8(const wchar_t *utf16, int len)
{
if (len < 0) {
len = (int) wcslen(utf16);
}
if (len < 0) {
len = (int) wcslen(utf16);
}
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t> > converter;
return converter.to_bytes(utf16, utf16+len);
}
std::wstring StringUtil::toUtf16(const char *utf8, int len)
{
if (len < 0) {
len = (int) strlen(utf8);
}
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t> > converter;
if (len < 0) {
len = (int) strlen(utf8);
}
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t> > converter;
return converter.from_bytes(utf8, utf8+len);
}
+23 -8
Ver Arquivo
@@ -20,15 +20,30 @@
class __declspec(dllexport) StringUtil {
public:
static std::string toUtf8(const wchar_t* utf16, int len = -1);
static std::wstring toUtf16(const char* utf8, int len = -1);
static std::string toUtf8(const wchar_t* utf16, int len = -1);
static std::wstring toUtf16(const char* utf8, int len = -1);
template<class T>
static bool begins_with(const T& input, const T& match)
{
return input.size() >= match.size()
&& std::equal(match.begin(), match.end(), input.begin());
}
template<class T>
static bool begins_with(const T& input, const T& match)
{
return input.size() >= match.size()
&& std::equal(match.begin(), match.end(), input.begin());
}
static bool isDescendantOf(const std::wstring& child, const std::wstring& parent) {
return isDescendantOf(child.c_str(), child.size(), parent.c_str(), parent.size());
}
static bool isDescendantOf(PCWSTR child, size_t childLength, const std::wstring& parent) {
return isDescendantOf(child, childLength, parent.c_str(), parent.size());
}
static bool isDescendantOf(PCWSTR child, size_t childLength, PCWSTR parent, size_t parentLength) {
if (!parentLength)
return false;
return (childLength == parentLength || childLength > parentLength && (child[parentLength] == L'\\' || child[parentLength - 1] == L'\\'))
&& wcsncmp(child, parent, parentLength) == 0;
}
};
#endif // STRINGUTIL_H
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
// This is the number that will end up in the version window of the DLLs.
// Increment this version before committing a new build if you are today's shell_integration build master.
#define OCEXT_BUILD_NUM 43
#define OCEXT_BUILD_NUM 44
#define STRINGIZE2(s) #s
#define STRINGIZE(s) STRINGIZE2(s)
-1
Ver Arquivo
@@ -1,7 +1,6 @@
# TODO: OSX and LIB_ONLY seem to require this to go to binary dir only
if(NOT TOKEN_AUTH_ONLY)
endif()
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(synclib_NAME ${APPLICATION_EXECUTABLE}sync)
+19 -7
Ver Arquivo
@@ -46,11 +46,17 @@ AccountManager *AccountManager::instance()
bool AccountManager::restore()
{
auto settings = Utility::settingsWithGroup(QLatin1String(accountsC));
if (settings->status() != QSettings::NoError) {
qDebug() << "Could not read settings from" << settings->fileName()
<< settings->status();
return false;
}
// If there are no accounts, check the old format.
if (settings->childGroups().isEmpty()
&& !settings->contains(QLatin1String(versionC))) {
return restoreFromLegacySettings();
restoreFromLegacySettings();
return true;
}
foreach (const auto& accountId, settings->childGroups()) {
@@ -69,6 +75,9 @@ bool AccountManager::restore()
bool AccountManager::restoreFromLegacySettings()
{
qDebug() << "Migrate: restoreFromLegacySettings, checking settings group"
<< Theme::instance()->appName();
// try to open the correctly themed settings
auto settings = Utility::settingsWithGroup(Theme::instance()->appName());
@@ -86,7 +95,7 @@ bool AccountManager::restoreFromLegacySettings()
QFileInfo fi( oCCfgFile );
if( fi.isReadable() ) {
QSettings *oCSettings = new QSettings(oCCfgFile, QSettings::IniFormat);
std::unique_ptr<QSettings> oCSettings(new QSettings(oCCfgFile, QSettings::IniFormat));
oCSettings->beginGroup(QLatin1String("ownCloud"));
// Check the theme url to see if it is the same url that the oC config was for
@@ -101,9 +110,7 @@ bool AccountManager::restoreFromLegacySettings()
qDebug() << "Migrate oC config if " << oCUrl << " == " << overrideUrl << ":"
<< (oCUrl == overrideUrl ? "Yes" : "No");
if( oCUrl == overrideUrl ) {
settings.reset( oCSettings );
} else {
delete oCSettings;
settings = std::move(oCSettings);
}
}
}
@@ -196,8 +203,8 @@ void AccountManager::saveAccountHelper(Account* acc, QSettings& settings, bool s
if (acc->_am) {
CookieJar* jar = qobject_cast<CookieJar*>(acc->_am->cookieJar());
if (jar) {
qDebug() << "Saving cookies.";
jar->save();
qDebug() << "Saving cookies." << acc->cookieJarPath();
jar->save(acc->cookieJarPath());
}
}
}
@@ -235,6 +242,9 @@ AccountPtr AccountManager::loadAccountHelper(QSettings& settings)
} else {
acc->setUrl(urlConfig.toUrl());
}
qDebug() << "Account for" << acc->url() << "using auth type" << authType;
acc->_serverVersion = settings.value(QLatin1String(serverVersionC)).toString();
// We want to only restore settings for that auth type and the user value
@@ -286,6 +296,8 @@ void AccountManager::deleteAccount(AccountState* account)
auto copy = *it; // keep a reference to the shared pointer so it does not delete it just yet
_accounts.erase(it);
QFile::remove(account->account()->cookieJarPath());
auto settings = Utility::settingsWithGroup(QLatin1String(accountsC));
settings->remove(account->account()->id());
+3 -1
Ver Arquivo
@@ -36,7 +36,9 @@ public:
/**
* Creates account objects from a given settings file.
* return true if the account was restored
*
* Returns false if there was an error reading the settings,
* but note that settings not existing is not an error.
*/
bool restore();
+7 -2
Ver Arquivo
@@ -675,8 +675,13 @@ void AccountSettings::refreshSelectiveSyncStatus()
ui->selectiveSyncButtons->setVisible(true);
ui->bigFolderUi->setVisible(false);
} else {
QString wholeMsg = tr("There are new folders that were not synchronized because they are too big: ") + msg;
ui->selectiveSyncNotification->setText(wholeMsg);
ConfigFile cfg;
QString info =
!cfg.confirmExternalStorage() ? tr("There are folders that were not synchronized because they are too big: ") :
!cfg.newBigFolderSizeLimit().first ? tr("There are folders that were not synchronized because they are external storages: ") :
tr("There are folders that were not synchronized because they are too big or external storages: ");
ui->selectiveSyncNotification->setText(info + msg);
ui->selectiveSyncButtons->setVisible(false);
ui->bigFolderUi->setVisible(true);
shouldBeVisible = true;
+17 -1
Ver Arquivo
@@ -156,7 +156,23 @@ Application::Application(int &argc, char **argv) :
connect(this, SIGNAL(messageReceived(QString, QObject*)), SLOT(slotParseMessage(QString, QObject*)));
AccountManager::instance()->restore();
if (!AccountManager::instance()->restore()) {
// If there is an error reading the account settings, try again
// after a couple of seconds, if that fails, give up.
// (non-existence is not an error)
Utility::sleep(5);
if (!AccountManager::instance()->restore()) {
qDebug() << "Could not read the account settings, quitting";
QMessageBox::critical(
0,
tr("Error accessing the configuration file"),
tr("There was an error while accessing the configuration "
"file at %1.").arg(ConfigFile().configFile()),
tr("Quit ownCloud"));
QTimer::singleShot(0, qApp, SLOT(quit()));
return;
}
}
FolderMan::instance()->setSyncEnabled(true);
+3 -3
Ver Arquivo
@@ -130,7 +130,7 @@ void ShibbolethCredentials::fetchFromKeychain()
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
job->setSettings(Utility::settingsWithGroup(Theme::instance()->appName(), job).release());
job->setInsecureFallback(false);
job->setKey(keychainKey(_account->url().toString(), "shibAssertion"));
job->setKey(keychainKey(_account->url().toString(), user()));
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(QKeychain::Job*)));
job->start();
}
@@ -309,7 +309,7 @@ void ShibbolethCredentials::storeShibCookie(const QNetworkCookie &cookie)
job->setSettings(Utility::settingsWithGroup(Theme::instance()->appName(), job).release());
// we don't really care if it works...
//connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotWriteJobDone(QKeychain::Job*)));
job->setKey(keychainKey(_account->url().toString(), "shibAssertion"));
job->setKey(keychainKey(_account->url().toString(), user()));
job->setTextData(QString::fromUtf8(cookie.toRawForm()));
job->start();
}
@@ -318,7 +318,7 @@ void ShibbolethCredentials::removeShibCookie()
{
DeletePasswordJob *job = new DeletePasswordJob(Theme::instance()->appName());
job->setSettings(Utility::settingsWithGroup(Theme::instance()->appName(), job).release());
job->setKey(keychainKey(_account->url().toString(), "shibAssertion"));
job->setKey(keychainKey(_account->url().toString(), user()));
job->start();
}
+70 -169
Ver Arquivo
@@ -46,17 +46,13 @@
namespace OCC {
const char oldJournalPath[] = ".csync_journal.db";
Folder::Folder(const FolderDefinition& definition,
AccountState* accountState,
QObject* parent)
: QObject(parent)
, _accountState(accountState)
, _definition(definition)
, _csyncError(false)
, _csyncUnavail(false)
, _wipeDb(false)
, _proxyDirty(true)
, _lastSyncDuration(0)
, _consecutiveFailingSyncs(0)
@@ -89,8 +85,6 @@ Folder::Folder(const FolderDefinition& definition,
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);
connect(_engine.data(), SIGNAL(started()), SLOT(slotSyncStarted()), Qt::QueuedConnection);
connect(_engine.data(), SIGNAL(finished(bool)), SLOT(slotSyncFinished(bool)), Qt::QueuedConnection);
@@ -104,9 +98,10 @@ Folder::Folder(const FolderDefinition& definition,
SLOT(slotAboutToRestoreBackup(bool*)));
connect(_engine.data(), SIGNAL(folderDiscovered(bool,QString)), this, SLOT(slotFolderDiscovered(bool,QString)));
connect(_engine.data(), SIGNAL(transmissionProgress(ProgressInfo)), this, SLOT(slotTransmissionProgress(ProgressInfo)));
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(itemCompleted(const SyncFileItemPtr &)),
this, SLOT(slotItemCompleted(const SyncFileItemPtr &)));
connect(_engine.data(), SIGNAL(newBigFolder(QString,bool)),
this, SLOT(slotNewBigFolderDiscovered(QString,bool)));
connect(_engine.data(), SIGNAL(seenLockedFile(QString)), FolderMan::instance(), SLOT(slotSyncOnceFileUnlocks(QString)));
connect(_engine.data(), SIGNAL(aboutToPropagate(SyncFileItemVector&)),
SLOT(slotLogPropagationStart()));
@@ -140,13 +135,13 @@ void Folder::checkLocalPath()
} else {
// Check directory again
if( !FileSystem::fileExists(_definition.localPath, fi) ) {
_syncResult.setErrorString(tr("Local folder %1 does not exist.").arg(_definition.localPath));
_syncResult.appendErrorString(tr("Local folder %1 does not exist.").arg(_definition.localPath));
_syncResult.setStatus( SyncResult::SetupError );
} else if( !fi.isDir() ) {
_syncResult.setErrorString(tr("%1 should be a folder but is not.").arg(_definition.localPath));
_syncResult.appendErrorString(tr("%1 should be a folder but is not.").arg(_definition.localPath));
_syncResult.setStatus( SyncResult::SetupError );
} else if( !fi.isReadable() ) {
_syncResult.setErrorString(tr("%1 is not readable.").arg(_definition.localPath));
_syncResult.appendErrorString(tr("%1 is not readable.").arg(_definition.localPath));
_syncResult.setStatus( SyncResult::SetupError );
}
}
@@ -269,8 +264,8 @@ SyncResult Folder::syncResult() const
void Folder::prepareToSync()
{
_syncResult.reset();
_syncResult.setStatus( SyncResult::NotYetStarted );
_syncResult.clearErrors();
}
void Folder::slotRunEtagJob()
@@ -324,120 +319,33 @@ void Folder::etagRetreivedFromSyncEngine(const QString& etag)
}
void Folder::bubbleUpSyncResult()
void Folder::showSyncResultPopup()
{
// count new, removed and updated items
int newItems = 0;
int removedItems = 0;
int updatedItems = 0;
int ignoredItems = 0;
int renamedItems = 0;
int conflictItems = 0;
int errorItems = 0;
SyncFileItemPtr firstItemNew;
SyncFileItemPtr firstItemDeleted;
SyncFileItemPtr firstItemUpdated;
SyncFileItemPtr firstItemRenamed;
SyncFileItemPtr firstConflictItem;
SyncFileItemPtr firstItemError;
QElapsedTimer timer;
timer.start();
foreach (const SyncFileItemPtr &item, _syncResult.syncFileItemVector() ) {
// Process the item to the gui
if( item->_status == SyncFileItem::FatalError || item->_status == SyncFileItem::NormalError ) {
//: this displays an error string (%2) for a file %1
slotSyncError( tr("%1: %2").arg(item->_file, item->_errorString) );
errorItems++;
if (!firstItemError) {
firstItemError = item;
}
} else if( item->_status == SyncFileItem::FileIgnored ) {
// ignored files don't show up in notifications
continue;
} else if( item->_status == SyncFileItem::Conflict ) {
conflictItems++;
if (!firstConflictItem) {
firstConflictItem = item;
}
} else {
// add new directories or remove gone away dirs to the watcher
if (item->_isDirectory && item->_instruction == CSYNC_INSTRUCTION_NEW ) {
FolderMan::instance()->addMonitorPath( alias(), path()+item->_file );
}
if (item->_isDirectory && item->_instruction == CSYNC_INSTRUCTION_REMOVE ) {
FolderMan::instance()->removeMonitorPath( alias(), path()+item->_file );
}
if (!item->hasErrorStatus() && item->_direction == SyncFileItem::Down) {
switch (item->_instruction) {
case CSYNC_INSTRUCTION_NEW:
case CSYNC_INSTRUCTION_TYPE_CHANGE:
newItems++;
if (!firstItemNew)
firstItemNew = item;
break;
case CSYNC_INSTRUCTION_REMOVE:
removedItems++;
if (!firstItemDeleted)
firstItemDeleted = item;
break;
case CSYNC_INSTRUCTION_SYNC:
updatedItems++;
if (!firstItemUpdated)
firstItemUpdated = item;
break;
case CSYNC_INSTRUCTION_ERROR:
qDebug() << "Got Instruction ERROR. " << _syncResult.errorString();
break;
case CSYNC_INSTRUCTION_RENAME:
if (!firstItemRenamed) {
firstItemRenamed = item;
}
renamedItems++;
break;
default:
// nothing.
break;
}
} else if( item->_direction == SyncFileItem::None ) { // ignored files counting.
if( item->_instruction == CSYNC_INSTRUCTION_IGNORE ) {
ignoredItems++;
}
}
}
if( _syncResult.firstItemNew() ) {
createGuiLog( _syncResult.firstItemNew()->_file, LogStatusNew, _syncResult.numNewItems() );
}
if( _syncResult.firstItemDeleted() ) {
createGuiLog( _syncResult.firstItemDeleted()->_file, LogStatusRemove, _syncResult.numRemovedItems() );
}
if( _syncResult.firstItemUpdated() ) {
createGuiLog( _syncResult.firstItemUpdated()->_file, LogStatusUpdated, _syncResult.numUpdatedItems() );
}
qDebug() << "Processing result list and logging took " << timer.elapsed() << " Milliseconds.";
_syncResult.setWarnCount(ignoredItems);
if( firstItemNew ) {
createGuiLog( firstItemNew->_file, LogStatusNew, newItems );
}
if( firstItemDeleted ) {
createGuiLog( firstItemDeleted->_file, LogStatusRemove, removedItems );
}
if( firstItemUpdated ) {
createGuiLog( firstItemUpdated->_file, LogStatusUpdated, updatedItems );
}
if( firstItemRenamed ) {
if( _syncResult.firstItemRenamed() ) {
LogStatus status(LogStatusRename);
// if the path changes it's rather a move
QDir renTarget = QFileInfo(firstItemRenamed->_renameTarget).dir();
QDir renSource = QFileInfo(firstItemRenamed->_file).dir();
QDir renTarget = QFileInfo(_syncResult.firstItemRenamed()->_renameTarget).dir();
QDir renSource = QFileInfo(_syncResult.firstItemRenamed()->_file).dir();
if(renTarget != renSource) {
status = LogStatusMove;
}
createGuiLog( firstItemRenamed->_originalFile, status, renamedItems, firstItemRenamed->_renameTarget );
createGuiLog( _syncResult.firstItemRenamed()->_originalFile, status, _syncResult.numRenamedItems(), _syncResult.firstItemRenamed()->_renameTarget );
}
if( firstConflictItem ) {
createGuiLog( firstConflictItem->_file, LogStatusConflict, conflictItems );
if( _syncResult.firstConflictItem() ) {
createGuiLog( _syncResult.firstConflictItem()->_file, LogStatusConflict, _syncResult.numConflictItems() );
}
createGuiLog( firstItemError->_file, LogStatusError, errorItems );
createGuiLog( _syncResult.firstItemError()->_file, LogStatusError, _syncResult.numErrorItems() );
qDebug() << "OO folder slotSyncFinished: result: " << int(_syncResult.status());
}
@@ -576,12 +484,6 @@ void Folder::slotWatchedPathChanged(const QString& path)
scheduleThisFolderSoon();
}
void Folder::slotThreadTreeWalkResult(const SyncFileItemVector& items)
{
_syncResult.setSyncFileItemVector(items);
}
void Folder::saveToSettings() const
{
// Remove first to make sure we don't get duplicates
@@ -644,9 +546,6 @@ void Folder::slotTerminateSync()
if( _engine->isSyncRunning() ) {
_engine->abort();
// Do not display an error message, user knows his own actions.
// _errors.append( tr("The CSync thread terminated.") );
// _csyncError = true;
setSyncState(SyncResult::SyncAbortRequested);
}
}
@@ -694,10 +593,9 @@ bool Folder::setIgnoredFiles()
// a QSet of files to load.
ConfigFile cfg;
QString systemList = cfg.excludeFile(ConfigFile::SystemScope);
if( QFile::exists(systemList) ) {
qDebug() << "==== adding system ignore list to csync:" << systemList;
_engine->excludedFiles().addExcludeFilePath(systemList);
}
qDebug() << "==== adding system ignore list to csync:" << systemList;
_engine->excludedFiles().addExcludeFilePath(systemList);
QString userList = cfg.excludeFile(ConfigFile::UserScope);
if( QFile::exists(userList) ) {
qDebug() << "==== adding user defined ignore list to csync:" << userList;
@@ -728,19 +626,17 @@ void Folder::startSync(const QStringList &pathList)
qCritical() << "* ERROR csync is still running and new sync requested.";
return;
}
_errors.clear();
_csyncError = false;
_csyncUnavail = false;
_timeSinceLastSyncStart.restart();
_syncResult.clearErrors();
_syncResult.setStatus( SyncResult::SyncPrepare );
_syncResult.setSyncFileItemVector(SyncFileItemVector());
emit syncStateChange();
qDebug() << "*** Start syncing " << remoteUrl().toString() << " - client version"
<< qPrintable(Theme::instance()->version());
_fileLog->start(path());
if (!setIgnoredFiles())
{
slotSyncError(tr("Could not read system exclude file"));
@@ -750,15 +646,15 @@ void Folder::startSync(const QStringList &pathList)
setDirtyNetworkLimits();
SyncOptions opt;
ConfigFile cfgFile;
auto newFolderLimit = cfgFile.newBigFolderSizeLimit();
quint64 limit = newFolderLimit.first ? newFolderLimit.second * 1000 * 1000 : -1; // convert from MB to B
_engine->setNewBigFolderSizeLimit(limit);
opt._newBigFolderSizeLimit = newFolderLimit.first ? newFolderLimit.second * 1000LL * 1000LL : -1; // convert from MB to B
opt._confirmExternalStorage = cfgFile.confirmExternalStorage();
_engine->setSyncOptions(opt);
_engine->setIgnoreHiddenFiles(_definition.ignoreHiddenFiles);
_fileLog->start(path());
QMetaObject::invokeMethod(_engine.data(), "startSync", Qt::QueuedConnection);
emit syncStarted();
@@ -789,8 +685,7 @@ void Folder::setDirtyNetworkLimits()
void Folder::slotSyncError(const QString& err)
{
_errors.append( err );
_csyncError = true;
_syncResult.appendErrorString(err);
}
void Folder::slotSyncStarted()
@@ -812,29 +707,26 @@ void Folder::slotSyncFinished(bool success)
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
<< " SSL " << QSslSocket::sslLibraryVersionString().toUtf8().data()
#endif
;
;
if( _csyncError ) {
qDebug() << "-> SyncEngine finished with ERROR, warn count is" << _syncResult.warnCount();
bool syncError = !_syncResult.errorStrings().isEmpty();
if( syncError ) {
qDebug() << "-> SyncEngine finished with ERROR";
} else {
qDebug() << "-> SyncEngine finished without problem.";
}
_fileLog->finish();
bubbleUpSyncResult();
showSyncResultPopup();
auto anotherSyncNeeded = _engine->isAnotherSyncNeeded();
if (_csyncError) {
if (syncError) {
_syncResult.setStatus(SyncResult::Error);
qDebug() << " ** error Strings: " << _errors;
_syncResult.setErrorStrings( _errors );
qDebug() << " * owncloud csync thread finished with error";
} else if (_csyncUnavail) {
_syncResult.setStatus(SyncResult::Error);
qDebug() << " ** csync not available.";
} else if( _syncResult.warnCount() > 0 ) {
// there have been warnings on the way.
} else if( _syncResult.foundFilesNotSynced() ) {
_syncResult.setStatus(SyncResult::Problem);
} else if( _definition.paused ) {
// Maybe the sync was terminated because the user paused the folder
@@ -911,26 +803,28 @@ void Folder::slotFolderDiscovered(bool, QString folderName)
// and hand the result over to the progress dispatcher.
void Folder::slotTransmissionProgress(const ProgressInfo &pi)
{
if( !pi.isUpdatingEstimates() ) {
// this is the beginning of a sync, set the warning level to 0
_syncResult.setWarnCount(0);
}
emit progressInfo(pi);
ProgressDispatcher::instance()->setProgressInfo(alias(), pi);
}
// a item is completed: count the errors and forward to the ProgressDispatcher
void Folder::slotItemCompleted(const SyncFileItem &item, const PropagatorJob& job)
void Folder::slotItemCompleted(const SyncFileItemPtr &item)
{
if (Progress::isWarningKind(item._status)) {
// Count all error conditions.
_syncResult.setWarnCount(_syncResult.warnCount()+1);
// add new directories or remove gone away dirs to the watcher
if (item->_isDirectory && item->_instruction == CSYNC_INSTRUCTION_NEW ) {
FolderMan::instance()->addMonitorPath( alias(), path()+item->_file );
}
_fileLog->logItem(item);
emit ProgressDispatcher::instance()->itemCompleted(alias(), item, job);
if (item->_isDirectory && item->_instruction == CSYNC_INSTRUCTION_REMOVE ) {
FolderMan::instance()->removeMonitorPath( alias(), path()+item->_file );
}
_syncResult.processCompletedItem(item);
_fileLog->logItem(*item);
emit ProgressDispatcher::instance()->itemCompleted(alias(), item);
}
void Folder::slotNewBigFolderDiscovered(const QString &newF)
void Folder::slotNewBigFolderDiscovered(const QString &newF, bool isExternal)
{
auto newFolder = newF;
if (!newFolder.endsWith(QLatin1Char('/'))) {
@@ -955,9 +849,11 @@ void Folder::slotNewBigFolderDiscovered(const QString &newF)
journal->setSelectiveSyncList(SyncJournalDb::SelectiveSyncUndecidedList, undecidedList);
emit newBigFolderDiscovered(newFolder);
}
QString message = tr("A new folder larger than %1 MB has been added: %2.\n"
"Please go in the settings to select it if you wish to download it.")
.arg(ConfigFile().newBigFolderSizeLimit().second).arg(newF);
QString message = !isExternal ?
(tr("A new folder larger than %1 MB has been added: %2.\n")
.arg(ConfigFile().newBigFolderSizeLimit().second).arg(newF))
: (tr("A folder from an external storage has been added.\n"));
message += tr("Please go in the settings to select it if you wish to download it.");
auto logger = Logger::instance();
logger->postOptionalGuiLog(Theme::instance()->appNameGUI(), message);
@@ -986,17 +882,22 @@ void Folder::setSaveBackwardsCompatible(bool save)
_saveBackwardsCompatible = save;
}
void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction, bool *cancel)
void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction dir, bool *cancel)
{
ConfigFile cfgFile;
if (!cfgFile.promptDeleteFiles())
return;
QString msg =
tr("This sync would remove all the files in the sync folder '%1'.\n"
"This might be because the folder was silently reconfigured, or that all "
"the files were manually removed.\n"
"Are you sure you want to perform this operation?");
QString msg = dir == SyncFileItem::Down ?
tr("All files in the sync folder '%1' folder were deleted on the server.\n"
"These deletes will be synchronized to your local sync folder, making such files "
"unavailable unless you have a right to restore. \n"
"If you decide to keep the files, they will be re-synced with the server if you have rights to do so.\n"
"If you decide to delete the files, they will be unavailable to you, unless you are the owner.") :
tr("All the files in your local sync folder '%1' were deleted. These deletes will be "
"synchronized with your server, making such files unavailable unless restored.\n"
"Are you sure you want to sync those actions with the server?\n"
"If this was an accident and you decide to keep your files, they will be re-synced from the server.");
QMessageBox msgBox(QMessageBox::Warning, tr("Remove All Files?"),
msg.arg(shortGuiLocalPath()));
msgBox.addButton(tr("Remove all files"), QMessageBox::DestructiveRole);
+3 -8
Ver Arquivo
@@ -280,17 +280,15 @@ private slots:
void slotFolderDiscovered(bool local, QString folderName);
void slotTransmissionProgress(const ProgressInfo& pi);
void slotItemCompleted(const SyncFileItem&, const PropagatorJob&);
void slotItemCompleted(const SyncFileItemPtr&);
void slotRunEtagJob();
void etagRetreived(const QString &);
void etagRetreivedFromSyncEngine(const QString &);
void slotThreadTreeWalkResult(const SyncFileItemVector& ); // after sync is done
void slotEmitFinishedDelayed();
void slotNewBigFolderDiscovered(const QString &);
void slotNewBigFolderDiscovered(const QString &, bool isExternal);
void slotLogPropagationStart();
@@ -302,7 +300,7 @@ private slots:
private:
bool setIgnoredFiles();
void bubbleUpSyncResult();
void showSyncResultPopup();
void checkLocalPath();
@@ -325,10 +323,7 @@ private:
SyncResult _syncResult;
QScopedPointer<SyncEngine> _engine;
QStringList _errors;
bool _csyncError;
bool _csyncUnavail;
bool _wipeDb;
bool _proxyDirty;
QPointer<RequestEtagJob> _requestEtagJob;
QString _lastEtag;
+10 -9
Ver Arquivo
@@ -23,6 +23,7 @@
#include "accountmanager.h"
#include "filesystem.h"
#include "lockwatcher.h"
#include "asserts.h"
#include <syncengine.h>
#ifdef Q_OS_MAC
@@ -48,7 +49,7 @@ FolderMan::FolderMan(QObject *parent) :
_lockWatcher(new LockWatcher),
_appRestartRequired(false)
{
Q_ASSERT(!_instance);
ASSERT(!_instance);
_instance = this;
_socketApi.reset(new SocketApi);
@@ -115,7 +116,7 @@ void FolderMan::unloadFolder( Folder *f )
disconnect(f, SIGNAL(syncPausedChanged(Folder*,bool)),
this, SLOT(slotFolderSyncPaused(Folder*,bool)));
disconnect(&f->syncEngine().syncFileStatusTracker(), SIGNAL(fileStatusChanged(const QString &, SyncFileStatus)),
_socketApi.data(), SLOT(slotFileStatusChanged(const QString &, SyncFileStatus)));
_socketApi.data(), SLOT(broadcastStatusPushMessage(const QString &, SyncFileStatus)));
disconnect(f, SIGNAL(watchedFileChangedExternally(QString)),
&f->syncEngine().syncFileStatusTracker(), SLOT(slotPathTouched(QString)));
}
@@ -133,12 +134,13 @@ int FolderMan::unloadAndDeleteAllFolders()
delete f;
cnt++;
}
ASSERT(_folderMap.isEmpty());
_lastSyncFolder = 0;
_currentSyncFolder = 0;
_scheduledFolders.clear();
emit scheduleQueueChanged();
Q_ASSERT(_folderMap.count() == 0);
return cnt;
}
@@ -260,7 +262,6 @@ int FolderMan::setupFoldersMigration()
{
ConfigFile cfg;
QDir storageDir(cfg.configPath());
storageDir.mkpath(QLatin1String("folders"));
_folderConfigPath = cfg.configPath() + QLatin1String("folders");
qDebug() << "* Setup folders from " << _folderConfigPath << "(migration)";
@@ -463,7 +464,7 @@ void FolderMan::slotFolderSyncPaused( Folder *f, bool paused )
void FolderMan::slotFolderCanSyncChanged()
{
Folder *f = qobject_cast<Folder*>(sender());
Q_ASSERT(f);
ASSERT(f);
if (f->canSync()) {
_socketApi->slotRegisterPath(f->alias());
} else {
@@ -938,7 +939,7 @@ Folder* FolderMan::addFolderInternal(FolderDefinition folderDefinition,
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)));
_socketApi.data(), SLOT(broadcastStatusPushMessage(const QString &, SyncFileStatus)));
connect(folder, SIGNAL(watchedFileChangedExternally(QString)),
&folder->syncEngine().syncFileStatusTracker(), SLOT(slotPathTouched(QString)));
@@ -1121,7 +1122,7 @@ void FolderMan::setDirtyNetworkLimits()
SyncResult FolderMan::accountStatus(const QList<Folder*> &folders)
{
SyncResult overallResult(SyncResult::Undefined);
SyncResult overallResult;
int cnt = folders.count();
@@ -1235,10 +1236,10 @@ SyncResult FolderMan::accountStatus(const QList<Folder*> &folders)
return overallResult;
}
QString FolderMan::statusToString( SyncResult syncStatus, bool paused ) const
QString FolderMan::statusToString( SyncResult::Status syncStatus, bool paused ) const
{
QString folderMessage;
switch( syncStatus.status() ) {
switch( syncStatus ) {
case SyncResult::Undefined:
folderMessage = tr( "Undefined State." );
break;
+1 -1
Ver Arquivo
@@ -106,7 +106,7 @@ public:
/** Creates a new and empty local directory. */
bool startFromScratch( const QString& );
QString statusToString(SyncResult, bool paused ) const;
QString statusToString(SyncResult::Status, bool paused ) const;
static SyncResult accountStatus( const QList<Folder*> &folders );
+45 -23
Ver Arquivo
@@ -16,6 +16,7 @@
#include "folderman.h"
#include "accountstate.h"
#include "utility.h"
#include "asserts.h"
#include <theme.h>
#include <account.h>
#include "folderstatusdelegate.h"
@@ -29,6 +30,14 @@ Q_DECLARE_METATYPE(QPersistentModelIndex)
namespace OCC {
static const char propertyParentIndexC[] = "oc_parentIndex";
static const char propertyPermissionMap[] = "oc_permissionMap";
static QString removeTrailingSlash(const QString &s) {
if (s.endsWith('/')) {
return s.left(s.size() - 1);
}
return s;
}
FolderStatusModel::FolderStatusModel(QObject *parent)
:QAbstractItemModel(parent), _accountState(0), _dirty(false)
@@ -162,7 +171,7 @@ QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
case Qt::CheckStateRole:
return x._checked;
case Qt::DecorationRole:
return QFileIconProvider().icon(QFileIconProvider::Folder);
return QFileIconProvider().icon(x._isExternal ? QFileIconProvider::Network : QFileIconProvider::Folder);
case Qt::ForegroundRole:
if (x._isUndecided) {
return QColor(Qt::red);
@@ -368,6 +377,9 @@ FolderStatusModel::SubFolderInfo* FolderStatusModel::infoForIndex(const QModelIn
if (parentInfo->hasLabel()) {
return 0;
}
if (index.row() >= parentInfo->_subs.size()) {
return 0;
}
return &parentInfo->_subs[index.row()];
} else {
if (index.row() >= _folders.count()) {
@@ -469,14 +481,14 @@ QModelIndex FolderStatusModel::parent(const QModelIndex& child) const
}
auto pathIdx = static_cast<SubFolderInfo*>(child.internalPointer())->_pathIdx;
int i = 1;
Q_ASSERT(pathIdx.at(0) < _folders.count());
ASSERT(pathIdx.at(0) < _folders.count());
if (pathIdx.count() == 1) {
return createIndex(pathIdx.at(0), 0/*, nullptr*/);
}
const SubFolderInfo *info = &_folders[pathIdx.at(0)];
while (i < pathIdx.count() - 1) {
Q_ASSERT(pathIdx.at(i) < info->_subs.count());
ASSERT(pathIdx.at(i) < info->_subs.count());
info = &info->_subs[pathIdx.at(i)];
++i;
}
@@ -537,12 +549,15 @@ void FolderStatusModel::fetchMore(const QModelIndex& parent)
path += info->_path;
}
LsColJob *job = new LsColJob(_accountState->account(), path, this);
job->setProperties(QList<QByteArray>() << "resourcetype" << "http://owncloud.org/ns:size");
job->setProperties(QList<QByteArray>() << "resourcetype" << "http://owncloud.org/ns:size" << "http://owncloud.org/ns:permissions");
job->setTimeout(60 * 1000);
connect(job, SIGNAL(directoryListingSubfolders(QStringList)),
SLOT(slotUpdateDirectories(QStringList)));
connect(job, SIGNAL(finishedWithError(QNetworkReply*)),
this, SLOT(slotLscolFinishedWithError(QNetworkReply*)));
connect(job, SIGNAL(directoryListingIterated(const QString&, const QMap<QString,QString>&)),
this, SLOT(slotGatherPermissions(const QString&, const QMap<QString,QString>&)));
job->start();
QPersistentModelIndex persistentIndex(parent);
@@ -553,10 +568,24 @@ void FolderStatusModel::fetchMore(const QModelIndex& parent)
QTimer::singleShot(1000, this, SLOT(slotShowFetchProgress()));
}
void FolderStatusModel::slotGatherPermissions(const QString &href, const QMap<QString,QString> &map)
{
auto it = map.find("permissions");
if (it == map.end())
return;
auto job = sender();
auto permissionMap = job->property(propertyPermissionMap).toMap();
job->setProperty(propertyPermissionMap, QVariant()); // avoid a detach of the map while it is modified
ASSERT(!href.endsWith(QLatin1Char('/')), "LsColXMLParser::parse should remove the trailing slash before calling us.");
permissionMap[href] = *it;
job->setProperty(propertyPermissionMap, permissionMap);
}
void FolderStatusModel::slotUpdateDirectories(const QStringList &list)
{
auto job = qobject_cast<LsColJob *>(sender());
Q_ASSERT(job);
ASSERT(job);
QModelIndex idx = qvariant_cast<QPersistentModelIndex>(job->property(propertyParentIndexC));
auto parentInfo = infoForIndex(idx);
if (!parentInfo) {
@@ -598,6 +627,7 @@ void FolderStatusModel::slotUpdateDirectories(const QStringList &list)
selectiveSyncUndecidedSet.insert(str);
}
}
const auto permissionMap = job->property(propertyPermissionMap).toMap();
QStringList sortedSubfolders = list;
// skip the parent item (first in the list)
@@ -618,8 +648,8 @@ void FolderStatusModel::slotUpdateDirectories(const QStringList &list)
newInfo._folder = parentInfo->_folder;
newInfo._pathIdx = parentInfo->_pathIdx;
newInfo._pathIdx << newSubs.size();
auto size = job ? job->_sizes.value(path) : 0;
newInfo._size = size;
newInfo._size = job->_sizes.value(path);
newInfo._isExternal = permissionMap.value(removeTrailingSlash(path)).toString().contains("M");
newInfo._path = relativePath;
newInfo._name = relativePath.split('/', QString::SkipEmptyParts).last();
@@ -686,7 +716,7 @@ void FolderStatusModel::slotUpdateDirectories(const QStringList &list)
void FolderStatusModel::slotLscolFinishedWithError(QNetworkReply* r)
{
auto job = qobject_cast<LsColJob *>(sender());
Q_ASSERT(job);
ASSERT(job);
QModelIndex idx = qvariant_cast<QPersistentModelIndex>(job->property(propertyParentIndexC));
if (!idx.isValid()) {
return;
@@ -701,7 +731,7 @@ void FolderStatusModel::slotLscolFinishedWithError(QNetworkReply* r)
if (r->error() == QNetworkReply::ContentNotFoundError) {
parentInfo->_fetched = true;
} else {
Q_ASSERT(!parentInfo->hasLabel());
ASSERT(!parentInfo->hasLabel());
beginInsertRows(idx, 0, 0);
parentInfo->_hasError = true;
endInsertRows();
@@ -981,7 +1011,7 @@ void FolderStatusModel::slotFolderSyncStateChange(Folder *f)
auto& pi = _folders[folderIndex]._progress;
SyncResult::Status state = f->syncResult().status();
if (f->syncPaused()) {
if (!f->canSync()) {
// Reset progress info.
pi = SubFolderInfo::Progress();
} else if (state == SyncResult::NotYetStarted) {
@@ -1012,18 +1042,10 @@ void FolderStatusModel::slotFolderSyncStateChange(Folder *f)
// update the icon etc. now
slotUpdateFolderState(f);
if (state == SyncResult::Success) {
foreach (const SyncFileItemPtr &i, f->syncResult().syncFileItemVector()) {
if (i->_isDirectory && (i->_instruction == CSYNC_INSTRUCTION_NEW
|| i->_instruction == CSYNC_INSTRUCTION_TYPE_CHANGE
|| i->_instruction == CSYNC_INSTRUCTION_REMOVE
|| i->_instruction == CSYNC_INSTRUCTION_RENAME)) {
// There is a new or a removed folder. reset all data
auto & info = _folders[folderIndex];
info.resetSubs(this, index(folderIndex));
return;
}
}
if (state == SyncResult::Success && f->syncResult().folderStructureWasChanged()) {
// There is a new or a removed folder. reset all data
auto & info = _folders[folderIndex];
info.resetSubs(this, index(folderIndex));
}
}
@@ -1114,7 +1136,7 @@ void FolderStatusModel::slotSyncNoPendingBigFolders()
void FolderStatusModel::slotNewBigFolder()
{
auto f = qobject_cast<Folder *>(sender());
Q_ASSERT(f);
ASSERT(f);
int folderIndex = -1;
for (int i = 0; i < _folders.count(); ++i) {
+3 -1
Ver Arquivo
@@ -51,7 +51,7 @@ public:
struct SubFolderInfo {
SubFolderInfo()
: _folder(0), _size(0), _fetched(false), _fetching(false),
: _folder(0), _size(0), _isExternal(false), _fetched(false), _fetching(false),
_hasError(false), _fetchingLabel(false), _isUndecided(false), _checked(Qt::Checked) {}
Folder *_folder;
QString _name;
@@ -59,6 +59,7 @@ public:
QVector<int> _pathIdx;
QVector<SubFolderInfo> _subs;
qint64 _size;
bool _isExternal;
bool _fetched; // If we did the LSCOL for this folder already
bool _fetching; // Whether a LSCOL job is currently running
@@ -113,6 +114,7 @@ public slots:
private slots:
void slotUpdateDirectories(const QStringList &);
void slotGatherPermissions(const QString &name, const QMap<QString,QString> &properties);
void slotLscolFinishedWithError(QNetworkReply *r);
void slotFolderSyncStateChange(Folder* f);
void slotFolderScheduleQueueChanged();
+9 -6
Ver Arquivo
@@ -482,9 +482,8 @@ void FolderWizardRemotePath::showWarn( const QString& msg ) const
FolderWizardSelectiveSync::FolderWizardSelectiveSync(const AccountPtr& account)
{
QVBoxLayout *layout = new QVBoxLayout(this);
_treeView = new SelectiveSyncTreeView(account, this);
layout->addWidget(new QLabel(tr("Choose What to Sync: You can optionally deselect remote subfolders you do not wish to synchronize.")));
layout->addWidget(_treeView);
_selectiveSync = new SelectiveSyncWidget(account, this);
layout->addWidget(_selectiveSync);
}
FolderWizardSelectiveSync::~FolderWizardSelectiveSync()
@@ -501,13 +500,17 @@ void FolderWizardSelectiveSync::initializePage()
QString alias = QFileInfo(targetPath).fileName();
if (alias.isEmpty())
alias = Theme::instance()->appName();
_treeView->setFolderInfo(targetPath, alias);
QStringList initialBlacklist;
if (Theme::instance()->wizardSelectiveSyncDefaultNothing()) {
initialBlacklist = QStringList("/");
}
_selectiveSync->setFolderInfo(targetPath, alias, initialBlacklist);
QWizardPage::initializePage();
}
bool FolderWizardSelectiveSync::validatePage()
{
wizard()->setProperty("selectiveSyncBlackList", QVariant(_treeView->createBlackList()));
wizard()->setProperty("selectiveSyncBlackList", QVariant(_selectiveSync->createBlackList()));
return true;
}
@@ -517,7 +520,7 @@ void FolderWizardSelectiveSync::cleanupPage()
QString alias = QFileInfo(targetPath).fileName();
if (alias.isEmpty())
alias = Theme::instance()->appName();
_treeView->setFolderInfo(targetPath, alias);
_selectiveSync->setFolderInfo(targetPath, alias);
QWizardPage::cleanupPage();
}
+2 -2
Ver Arquivo
@@ -27,7 +27,7 @@
namespace OCC {
class SelectiveSyncTreeView;
class SelectiveSyncWidget;
class ownCloudInfo;
@@ -127,7 +127,7 @@ public:
virtual void cleanupPage() Q_DECL_OVERRIDE;
private:
SelectiveSyncTreeView *_treeView;
SelectiveSyncWidget *_selectiveSync;
};
+20 -2
Ver Arquivo
@@ -32,12 +32,14 @@
#include <QNetworkProxy>
#include <QDir>
#include <QScopedValueRollback>
namespace OCC {
GeneralSettings::GeneralSettings(QWidget *parent) :
QWidget(parent),
_ui(new Ui::GeneralSettings)
_ui(new Ui::GeneralSettings),
_currentlyLoading(false)
{
_ui->setupUi(this);
@@ -66,6 +68,7 @@ GeneralSettings::GeneralSettings(QWidget *parent) :
connect(_ui->crashreporterCheckBox, SIGNAL(toggled(bool)), SLOT(saveMiscSettings()));
connect(_ui->newFolderLimitCheckBox, SIGNAL(toggled(bool)), SLOT(saveMiscSettings()));
connect(_ui->newFolderLimitSpinBox, SIGNAL(valueChanged(int)), SLOT(saveMiscSettings()));
connect(_ui->newExternalStorage, SIGNAL(toggled(bool)), SLOT(saveMiscSettings()));
#ifndef WITH_CRASHREPORTER
_ui->crashreporterCheckBox->setVisible(false);
@@ -85,6 +88,9 @@ GeneralSettings::GeneralSettings(QWidget *parent) :
_ui->monoIconsCheckBox->setVisible(QDir(themeDir).exists());
connect(_ui->ignoredFilesButton, SIGNAL(clicked()), SLOT(slotIgnoreFilesEditor()));
// accountAdded means the wizard was finished and the wizard might change some options.
connect(AccountManager::instance(), SIGNAL(accountAdded(AccountState*)), this, SLOT(loadMiscSettings()));
}
GeneralSettings::~GeneralSettings()
@@ -99,6 +105,12 @@ QSize GeneralSettings::sizeHint() const {
void GeneralSettings::loadMiscSettings()
{
#if QT_VERSION < QT_VERSION_CHECK( 5, 4, 0 )
QScopedValueRollback<bool> scope(_currentlyLoading);
_currentlyLoading = true;
#else
QScopedValueRollback<bool> scope(_currentlyLoading, true);
#endif
ConfigFile cfgFile;
_ui->monoIconsCheckBox->setChecked(cfgFile.monoIcons());
_ui->desktopNotificationsCheckBox->setChecked(cfgFile.optionalDesktopNotifications());
@@ -106,11 +118,14 @@ void GeneralSettings::loadMiscSettings()
auto newFolderLimit = cfgFile.newBigFolderSizeLimit();
_ui->newFolderLimitCheckBox->setChecked(newFolderLimit.first);
_ui->newFolderLimitSpinBox->setValue(newFolderLimit.second);
_ui->newExternalStorage->setChecked(cfgFile.confirmExternalStorage());
_ui->monoIconsCheckBox->setChecked(cfgFile.monoIcons());
}
void GeneralSettings::slotUpdateInfo()
{
OCUpdater *updater = dynamic_cast<OCUpdater*>(Updater::instance());
// Note: the sparkle-updater is not an OCUpdater
OCUpdater *updater = qobject_cast<OCUpdater*>(Updater::instance());
if (ConfigFile().skipUpdateCheck()) {
updater = 0; // don't show update info if updates are disabled
}
@@ -129,6 +144,8 @@ void GeneralSettings::slotUpdateInfo()
void GeneralSettings::saveMiscSettings()
{
if (_currentlyLoading)
return;
ConfigFile cfgFile;
bool isChecked = _ui->monoIconsCheckBox->isChecked();
cfgFile.setMonoIcons(isChecked);
@@ -137,6 +154,7 @@ void GeneralSettings::saveMiscSettings()
cfgFile.setNewBigFolderSizeLimit(_ui->newFolderLimitCheckBox->isChecked(),
_ui->newFolderLimitSpinBox->value());
cfgFile.setConfirmExternalStorage(_ui->newExternalStorage->isChecked());
}
void GeneralSettings::slotToggleLaunchOnStartup(bool enable)
+2 -1
Ver Arquivo
@@ -45,13 +45,14 @@ private slots:
void slotToggleOptionalDesktopNotifications(bool);
void slotUpdateInfo();
void slotIgnoreFilesEditor();
void loadMiscSettings();
private:
void loadMiscSettings();
Ui::GeneralSettings *_ui;
QPointer<IgnoreListEditor> _ignoreEditor;
QPointer<SyncLogDialog> _syncLogDialog;
bool _currentlyLoading;
};
+36 -42
Ver Arquivo
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>706</width>
<width>785</width>
<height>523</height>
</rect>
</property>
@@ -52,33 +52,37 @@
<property name="title">
<string>Advanced</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QPushButton" name="ignoredFilesButton">
<property name="text">
<string>Edit &amp;Ignored Files</string>
</property>
</widget>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QPushButton" name="ignoredFilesButton">
<property name="text">
<string>Edit &amp;Ignored Files</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>555</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="0" column="1" colspan="2">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>555</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" colspan="3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QCheckBox" name="newFolderLimitCheckBox">
<property name="text">
<string>Ask &amp;confirmation before downloading folders larger than</string>
<string>Ask for confirmation before synchronizing folders larger than</string>
</property>
<property name="checked">
<bool>true</bool>
@@ -98,7 +102,7 @@
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>MB</string>
<string extracomment="Trailing part of &quot;Ask confirmation before syncing folder larger than&quot; ">MB</string>
</property>
</widget>
</item>
@@ -117,7 +121,14 @@
</item>
</layout>
</item>
<item row="2" column="0" colspan="2">
<item>
<widget class="QCheckBox" name="newExternalStorage">
<property name="text">
<string>Ask for confirmation before synchronizing external storages</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="crashreporterCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
@@ -130,23 +141,6 @@
</property>
</widget>
</item>
<item row="2" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
+2 -1
Ver Arquivo
@@ -107,7 +107,8 @@ int main(int argc, char **argv)
// if handleStartup returns true, main()
// needs to terminate here, e.g. because
// the updater is triggered
if (Updater::instance()->handleStartup()) {
Updater *updater = Updater::instance();
if ( updater && updater->handleStartup()) {
return true;
}
+2 -1
Ver Arquivo
@@ -15,6 +15,7 @@
#include "notificationwidget.h"
#include "QProgressIndicator.h"
#include "utility.h"
#include "asserts.h"
#include <QPushButton>
@@ -33,8 +34,8 @@ void NotificationWidget::setActivity(const Activity& activity)
{
_myActivity = activity;
Q_ASSERT( !activity._accName.isEmpty() );
_accountName = activity._accName;
ASSERT(!_accountName.isEmpty());
// _ui._headerLabel->setText( );
_ui._subjectLabel->setVisible( !activity._subject.isEmpty() );
+4 -2
Ver Arquivo
@@ -533,9 +533,11 @@ void OwncloudSetupWizard::slotAssistantFinished( int result )
if (f) {
f->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList,
_ocWizard->selectiveSyncBlacklist());
// The user already accepted the selective sync dialog. everything is in the white list
f->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncWhiteList,
if (!_ocWizard->isConfirmBigFolderChecked()) {
// The user already accepted the selective sync dialog. everything is in the white list
f->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncWhiteList,
QStringList() << QLatin1String("/"));
}
}
_ocWizard->appendToConfigurationLog(tr("<font color=\"green\"><b>Local sync folder %1 successfully created!</b></font>").arg(localFolder));
}
+5 -10
Ver Arquivo
@@ -27,7 +27,6 @@
#include "syncfileitem.h"
#include "folder.h"
#include "openfilemanager.h"
#include "owncloudpropagator.h"
#include "activityitemdelegate.h"
#include "ui_protocolwidget.h"
@@ -45,8 +44,8 @@ ProtocolWidget::ProtocolWidget(QWidget *parent) :
connect(ProgressDispatcher::instance(), SIGNAL(progressInfo(QString,ProgressInfo)),
this, SLOT(slotProgressInfo(QString,ProgressInfo)));
connect(ProgressDispatcher::instance(), SIGNAL(itemCompleted(QString,SyncFileItem,PropagatorJob)),
this, SLOT(slotItemCompleted(QString,SyncFileItem,PropagatorJob)));
connect(ProgressDispatcher::instance(), SIGNAL(itemCompleted(QString,SyncFileItemPtr)),
this, SLOT(slotItemCompleted(QString,SyncFileItemPtr)));
connect(_ui->_treeWidget, SIGNAL(itemActivated(QTreeWidgetItem*,int)), SLOT(slotOpenFile(QTreeWidgetItem*,int)));
@@ -222,15 +221,11 @@ void ProtocolWidget::slotProgressInfo( const QString& folder, const ProgressInfo
}
}
void ProtocolWidget::slotItemCompleted(const QString &folder, const SyncFileItem &item, const PropagatorJob &job)
void ProtocolWidget::slotItemCompleted(const QString &folder, const SyncFileItemPtr &item)
{
if (qobject_cast<const PropagateDirectory*>(&job)) {
return;
}
QTreeWidgetItem *line = createCompletedTreewidgetItem(folder, item);
QTreeWidgetItem *line = createCompletedTreewidgetItem(folder, *item);
if(line) {
if( item.hasErrorStatus() ) {
if( item->hasErrorStatus() ) {
_issueItemView->insertTopLevelItem(0, line);
emit issueItemCountUpdated(_issueItemView->topLevelItemCount());
} else {
+1 -1
Ver Arquivo
@@ -52,7 +52,7 @@ public:
public slots:
void slotProgressInfo( const QString& folder, const ProgressInfo& progress );
void slotItemCompleted( const QString& folder, const SyncFileItem& item, const PropagatorJob& job);
void slotItemCompleted( const QString& folder, const SyncFileItemPtr& item);
void slotOpenFile( QTreeWidgetItem* item, int );
protected:
+71 -55
Ver Arquivo
@@ -18,6 +18,7 @@
#include "networkjobs.h"
#include "theme.h"
#include "folderman.h"
#include "configfile.h"
#include <QDialogButtonBox>
#include <QVBoxLayout>
#include <QTreeWidget>
@@ -29,6 +30,7 @@
#include <QScopedValueRollback>
#include <QTreeWidgetItem>
#include <QLabel>
#include <QVBoxLayout>
namespace OCC {
@@ -54,32 +56,48 @@ private:
}
};
SelectiveSyncTreeView::SelectiveSyncTreeView(AccountPtr account, QWidget* parent)
: QTreeWidget(parent), _inserting(false), _account(account)
SelectiveSyncWidget::SelectiveSyncWidget(AccountPtr account, QWidget *parent)
: QWidget(parent)
, _account(account)
, _inserting(false)
, _folderTree(new QTreeWidget(this))
{
_loading = new QLabel(tr("Loading ..."), this);
connect(this, SIGNAL(itemExpanded(QTreeWidgetItem*)), this, SLOT(slotItemExpanded(QTreeWidgetItem*)));
connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(slotItemChanged(QTreeWidgetItem*,int)));
setSortingEnabled(true);
sortByColumn(0, Qt::AscendingOrder);
setColumnCount(2);
_loading = new QLabel(tr("Loading ..."), _folderTree);
auto layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
auto header = new QLabel(this);
header->setText(tr("Deselect remote folders you do not wish to synchronize."));
header->setWordWrap(true);
layout->addWidget(header);
layout->addWidget(_folderTree);
connect(_folderTree, SIGNAL(itemExpanded(QTreeWidgetItem*)),
SLOT(slotItemExpanded(QTreeWidgetItem*)));
connect(_folderTree, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
SLOT(slotItemChanged(QTreeWidgetItem*,int)));
_folderTree->setSortingEnabled(true);
_folderTree->sortByColumn(0, Qt::AscendingOrder);
_folderTree->setColumnCount(2);
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
header()->setSectionResizeMode(0, QHeaderView::QHeaderView::ResizeToContents);
header()->setSectionResizeMode(1, QHeaderView::QHeaderView::ResizeToContents);
_folderTree->header()->setSectionResizeMode(0, QHeaderView::QHeaderView::ResizeToContents);
_folderTree->header()->setSectionResizeMode(1, QHeaderView::QHeaderView::ResizeToContents);
#else
header()->resizeSection(0, sizeHint().width()/2);
_folderTree->header()->resizeSection(0, sizeHint().width()/2);
#endif
header()->setStretchLastSection(true);
headerItem()->setText(0, tr("Name"));
headerItem()->setText(1, tr("Size"));
_folderTree->header()->setStretchLastSection(true);
_folderTree->headerItem()->setText(0, tr("Name"));
_folderTree->headerItem()->setText(1, tr("Size"));
}
QSize SelectiveSyncTreeView::sizeHint() const
QSize SelectiveSyncWidget::sizeHint() const
{
return QTreeView::sizeHint().expandedTo(QSize(400, 400));
return QWidget::sizeHint().expandedTo(QSize(600, 600));
}
void SelectiveSyncTreeView::refreshFolders()
void SelectiveSyncWidget::refreshFolders()
{
LsColJob *job = new LsColJob(_account, _folderPath, this);
job->setProperties(QList<QByteArray>() << "resourcetype" << "http://owncloud.org/ns:size");
@@ -88,12 +106,12 @@ void SelectiveSyncTreeView::refreshFolders()
connect(job, SIGNAL(finishedWithError(QNetworkReply*)),
this, SLOT(slotLscolFinishedWithError(QNetworkReply*)));
job->start();
clear();
_folderTree->clear();
_loading->show();
_loading->move(10,header()->height() + 10);
_loading->move(10, _folderTree->header()->height() + 10);
}
void SelectiveSyncTreeView::setFolderInfo(const QString& folderPath, const QString& rootName, const QStringList& oldBlackList)
void SelectiveSyncWidget::setFolderInfo(const QString& folderPath, const QString& rootName, const QStringList& oldBlackList)
{
_folderPath = folderPath;
if (_folderPath.startsWith(QLatin1Char('/'))) {
@@ -116,7 +134,7 @@ static QTreeWidgetItem* findFirstChild(QTreeWidgetItem *parent, const QString& t
return 0;
}
void SelectiveSyncTreeView::recursiveInsert(QTreeWidgetItem* parent, QStringList pathTrail, QString path, qint64 size)
void SelectiveSyncWidget::recursiveInsert(QTreeWidgetItem* parent, QStringList pathTrail, QString path, qint64 size)
{
QFileIconProvider prov;
QIcon folderIcon = prov.icon(QFileIconProvider::Folder);
@@ -159,13 +177,13 @@ void SelectiveSyncTreeView::recursiveInsert(QTreeWidgetItem* parent, QStringList
}
}
void SelectiveSyncTreeView::slotUpdateDirectories(QStringList list)
void SelectiveSyncWidget::slotUpdateDirectories(QStringList list)
{
auto job = qobject_cast<LsColJob *>(sender());
QScopedValueRollback<bool> isInserting(_inserting);
_inserting = true;
SelectiveSyncTreeViewItem *root = static_cast<SelectiveSyncTreeViewItem*>(topLevelItem(0));
SelectiveSyncTreeViewItem *root = static_cast<SelectiveSyncTreeViewItem*>(_folderTree->topLevelItem(0));
QUrl url = _account->davUrl();
QString pathToRemove = url.path();
@@ -206,15 +224,11 @@ void SelectiveSyncTreeView::slotUpdateDirectories(QStringList list)
}
if (!root) {
root = new SelectiveSyncTreeViewItem(this);
root = new SelectiveSyncTreeViewItem(_folderTree);
root->setText(0, _rootName);
root->setIcon(0, Theme::instance()->applicationIcon());
root->setData(0, Qt::UserRole, QString());
if (_oldBlackList.isEmpty()) {
root->setCheckState(0, Qt::Checked);
} else {
root->setCheckState(0, Qt::PartiallyChecked);
}
root->setCheckState(0, Qt::Checked);
qint64 size = job ? job->_sizes.value(pathToRemove, -1) : -1;
if (size >= 0) {
root->setText(1, Utility::octetsToString(size));
@@ -236,10 +250,19 @@ void SelectiveSyncTreeView::slotUpdateDirectories(QStringList list)
recursiveInsert(root, paths, path, size);
}
// Root is partially checked if any children are not checked
for (int i = 0; i < root->childCount(); ++i) {
const auto child = root->child(i);
if (child->checkState(0) != Qt::Checked) {
root->setCheckState(0, Qt::PartiallyChecked);
break;
}
}
root->setExpanded(true);
}
void SelectiveSyncTreeView::slotLscolFinishedWithError(QNetworkReply *r)
void SelectiveSyncWidget::slotLscolFinishedWithError(QNetworkReply *r)
{
if (r->error() == QNetworkReply::ContentNotFoundError) {
_loading->setText(tr("No subfolders currently on the server."));
@@ -249,7 +272,7 @@ void SelectiveSyncTreeView::slotLscolFinishedWithError(QNetworkReply *r)
_loading->resize(_loading->sizeHint()); // because it's not in a layout
}
void SelectiveSyncTreeView::slotItemExpanded(QTreeWidgetItem *item)
void SelectiveSyncWidget::slotItemExpanded(QTreeWidgetItem *item)
{
QString dir = item->data(0, Qt::UserRole).toString();
if (dir.isEmpty()) return;
@@ -264,7 +287,7 @@ void SelectiveSyncTreeView::slotItemExpanded(QTreeWidgetItem *item)
job->start();
}
void SelectiveSyncTreeView::slotItemChanged(QTreeWidgetItem *item, int col)
void SelectiveSyncWidget::slotItemChanged(QTreeWidgetItem *item, int col)
{
if (col != 0 || _inserting)
return;
@@ -322,10 +345,10 @@ void SelectiveSyncTreeView::slotItemChanged(QTreeWidgetItem *item, int col)
}
}
QStringList SelectiveSyncTreeView::createBlackList(QTreeWidgetItem* root) const
QStringList SelectiveSyncWidget::createBlackList(QTreeWidgetItem* root) const
{
if (!root) {
root = topLevelItem(0);
root = _folderTree->topLevelItem(0);
}
if (!root) return QStringList();
@@ -354,15 +377,15 @@ QStringList SelectiveSyncTreeView::createBlackList(QTreeWidgetItem* root) const
return result;
}
QStringList SelectiveSyncTreeView::oldBlackList() const
QStringList SelectiveSyncWidget::oldBlackList() const
{
return _oldBlackList;
}
qint64 SelectiveSyncTreeView::estimatedSize(QTreeWidgetItem* root)
qint64 SelectiveSyncWidget::estimatedSize(QTreeWidgetItem* root)
{
if (!root) {
root = topLevelItem(0);
root = _folderTree->topLevelItem(0);
}
if (!root) return -1;
@@ -396,10 +419,10 @@ SelectiveSyncDialog::SelectiveSyncDialog(AccountPtr account, Folder* folder, QWi
_okButton(0) // defined in init()
{
bool ok;
init(account, tr("Unchecked folders will be <b>removed</b> from your local file system and will not be synchronized to this computer anymore"));
init(account);
QStringList selectiveSyncList = _folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok);
if( ok ) {
_treeView->setFolderInfo(_folder->remotePath(), _folder->alias(),selectiveSyncList);
_selectiveSync->setFolderInfo(_folder->remotePath(), _folder->alias(),selectiveSyncList);
} else {
_okButton->setEnabled(false);
}
@@ -411,22 +434,16 @@ SelectiveSyncDialog::SelectiveSyncDialog(AccountPtr account, const QString &fold
const QStringList& blacklist, QWidget* parent, Qt::WindowFlags f)
: QDialog(parent, f), _folder(0)
{
init(account,
Theme::instance()->wizardSelectiveSyncDefaultNothing() ?
tr("Choose What to Sync: Select remote subfolders you wish to synchronize.") :
tr("Choose What to Sync: Deselect remote subfolders you do not wish to synchronize."));
_treeView->setFolderInfo(folder, folder, blacklist);
init(account);
_selectiveSync->setFolderInfo(folder, folder, blacklist);
}
void SelectiveSyncDialog::init(const AccountPtr &account, const QString &labelText)
void SelectiveSyncDialog::init(const AccountPtr &account)
{
setWindowTitle(tr("Choose What to Sync"));
QVBoxLayout *layout = new QVBoxLayout(this);
_treeView = new SelectiveSyncTreeView(account, this);
auto label = new QLabel(labelText);
label->setWordWrap(true);
layout->addWidget(label);
layout->addWidget(_treeView);
_selectiveSync = new SelectiveSyncWidget(account, this);
layout->addWidget(_selectiveSync);
QDialogButtonBox *buttonBox = new QDialogButtonBox(Qt::Horizontal);
_okButton = buttonBox->addButton(QDialogButtonBox::Ok);
connect(_okButton, SIGNAL(clicked()), this, SLOT(accept()));
@@ -444,7 +461,7 @@ void SelectiveSyncDialog::accept()
if( ! ok ) {
return;
}
QStringList blackList = _treeView->createBlackList();
QStringList blackList = _selectiveSync->createBlackList();
_folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, blackList);
FolderMan *folderMan = FolderMan::instance();
@@ -467,19 +484,18 @@ void SelectiveSyncDialog::accept()
QStringList SelectiveSyncDialog::createBlackList() const
{
return _treeView->createBlackList();
return _selectiveSync->createBlackList();
}
QStringList SelectiveSyncDialog::oldBlackList() const
{
return _treeView->oldBlackList();
return _selectiveSync->oldBlackList();
}
qint64 SelectiveSyncDialog::estimatedSize()
{
return _treeView->estimatedSize();
return _selectiveSync->estimatedSize();
}
}
+17 -7
Ver Arquivo
@@ -26,40 +26,50 @@ namespace OCC {
class Folder;
/**
* @brief The SelectiveSyncTreeView class
* @brief The SelectiveSyncWidget contains a folder tree with labels
* @ingroup gui
*/
class SelectiveSyncTreeView : public QTreeWidget {
class SelectiveSyncWidget : public QWidget {
Q_OBJECT
public:
explicit SelectiveSyncTreeView(AccountPtr account, QWidget* parent = 0);
explicit SelectiveSyncWidget(AccountPtr account, QWidget* parent = 0);
/// Returns a list of blacklisted paths, each including the trailing /
QStringList createBlackList(QTreeWidgetItem* root = 0) const;
/** Returns the oldBlackList passed into setFolderInfo(), except that
* a "/" entry is expanded to all top-level folder names.
*/
QStringList oldBlackList() const;
// Estimates the total size of checked items (recursively)
qint64 estimatedSize(QTreeWidgetItem *root = 0);
void refreshFolders();
// oldBlackList is a list of excluded paths, each including a trailing /
void setFolderInfo(const QString &folderPath, const QString &rootName,
const QStringList &oldBlackList = QStringList());
QSize sizeHint() const Q_DECL_OVERRIDE;
private slots:
void slotUpdateDirectories(QStringList);
void slotItemExpanded(QTreeWidgetItem *);
void slotItemChanged(QTreeWidgetItem*,int);
void slotLscolFinishedWithError(QNetworkReply*);
private:
void refreshFolders();
void recursiveInsert(QTreeWidgetItem* parent, QStringList pathTrail, QString path, qint64 size);
AccountPtr _account;
QString _folderPath;
QString _rootName;
QStringList _oldBlackList;
bool _inserting; // set to true when we are inserting new items on the list
AccountPtr _account;
QLabel *_loading;
QTreeWidget *_folderTree;
};
/**
@@ -85,9 +95,9 @@ public:
private:
void init(const AccountPtr &account, const QString &label);
void init(const AccountPtr &account);
SelectiveSyncTreeView *_treeView;
SelectiveSyncWidget *_selectiveSync;
Folder *_folder;
QPushButton *_okButton;
+153 -102
Ver Arquivo
@@ -31,9 +31,12 @@
#include "accountstate.h"
#include "account.h"
#include "capabilities.h"
#include "asserts.h"
#include <QBitArray>
#include <QDebug>
#include <QUrl>
#include <QMetaMethod>
#include <QMetaObject>
#include <QStringList>
#include <QScopedPointer>
@@ -56,6 +59,8 @@
// The second number should be changed when there are new features.
#define MIRALL_SOCKET_API_VERSION "1.0"
#define DEBUG qDebug() << "SocketApi: "
static inline QString removeTrailingSlash(QString path)
{
Q_ASSERT(path.endsWith(QLatin1Char('/')));
@@ -63,9 +68,89 @@ static inline QString removeTrailingSlash(QString path)
return path;
}
static QString buildMessage(const QString& verb, const QString &path, const QString &status = QString::null )
{
QString msg(verb);
if( !status.isEmpty() ) {
msg.append(QLatin1Char(':'));
msg.append(status);
}
if( !path.isEmpty() ) {
msg.append(QLatin1Char(':'));
QFileInfo fi(path);
msg.append(QDir::toNativeSeparators(fi.absoluteFilePath()));
}
return msg;
}
namespace OCC {
#define DEBUG qDebug() << "SocketApi: "
class BloomFilter {
// Initialize with m=1024 bits and k=2 (high and low 16 bits of a qHash).
// For a client navigating in less than 100 directories, this gives us a probability less than (1-e^(-2*100/1024))^2 = 0.03147872136 false positives.
const static int NumBits = 1024;
public:
BloomFilter() : hashBits(NumBits) { }
void storeHash(uint hash) {
hashBits.setBit((hash & 0xFFFF) % NumBits);
hashBits.setBit((hash >> 16) % NumBits);
}
bool isHashMaybeStored(uint hash) const {
return hashBits.testBit((hash & 0xFFFF) % NumBits)
&& hashBits.testBit((hash >> 16) % NumBits);
}
private:
QBitArray hashBits;
};
class SocketListener {
public:
QIODevice* socket;
SocketListener(QIODevice* socket = 0) : socket(socket) { }
void sendMessage(const QString& message, bool doWait = false) const
{
DEBUG << "Sending message: " << message;
QString localMessage = message;
if( ! localMessage.endsWith(QLatin1Char('\n'))) {
localMessage.append(QLatin1Char('\n'));
}
QByteArray bytesToSend = localMessage.toUtf8();
qint64 sent = socket->write(bytesToSend);
if( doWait ) {
socket->waitForBytesWritten(1000);
}
if( sent != bytesToSend.length() ) {
qDebug() << "WARN: Could not send all data on socket for " << localMessage;
}
}
void sendMessageIfDirectoryMonitored(const QString& message, uint systemDirectoryHash) const
{
if (_monitoredDirectoriesBloomFilter.isHashMaybeStored(systemDirectoryHash))
sendMessage(message, false);
}
void registerMonitoredDirectory(uint systemDirectoryHash)
{
_monitoredDirectoriesBloomFilter.storeHash(systemDirectoryHash);
}
private:
BloomFilter _monitoredDirectoriesBloomFilter;
};
struct ListenerHasSocketPred {
QIODevice *socket;
ListenerHasSocketPred(QIODevice *socket) : socket(socket) { }
bool operator()(const SocketListener &listener) const { return listener.socket == socket; }
};
SocketApi::SocketApi(QObject* parent)
: QObject(parent)
@@ -129,7 +214,7 @@ SocketApi::~SocketApi()
DEBUG << "dtor";
_localServer.close();
// All remaining sockets will be destroyed with _localServer, their parent
Q_ASSERT(_listeners.isEmpty() || _listeners.first()->parent() == &_localServer);
ASSERT(_listeners.isEmpty() || _listeners.first().socket->parent() == &_localServer);
_listeners.clear();
}
@@ -143,14 +228,16 @@ void SocketApi::slotNewConnection()
DEBUG << "New connection" << socket;
connect(socket, SIGNAL(readyRead()), this, SLOT(slotReadSocket()));
connect(socket, SIGNAL(disconnected()), this, SLOT(onLostConnection()));
Q_ASSERT(socket->readAll().isEmpty());
connect(socket, SIGNAL(destroyed(QObject*)), this, SLOT(slotSocketDestroyed(QObject*)));
ASSERT(socket->readAll().isEmpty());
_listeners.append(socket);
_listeners.append(SocketListener(socket));
SocketListener &listener = _listeners.last();
foreach( Folder *f, FolderMan::instance()->map() ) {
if (f->canSync()) {
QString message = buildRegisterPathMessage(removeTrailingSlash(f->path()));
sendMessage(socket, message);
listener.sendMessage(message);
}
}
}
@@ -158,32 +245,33 @@ void SocketApi::slotNewConnection()
void SocketApi::onLostConnection()
{
DEBUG << "Lost connection " << sender();
QIODevice* socket = qobject_cast<QIODevice*>(sender());
_listeners.removeAll(socket);
socket->deleteLater();
sender()->deleteLater();
}
void SocketApi::slotSocketDestroyed(QObject* obj)
{
QIODevice* socket = static_cast<QIODevice*>(obj);
_listeners.erase(std::remove_if(_listeners.begin(), _listeners.end(), ListenerHasSocketPred(socket)), _listeners.end());
}
void SocketApi::slotReadSocket()
{
QIODevice* socket = qobject_cast<QIODevice*>(sender());
Q_ASSERT(socket);
ASSERT(socket);
SocketListener *listener = &*std::find_if(_listeners.begin(), _listeners.end(), ListenerHasSocketPred(socket));
while(socket->canReadLine()) {
// Make sure to normalize the input from the socket to
// make sure that the path will match, especially on OS X.
QString line = QString::fromUtf8(socket->readLine()).normalized(QString::NormalizationForm_C);
line.chop(1); // remove the '\n'
QString command = line.split(":").value(0);
QString function = QString(QLatin1String("command_")).append(command);
QString functionWithArguments = function + QLatin1String("(QString,QIODevice*)");
int indexOfMethod = this->metaObject()->indexOfMethod(functionWithArguments.toAscii());
QByteArray command = line.split(":").value(0).toAscii();
QByteArray functionWithArguments = "command_" + command + "(QString,SocketListener*)";
int indexOfMethod = staticMetaObject.indexOfMethod(functionWithArguments);
QString argument = line.remove(0, command.length()+1);
if(indexOfMethod != -1) {
QMetaObject::invokeMethod(this, function.toAscii(), Q_ARG(QString, argument), Q_ARG(QIODevice*, socket));
staticMetaObject.method(indexOfMethod).invoke(this, Q_ARG(QString, argument), Q_ARG(SocketListener*, listener));
} else {
DEBUG << "The command is not supported by this version of the client:" << command << "with argument:" << argument;
}
@@ -199,8 +287,8 @@ void SocketApi::slotRegisterPath( const QString& alias )
Folder *f = FolderMan::instance()->folder(alias);
if (f) {
QString message = buildRegisterPathMessage(removeTrailingSlash(f->path()));
foreach(QIODevice *socket, _listeners) {
sendMessage(socket, message);
foreach (auto &listener, _listeners) {
listener.sendMessage(message);
}
}
@@ -214,7 +302,7 @@ void SocketApi::slotUnregisterPath( const QString& alias )
Folder *f = FolderMan::instance()->folder(alias);
if (f)
broadcastMessage(QLatin1String("UNREGISTER_PATH"), removeTrailingSlash(f->path()), QString::null, true );
broadcastMessage(buildMessage(QLatin1String("UNREGISTER_PATH"), removeTrailingSlash(f->path()), QString::null), true);
_registeredAliases.remove(alias);
}
@@ -235,74 +323,42 @@ void SocketApi::slotUpdateFolderView(Folder *f)
f->syncResult().status() == SyncResult::SetupError ) {
QString rootPath = removeTrailingSlash(f->path());
broadcastMessage(QLatin1String("STATUS"), rootPath,
f->syncEngine().syncFileStatusTracker().fileStatus("").toSocketAPIString());
broadcastStatusPushMessage(rootPath, f->syncEngine().syncFileStatusTracker().fileStatus(""));
broadcastMessage(QLatin1String("UPDATE_VIEW"), rootPath);
broadcastMessage(buildMessage(QLatin1String("UPDATE_VIEW"), rootPath));
} else {
qDebug() << "Not sending UPDATE_VIEW for" << f->alias() << "because status() is" << f->syncResult().status();
}
}
}
void SocketApi::slotFileStatusChanged(const QString& systemFileName, SyncFileStatus fileStatus)
void SocketApi::broadcastMessage(const QString& msg, bool doWait)
{
broadcastMessage(QLatin1String("STATUS"), systemFileName, fileStatus.toSocketAPIString());
}
void SocketApi::sendMessage(QIODevice *socket, const QString& message, bool doWait)
{
DEBUG << "Sending message: " << message;
QString localMessage = message;
if( ! localMessage.endsWith(QLatin1Char('\n'))) {
localMessage.append(QLatin1Char('\n'));
}
QByteArray bytesToSend = localMessage.toUtf8();
qint64 sent = socket->write(bytesToSend);
if( doWait ) {
socket->waitForBytesWritten(1000);
}
if( sent != bytesToSend.length() ) {
qDebug() << "WARN: Could not send all data on socket for " << localMessage;
}
}
void SocketApi::broadcastMessage( const QString& verb, const QString& path, const QString& status, bool doWait )
{
QString msg(verb);
if( !status.isEmpty() ) {
msg.append(QLatin1Char(':'));
msg.append(status);
}
if( !path.isEmpty() ) {
msg.append(QLatin1Char(':'));
QFileInfo fi(path);
msg.append(QDir::toNativeSeparators(fi.absoluteFilePath()));
}
foreach(QIODevice *socket, _listeners) {
sendMessage(socket, msg, doWait);
foreach (auto &listener, _listeners) {
listener.sendMessage(msg, doWait);
}
}
void SocketApi::command_RETRIEVE_FOLDER_STATUS(const QString& argument, QIODevice* socket)
void SocketApi::broadcastStatusPushMessage(const QString& systemPath, SyncFileStatus fileStatus)
{
QString msg = buildMessage(QLatin1String("STATUS"), systemPath, fileStatus.toSocketAPIString());
Q_ASSERT(!systemPath.endsWith('/'));
uint directoryHash = qHash(systemPath.left(systemPath.lastIndexOf('/')));
foreach (auto &listener, _listeners) {
listener.sendMessageIfDirectoryMonitored(msg, directoryHash);
}
}
void SocketApi::command_RETRIEVE_FOLDER_STATUS(const QString& argument, SocketListener* listener)
{
// This command is the same as RETRIEVE_FILE_STATUS
//qDebug() << Q_FUNC_INFO << argument;
command_RETRIEVE_FILE_STATUS(argument, socket);
command_RETRIEVE_FILE_STATUS(argument, listener);
}
void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, QIODevice* socket)
void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, SocketListener* listener)
{
if( !socket ) {
qDebug() << "No valid socket object.";
return;
}
qDebug() << Q_FUNC_INFO << argument;
QString statusString;
@@ -312,27 +368,27 @@ void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, QIODevice*
// this can happen in offline mode e.g.: nothing to worry about
statusString = QLatin1String("NOP");
} else {
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.";
QString systemPath = QDir::cleanPath(argument);
if( systemPath.endsWith(QLatin1Char('/')) ) {
systemPath.truncate(systemPath.length()-1);
qWarning() << "Removed trailing slash for directory: " << systemPath << "Status pushes won't have one.";
}
SyncFileStatus fileStatus = syncFolder->syncEngine().syncFileStatusTracker().fileStatus(relativePath);
// The user probably visited this directory in the file shell.
// Let the listener know that it should now send status pushes for sibblings of this file.
QString directory = systemPath.left(systemPath.lastIndexOf('/'));
listener->registerMonitoredDirectory(qHash(directory));
QString relativePath = systemPath.mid(syncFolder->cleanPath().length()+1);
SyncFileStatus fileStatus = syncFolder->syncEngine().syncFileStatusTracker().fileStatus(relativePath);
statusString = fileStatus.toSocketAPIString();
}
const QString message = QLatin1String("STATUS:") % statusString % QLatin1Char(':') % QDir::toNativeSeparators(argument);
sendMessage(socket, message);
listener->sendMessage(message);
}
void SocketApi::command_SHARE(const QString& localFile, QIODevice* socket)
void SocketApi::command_SHARE(const QString& localFile, SocketListener* listener)
{
if (!socket) {
qDebug() << Q_FUNC_INFO << "No valid socket object.";
return;
}
qDebug() << Q_FUNC_INFO << localFile;
auto theme = Theme::instance();
@@ -341,16 +397,16 @@ void SocketApi::command_SHARE(const QString& localFile, QIODevice* socket)
if (!shareFolder) {
const QString message = QLatin1String("SHARE:NOP:")+QDir::toNativeSeparators(localFile);
// files that are not within a sync folder are not synced.
sendMessage(socket, message);
listener->sendMessage(message);
} else if (!shareFolder->accountState()->isConnected()) {
const QString message = QLatin1String("SHARE:NOTCONNECTED:")+QDir::toNativeSeparators(localFile);
// if the folder isn't connected, don't open the share dialog
sendMessage(socket, message);
listener->sendMessage(message);
} else if (!theme->linkSharing() && (
!theme->userGroupSharing() ||
shareFolder->accountState()->account()->serverVersionInt() < ((8 << 16) + (2 << 8)))) {
const QString message = QLatin1String("SHARE:NOP:")+QDir::toNativeSeparators(localFile);
sendMessage(socket, message);
listener->sendMessage(message);
} else {
const QString localFileClean = QDir::cleanPath(localFile);
const QString file = localFileClean.mid(shareFolder->cleanPath().length()+1);
@@ -359,7 +415,7 @@ void SocketApi::command_SHARE(const QString& localFile, QIODevice* socket)
// Verify the file is on the server (to our knowledge of course)
if (fileStatus.tag() != SyncFileStatus::StatusUpToDate) {
const QString message = QLatin1String("SHARE:NOTSYNCED:")+QDir::toNativeSeparators(localFile);
sendMessage(socket, message);
listener->sendMessage(message);
return;
}
@@ -368,7 +424,7 @@ void SocketApi::command_SHARE(const QString& localFile, QIODevice* socket)
// Can't share root folder
if (remotePath == "/") {
const QString message = QLatin1String("SHARE:CANNOTSHAREROOT:")+QDir::toNativeSeparators(localFile);
sendMessage(socket, message);
listener->sendMessage(message);
return;
}
@@ -382,31 +438,26 @@ void SocketApi::command_SHARE(const QString& localFile, QIODevice* socket)
}
}
const QString message = QLatin1String("SHARE:OK:")+QDir::toNativeSeparators(localFile);
sendMessage(socket, message);
listener->sendMessage(message);
emit shareCommandReceived(remotePath, localFileClean, allowReshare);
}
}
void SocketApi::command_VERSION(const QString&, QIODevice* socket)
void SocketApi::command_VERSION(const QString&, SocketListener* listener)
{
sendMessage(socket, QLatin1String("VERSION:" MIRALL_VERSION_STRING ":" MIRALL_SOCKET_API_VERSION));
listener->sendMessage(QLatin1String("VERSION:" MIRALL_VERSION_STRING ":" MIRALL_SOCKET_API_VERSION));
}
void SocketApi::command_SHARE_STATUS(const QString &localFile, QIODevice *socket)
void SocketApi::command_SHARE_STATUS(const QString &localFile, SocketListener* listener)
{
if (!socket) {
qDebug() << Q_FUNC_INFO << "No valid socket object.";
return;
}
qDebug() << Q_FUNC_INFO << localFile;
Folder *shareFolder = FolderMan::instance()->folderForPath(localFile);
if (!shareFolder) {
const QString message = QLatin1String("SHARE_STATUS:NOP:")+QDir::toNativeSeparators(localFile);
sendMessage(socket, message);
listener->sendMessage(message);
} else {
const QString file = QDir::cleanPath(localFile).mid(shareFolder->cleanPath().length()+1);
SyncFileStatus fileStatus = shareFolder->syncEngine().syncFileStatusTracker().fileStatus(file);
@@ -414,7 +465,7 @@ void SocketApi::command_SHARE_STATUS(const QString &localFile, QIODevice *socket
// Verify the file is on the server (to our knowledge of course)
if (fileStatus.tag() != SyncFileStatus::StatusUpToDate) {
const QString message = QLatin1String("SHARE_STATUS:NOTSYNCED:")+QDir::toNativeSeparators(localFile);
sendMessage(socket, message);
listener->sendMessage(message);
return;
}
@@ -422,7 +473,7 @@ void SocketApi::command_SHARE_STATUS(const QString &localFile, QIODevice *socket
if (!capabilities.shareAPI()) {
const QString message = QLatin1String("SHARE_STATUS:DISABLED:")+QDir::toNativeSeparators(localFile);
sendMessage(socket, message);
listener->sendMessage(message);
} else {
auto theme = Theme::instance();
QString available;
@@ -441,18 +492,18 @@ void SocketApi::command_SHARE_STATUS(const QString &localFile, QIODevice *socket
if (available.isEmpty()) {
const QString message = QLatin1String("SHARE_STATUS:DISABLED") + ":" + QDir::toNativeSeparators(localFile);
sendMessage(socket, message);
listener->sendMessage(message);
} else {
const QString message = QLatin1String("SHARE_STATUS:") + available + ":" + QDir::toNativeSeparators(localFile);
sendMessage(socket, message);
listener->sendMessage(message);
}
}
}
}
void SocketApi::command_SHARE_MENU_TITLE(const QString &, QIODevice* socket)
void SocketApi::command_SHARE_MENU_TITLE(const QString &, SocketListener* listener)
{
sendMessage(socket, QLatin1String("SHARE_MENU_TITLE:") + tr("Share with %1", "parameter is ownCloud").arg(Theme::instance()->appNameGUI()));
listener->sendMessage(QLatin1String("SHARE_MENU_TITLE:") + tr("Share with %1", "parameter is ownCloud").arg(Theme::instance()->appNameGUI()));
}
QString SocketApi::buildRegisterPathMessage(const QString& path)
+11 -10
Ver Arquivo
@@ -35,6 +35,7 @@ namespace OCC {
class SyncFileStatus;
class Folder;
class SocketListener;
/**
* @brief The SocketApi class
@@ -60,25 +61,25 @@ signals:
private slots:
void slotNewConnection();
void onLostConnection();
void slotSocketDestroyed(QObject* obj);
void slotReadSocket();
void slotFileStatusChanged(const QString& systemFileName, SyncFileStatus fileStatus);
void broadcastStatusPushMessage(const QString& systemPath, SyncFileStatus fileStatus);
private:
void sendMessage(QIODevice* socket, const QString& message, bool doWait = false);
void broadcastMessage(const QString& verb, const QString &path, const QString &status = QString::null, bool doWait = false);
void broadcastMessage(const QString& msg, bool doWait = false);
Q_INVOKABLE void command_RETRIEVE_FOLDER_STATUS(const QString& argument, QIODevice* socket);
Q_INVOKABLE void command_RETRIEVE_FILE_STATUS(const QString& argument, QIODevice* socket);
Q_INVOKABLE void command_SHARE(const QString& localFile, QIODevice* socket);
Q_INVOKABLE void command_RETRIEVE_FOLDER_STATUS(const QString& argument, SocketListener* listener);
Q_INVOKABLE void command_RETRIEVE_FILE_STATUS(const QString& argument, SocketListener* listener);
Q_INVOKABLE void command_SHARE(const QString& localFile, SocketListener* listener);
Q_INVOKABLE void command_VERSION(const QString& argument, QIODevice* socket);
Q_INVOKABLE void command_VERSION(const QString& argument, SocketListener* listener);
Q_INVOKABLE void command_SHARE_STATUS(const QString& localFile, QIODevice *socket);
Q_INVOKABLE void command_SHARE_MENU_TITLE(const QString& argument, QIODevice* socket);
Q_INVOKABLE void command_SHARE_STATUS(const QString& localFile, SocketListener* listener);
Q_INVOKABLE void command_SHARE_MENU_TITLE(const QString& argument, SocketListener* listener);
QString buildRegisterPathMessage(const QString& path);
QSet<QString> _registeredAliases;
QList<QIODevice*> _listeners;
QList<SocketListener> _listeners;
SocketApiServer _localServer;
};
+7 -7
Ver Arquivo
@@ -145,18 +145,18 @@ void SyncRunFileLog::logItem( const SyncFileItem& item )
const QChar L = QLatin1Char('|');
_out << ts << L;
_out << QString::number(item._requestDuration) << L;
if( item.log._instruction != CSYNC_INSTRUCTION_RENAME ) {
_out << L;
if( item._instruction != CSYNC_INSTRUCTION_RENAME ) {
_out << item._file << L;
} else {
_out << item._file << QLatin1String(" -> ") << item._renameTarget << L;
}
_out << instructionToStr( item.log._instruction ) << L;
_out << instructionToStr( item._instruction ) << L;
_out << directionToStr( item._direction ) << L;
_out << QString::number(item.log._modtime) << L;
_out << item.log._etag << L;
_out << QString::number(item.log._size) << L;
_out << item.log._fileId << L;
_out << QString::number(item._modtime) << L;
_out << item._etag << L;
_out << QString::number(item._size) << L;
_out << item._fileId << L;
_out << item._status << L;
_out << item._errorString << L;
_out << QString::number(item._httpErrorCode) << L;
+13 -10
Ver Arquivo
@@ -19,6 +19,7 @@
#include "updater/ocupdater.h"
#include <QObject>
#include <QtCore>
#include <QtNetwork>
#include <QtGui>
@@ -43,9 +44,8 @@ UpdaterScheduler::UpdaterScheduler(QObject *parent) :
connect( &_updateCheckTimer, SIGNAL(timeout()),
this, SLOT(slotTimerFired()) );
// Note: the sparkle-updater is not an OCUpdater and thus the dynamic_cast
// returns NULL. Clever detail.
if (OCUpdater *updater = dynamic_cast<OCUpdater*>(Updater::instance())) {
// Note: the sparkle-updater is not an OCUpdater
if (OCUpdater *updater = qobject_cast<OCUpdater*>(Updater::instance())) {
connect(updater, SIGNAL(newUpdateAvailable(QString,QString)),
this, SIGNAL(updaterAnnouncement(QString,QString)) );
connect(updater, SIGNAL(requestRestart()), SIGNAL(requestRestart()));
@@ -76,14 +76,17 @@ void UpdaterScheduler::slotTimerFired()
return;
}
Updater::instance()->backgroundCheckForUpdate();
Updater *updater = Updater::instance();
if (updater) {
updater->backgroundCheckForUpdate();
}
}
/* ----------------------------------------------------------------- */
OCUpdater::OCUpdater(const QUrl &url, QObject *parent) :
QObject(parent)
OCUpdater::OCUpdater(const QUrl &url) :
Updater()
, _updateUrl(url)
, _state(Unknown)
, _accessManager(new AccessManager(this))
@@ -242,8 +245,8 @@ void OCUpdater::slotTimedOut()
////////////////////////////////////////////////////////////////////////
NSISUpdater::NSISUpdater(const QUrl &url, QObject *parent)
: OCUpdater(url, parent)
NSISUpdater::NSISUpdater(const QUrl &url)
: OCUpdater(url)
, _showFallbackMessage(false)
{
}
@@ -421,8 +424,8 @@ void NSISUpdater::slotSetSeenVersion()
////////////////////////////////////////////////////////////////////////
PassiveUpdateNotifier::PassiveUpdateNotifier(const QUrl &url, QObject *parent)
: OCUpdater(url, parent)
PassiveUpdateNotifier::PassiveUpdateNotifier(const QUrl &url)
: OCUpdater(url)
{
// remember the version of the currently running binary. On Linux it might happen that the
// package management updates the package while the app is running. This is detected in the
+4 -4
Ver Arquivo
@@ -86,7 +86,7 @@ private:
* @brief Class that uses an ownCloud proprietary XML format to fetch update information
* @ingroup gui
*/
class OCUpdater : public QObject, public Updater
class OCUpdater : public Updater
{
Q_OBJECT
public:
@@ -94,7 +94,7 @@ public:
Downloading, DownloadComplete,
DownloadFailed, DownloadTimedOut,
UpdateOnlyAvailableThroughSystem };
explicit OCUpdater(const QUrl &url, QObject *parent = 0);
explicit OCUpdater(const QUrl &url);
bool performUpdate();
@@ -141,7 +141,7 @@ class NSISUpdater : public OCUpdater {
Q_OBJECT
public:
enum UpdateState { NoUpdate = 0, UpdateAvailable, UpdateFailed };
explicit NSISUpdater(const QUrl &url, QObject *parent = 0);
explicit NSISUpdater(const QUrl &url);
bool handleStartup() Q_DECL_OVERRIDE;
private slots:
void slotSetSeenVersion();
@@ -167,7 +167,7 @@ private:
class PassiveUpdateNotifier : public OCUpdater {
Q_OBJECT
public:
explicit PassiveUpdateNotifier(const QUrl &url, QObject *parent = 0);
explicit PassiveUpdateNotifier(const QUrl &url);
bool handleStartup() Q_DECL_OVERRIDE { return false; }
void backgroundCheckForUpdate() Q_DECL_OVERRIDE;
+4
Ver Arquivo
@@ -87,6 +87,10 @@ Updater *Updater::create()
if (updateBaseUrl.isEmpty()) {
updateBaseUrl = QUrl(QLatin1String(APPLICATION_UPDATE_URL));
}
if (!updateBaseUrl.isValid() || updateBaseUrl.host() == ".") {
qDebug() << "Not a valid updater URL, will not do update check";
return 0;
}
updateBaseUrl = addQueryParams(updateBaseUrl);
#if defined(Q_OS_MAC) && defined(HAVE_SPARKLE)
updateBaseUrl.addQueryItem( QLatin1String("sparkle"), QLatin1String("true"));
+3 -1
Ver Arquivo
@@ -21,7 +21,8 @@ class QUrl;
namespace OCC {
class Updater {
class Updater : public QObject {
Q_OBJECT
public:
struct Helper {
static qint64 stringVersionToInt(const QString& version);
@@ -37,6 +38,7 @@ public:
protected:
static QString clientVersion();
Updater() : QObject(0) {}
private:
static QString getSystemInfo();
+27
Ver Arquivo
@@ -68,6 +68,15 @@ OwncloudAdvancedSetupPage::OwncloudAdvancedSetupPage()
_ui.lServerIcon->setPixmap(appIcon.pixmap(48));
_ui.lLocalIcon->setText(QString());
_ui.lLocalIcon->setPixmap(QPixmap(Theme::hidpiFileName(":/client/resources/folder-sync.png")));
if (theme->wizardHideExternalStorageConfirmationCheckbox()) {
_ui.confCheckBoxExternal->hide();
}
if (theme->wizardHideFolderSizeLimitCheckbox()) {
_ui.confCheckBoxSize->hide();
_ui.confSpinBox->hide();
_ui.confTraillingSizeLabel->hide();
}
}
void OwncloudAdvancedSetupPage::setupCustomization()
@@ -118,6 +127,12 @@ void OwncloudAdvancedSetupPage::initializePage()
_selectiveSyncBlacklist = QStringList("/");
QTimer::singleShot(0, this, SLOT(slotSelectiveSyncClicked()));
}
ConfigFile cfgFile;
auto newFolderLimit = cfgFile.newBigFolderSizeLimit();
_ui.confCheckBoxSize->setChecked(newFolderLimit.first);
_ui.confSpinBox->setValue(newFolderLimit.second);
_ui.confCheckBoxExternal->setChecked(cfgFile.confirmExternalStorage());
}
// Called if the user changes the user- or url field. Adjust the texts and
@@ -200,6 +215,11 @@ QStringList OwncloudAdvancedSetupPage::selectiveSyncBlacklist() const
return _selectiveSyncBlacklist;
}
bool OwncloudAdvancedSetupPage::isConfirmBigFolderChecked() const
{
return _ui.rSyncEverything->isChecked() && _ui.confCheckBoxSize->isChecked();
}
bool OwncloudAdvancedSetupPage::validatePage()
{
if(!_created) {
@@ -208,6 +228,13 @@ bool OwncloudAdvancedSetupPage::validatePage()
startSpinner();
emit completeChanged();
if (_ui.rSyncEverything->isChecked()) {
ConfigFile cfgFile;
cfgFile.setNewBigFolderSizeLimit(_ui.confCheckBoxSize->isChecked(),
_ui.confSpinBox->value());
cfgFile.setConfirmExternalStorage(_ui.confCheckBoxExternal->isChecked());
}
emit createLocalAndRemoteFolders(localFolder(), _remoteFolder);
return false;
} else {
+1
Ver Arquivo
@@ -41,6 +41,7 @@ public:
bool validatePage() Q_DECL_OVERRIDE;
QString localFolder() const;
QStringList selectiveSyncBlacklist() const;
bool isConfirmBigFolderChecked() const;
void setRemoteFolder( const QString& remoteFolder);
void setMultipleFoldersExist( bool exist );
void directoriesCreated();
+133 -7
Ver Arquivo
@@ -6,12 +6,12 @@
<rect>
<x>0</x>
<y>0</y>
<width>917</width>
<height>493</height>
<width>912</width>
<height>633</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -226,11 +226,14 @@
<item row="0" column="1" colspan="2">
<widget class="QWidget" name="widget" native="true">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="rSyncEverything">
<property name="text">
@@ -263,6 +266,64 @@
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_2">
<property name="horizontalSpacing">
<number>0</number>
</property>
<item row="0" column="0">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QCheckBox" name="confCheckBoxSize">
<property name="text">
<string>Ask for confirmation before synchroni&amp;zing folders larger than</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="confSpinBox">
<property name="maximum">
<number>999999</number>
</property>
<property name="value">
<number>99</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="confTraillingSizeLabel">
<property name="text">
<string extracomment="Trailing part of &quot;Ask confirmation before syncing folder larger than&quot; ">MB</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="confCheckBoxExternal">
<property name="text">
<string>Ask for confirmation before synchronizing e&amp;xternal storages</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
@@ -345,5 +406,70 @@
</layout>
</widget>
<resources/>
<connections/>
<connections>
<connection>
<sender>rSyncEverything</sender>
<signal>toggled(bool)</signal>
<receiver>confCheckBoxSize</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>217</x>
<y>78</y>
</hint>
<hint type="destinationlabel">
<x>298</x>
<y>126</y>
</hint>
</hints>
</connection>
<connection>
<sender>rSyncEverything</sender>
<signal>toggled(bool)</signal>
<receiver>confSpinBox</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>311</x>
<y>83</y>
</hint>
<hint type="destinationlabel">
<x>952</x>
<y>134</y>
</hint>
</hints>
</connection>
<connection>
<sender>rSyncEverything</sender>
<signal>toggled(bool)</signal>
<receiver>confTraillingSizeLabel</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>277</x>
<y>76</y>
</hint>
<hint type="destinationlabel">
<x>1076</x>
<y>136</y>
</hint>
</hints>
</connection>
<connection>
<sender>rSyncEverything</sender>
<signal>toggled(bool)</signal>
<receiver>confCheckBoxExternal</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>181</x>
<y>78</y>
</hint>
<hint type="destinationlabel">
<x>382</x>
<y>174</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+7 -4
Ver Arquivo
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>602</width>
<height>193</height>
<width>506</width>
<height>515</height>
</rect>
</property>
<property name="sizePolicy">
@@ -80,7 +80,7 @@
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Server &amp;Address</string>
<string>Ser&amp;ver Address</string>
</property>
<property name="buddy">
<cstring>leUrl</cstring>
@@ -166,10 +166,13 @@
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
<height>200</height>
</size>
</property>
</spacer>
@@ -44,6 +44,7 @@ void OwncloudShibbolethCredsPage::setupBrowser()
// i.e. if someone presses "back"
QNetworkAccessManager *qnam = account->networkAccessManager();
CookieJar *jar = new CookieJar;
jar->restore(account->cookieJarPath());
// Implicitly deletes the old cookie jar, and reparents the jar
qnam->setCookieJar(jar);
+4 -1
Ver Arquivo
@@ -86,7 +86,6 @@ OwncloudWizard::OwncloudWizard(QWidget *parent)
setTitleFormat(Qt::RichText);
setSubTitleFormat(Qt::RichText);
setButtonText(QWizard::CustomButton1, tr("Skip folders configuration"));
}
void OwncloudWizard::setAccount(AccountPtr account)
@@ -109,6 +108,10 @@ QStringList OwncloudWizard::selectiveSyncBlacklist() const
return _advancedSetupPage->selectiveSyncBlacklist();
}
bool OwncloudWizard::isConfirmBigFolderChecked() const
{
return _advancedSetupPage->isConfirmBigFolderChecked();
}
QString OwncloudWizard::ocUrl() const
{
+1
Ver Arquivo
@@ -59,6 +59,7 @@ public:
QString ocUrl() const;
QString localFolder() const;
QStringList selectiveSyncBlacklist() const;
bool isConfirmBigFolderChecked() const;
void enableFinishOnResultWidget(bool enable);
-8
Ver Arquivo
@@ -172,7 +172,6 @@ void AbstractNetworkJob::slotFinished()
// get the Date timestamp from reply
_responseTimestamp = _reply->rawHeader("Date");
_duration = _durationTimer.elapsed();
if (_followRedirects) {
// ### the qWarnings here should be exported via displayErrors() so they
@@ -206,11 +205,6 @@ void AbstractNetworkJob::slotFinished()
}
}
quint64 AbstractNetworkJob::duration()
{
return _duration;
}
QByteArray AbstractNetworkJob::responseTimestamp()
{
return _responseTimestamp;
@@ -224,8 +218,6 @@ AbstractNetworkJob::~AbstractNetworkJob()
void AbstractNetworkJob::start()
{
_timer.start();
_durationTimer.start();
_duration = 0;
const QUrl url = account()->url();
const QString displayUrl = QString( "%1://%2%3").arg(url.scheme()).arg(url.host()).arg(url.path());
-3
Ver Arquivo
@@ -55,7 +55,6 @@ public:
bool ignoreCredentialFailure() const { return _ignoreCredentialFailure; }
QByteArray responseTimestamp();
quint64 duration();
qint64 timeoutMsec() { return _timer.interval(); }
@@ -82,8 +81,6 @@ protected:
int maxRedirects() const { return 10; }
virtual bool finished() = 0;
QByteArray _responseTimestamp;
QElapsedTimer _durationTimer;
quint64 _duration;
bool _timedout; // set to true when the timeout slot is received
// Automatically follows redirects. Note that this only works for
+10 -2
Ver Arquivo
@@ -20,6 +20,7 @@
#include "creds/abstractcredentials.h"
#include "capabilities.h"
#include "theme.h"
#include "asserts.h"
#include <QSettings>
#include <QMutex>
@@ -153,8 +154,9 @@ QUrl Account::davUrl() const
*/
void Account::clearCookieJar()
{
Q_ASSERT(qobject_cast<CookieJar*>(_am->cookieJar()));
static_cast<CookieJar*>(_am->cookieJar())->setAllCookies(QList<QNetworkCookie>());
auto jar = qobject_cast<CookieJar*>(_am->cookieJar());
ASSERT(jar);
jar->setAllCookies(QList<QNetworkCookie>());
emit wantsAccountSaved(this);
}
@@ -169,6 +171,12 @@ void Account::lendCookieJarTo(QNetworkAccessManager *guest)
jar->setParent(oldParent); // takes it back
}
QString Account::cookieJarPath()
{
ConfigFile cfg;
return cfg.configPath() + "/cookies" + id() + ".db";
}
void Account::resetNetworkAccessManager()
{
if (!_credentials || !_am) {
+1
Ver Arquivo
@@ -172,6 +172,7 @@ public:
void clearCookieJar();
void lendCookieJarTo(QNetworkAccessManager *guest);
QString cookieJarPath();
void resetNetworkAccessManager();
QNetworkAccessManager* networkAccessManager();
+52
Ver Arquivo
@@ -0,0 +1,52 @@
#ifndef OWNCLOUD_ASSERTS_H
#define OWNCLOUD_ASSERTS_H
#include <qglobal.h>
#if defined(QT_FORCE_ASSERTS) || !defined(QT_NO_DEBUG)
#define OC_ASSERT_MSG qFatal
#else
#define OC_ASSERT_MSG qWarning
#endif
// For overloading macros by argument count
// See stackoverflow.com/questions/16683146/can-macros-be-overloaded-by-number-of-arguments
#define OC_ASSERT_CAT(A, B) A ## B
#define OC_ASSERT_SELECT(NAME, NUM) OC_ASSERT_CAT(NAME ## _, NUM)
#define OC_ASSERT_GET_COUNT(_1, _2, _3, COUNT, ...) COUNT
#define OC_ASSERT_VA_SIZE(...) OC_ASSERT_GET_COUNT(__VA_ARGS__, 3, 2, 1, 0)
#define OC_ASSERT_OVERLOAD(NAME, ...) OC_ASSERT_SELECT(NAME, OC_ASSERT_VA_SIZE(__VA_ARGS__))(__VA_ARGS__)
// Default assert: If the condition is false in debug builds, terminate.
//
// Prints a message on failure, even in release builds.
#define ASSERT(...) OC_ASSERT_OVERLOAD(ASSERT, __VA_ARGS__)
#define ASSERT_1(cond) \
if (!(cond)) { \
OC_ASSERT_MSG("ASSERT: \"%s\" in file %s, line %d", #cond, __FILE__, __LINE__); \
} else {}
#define ASSERT_2(cond, message) \
if (!(cond)) { \
OC_ASSERT_MSG("ASSERT: \"%s\" in file %s, line %d with message: %s", #cond, __FILE__, __LINE__, message); \
} else {}
// Enforce condition to be true, even in release builds.
//
// Prints 'message' and aborts execution if 'cond' is false.
#define ENFORCE(...) OC_ASSERT_OVERLOAD(ENFORCE, __VA_ARGS__)
#define ENFORCE_1(cond) \
if (!(cond)) { \
qFatal("ENFORCE: \"%s\" in file %s, line %d", #cond, __FILE__, __LINE__); \
} else {}
#define ENFORCE_2(cond, message) \
if (!(cond)) { \
qFatal("ENFORCE: \"%s\" in file %s, line %d with message: %s", #cond, __FILE__, __LINE__, message); \
} else {}
// An assert that is only present in debug builds: typically used for
// asserts that are too expensive for release mode.
//
// Q_ASSERT
#endif
+9
Ver Arquivo
@@ -121,4 +121,13 @@ bool Capabilities::chunkingParallelUploadDisabled() const
return _capabilities["dav"].toMap()["chunkingParallelUploadDisabled"].toBool();
}
QList<int> Capabilities::httpErrorCodesThatResetFailingChunkedUploads() const
{
QList<int> list;
foreach (const auto & t, _capabilities["dav"].toMap()["httpErrorCodesThatResetFailingChunkedUploads"].toList()) {
list.push_back(t.toInt());
}
return list;
}
}
+19
Ver Arquivo
@@ -81,6 +81,25 @@ public:
*/
QByteArray uploadChecksumType() const;
/**
* List of HTTP error codes should be guaranteed to eventually reset
* failing chunked uploads.
*
* The resetting works by tracking UploadInfo::errorCount.
*
* Note that other error codes than the ones listed here may reset the
* upload as well.
*
* Motivation: See #5344. They should always be reset on 412 (possibly
* checksum error), but broken servers may also require resets on
* unusual error codes such as 503.
*
* Path: dav/httpErrorCodesThatResetFailingChunkedUploads
* Default: []
* Example: [503, 500]
*/
QList<int> httpErrorCodesThatResetFailingChunkedUploads() const;
private:
QVariantMap _capabilities;
};

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