Comparar commits

...

388 Commits

Autor SHA1 Mensagem Data
Olivier Goffart 7e63849fcb 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 09:43:15 +01:00
Olivier Goffart de53732629 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 09:43:15 +01:00
Olivier Goffart dc3accacfc 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 09:43:15 +01:00
Olivier Goffart 1b9c49e8f5 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 09:43:15 +01:00
Olivier Goffart ed15842eb9 FolderStatusModel: Different icon for external storages
Issue: https://github.com/owncloud/client/pull/5340#issuecomment-274564441
2017-01-24 16:25:38 +01:00
Olivier Goffart c24c3d559d 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-24 16:22:56 +01:00
Olivier Goffart 6dcd79ded6 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-24 16:21:18 +01:00
Olivier Goffart 0905bcdaea Discovery: Add branding option to disable default sync of 'M' directories
Issue #5331 and https://github.com/owncloud/enterprise/issues/1594
2017-01-24 16:20:55 +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
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
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
Jenkins for ownCloud 355a644020 [tx-robot] updated from transifex 2017-01-10 02:18:34 +01:00
Jenkins for ownCloud 5e6e4e7464 [tx-robot] updated from transifex 2017-01-08 02:18:35 +01:00
Markus Goetz 76fde49282 sqlite: Update bundled version to 3.16.1
For OS X and Windows.
2017-01-05 17:27:46 +01:00
Markus Goetz 4ef7d0410d First iteration ChangeLog for 2.3.0 2017-01-05 16:56:37 +01:00
octotree a1b4984d14 Symlink Support for Dolphin Plugins (#5428)
Add Symlink Support to Dolphin Overlay Plugin
2017-01-05 13:24:22 +01:00
Christian Kamm adbe5ecf55 ownsql: qFatal on prepare errors #5357 2017-01-04 15:15:06 +01:00
Jenkins for ownCloud ba32571039 [tx-robot] updated from transifex 2017-01-04 02:19:32 +01:00
Christian Kamm 084146756b Account: Fix displayName() #5413
This displayName() seemed to be based on Account::user() which used
to call _credentials->user(). But then we repurposed user() to be
davUser() and this usage wasn't updated to point back to the username
used for the credentials.
2017-01-03 13:54:59 +01:00
ckamm e1f5a49c21 Don't blacklist 507 Insufficent Storage #5346 (#5424) 2017-01-03 13:48:32 +01:00
ckamm 143320341e Build: Enable Q_ASSERT in release mode (#5425) 2017-01-03 13:42:25 +01:00
Christian Kamm e286bb1b64 Wizard: Don't accidentally pre-fill url field #5412
slotUrlEditFinished() is called when the wizard is triggered in
some situations.
2017-01-03 11:53:40 +01:00
Olivier Goffart d433f0e08e HTTPCreds: remove all cookies when logging out (#5383)
Some custom server use persistent cookies with the auth token. So we should
clear all the cookies when disconnecting.
Account::clearCookieJar is only called from the HTTPCredentials. This funciton
is not used for shibboleth.
There is probably no reasons to keep the HTTP cookie anyway.

Issue #5370
2017-01-03 11:39:10 +01:00
Christian Kamm 107149d601 Doc: Improve example #5422 2017-01-03 11:31:51 +01:00
Christian Kamm fa9b36f829 Wizard: Let the user know if url is invalid #5398 2017-01-03 11:28:56 +01:00
Christian Kamm 6775292d63 Fix compile of tests 2017-01-03 10:52:39 +01:00
Christian Kamm 6835429a28 Sql: Allow prepare fail for PRAGMA quick_check #5357
This actually happens in low-disk situations.
2017-01-03 10:43:29 +01:00
Christian Kamm 22135f9f57 Fixup broken authType on load #5408 2017-01-03 10:38:20 +01:00
Jenkins for ownCloud 0fd06a225c [tx-robot] updated from transifex 2017-01-03 02:19:30 +01:00
Christian Kamm 473dcb0947 Only create a FolderWatcher if the path exists
Also retry creating it before each sync.

See #5317
2017-01-02 08:52:26 +01:00
Christian Kamm e306f4611c Reschedule a folder regularly with some delay for some errors
Like "folder doesn't exist" - such that we will detect when the folder
becomes available and start syncing.

See #5317
2017-01-02 08:52:26 +01:00
Markus Goetz c6f4f44619 Fix up SSL client certificates #5213 #69 (#5289)
The re-enables the UI, uses Qt API for importing and
stores the certificate/key in the system keychain.
People who had set up client certs need to re-setup the account. This is ok
since it was an undocumented feature anyway.
2017-01-02 08:34:02 +01:00
Jenkins for ownCloud 0865c63745 [tx-robot] updated from transifex 2017-01-02 02:19:26 +01:00
Jenkins for ownCloud b81c3a6a67 [tx-robot] updated from transifex 2017-01-01 02:19:32 +01:00
Jenkins for ownCloud cc56e5639d [tx-robot] updated from transifex 2016-12-30 02:18:34 +01:00
Jenkins for ownCloud 3ce5b358ae [tx-robot] updated from transifex 2016-12-25 02:18:27 +01:00
Jenkins for ownCloud e968284618 [tx-robot] updated from transifex 2016-12-24 02:18:26 +01:00
Jenkins for ownCloud c7723179d8 [tx-robot] updated from transifex 2016-12-23 02:18:34 +01:00
Jenkins for ownCloud 1872f3f94a [tx-robot] updated from transifex 2016-12-22 02:18:30 +01:00
Christian Kamm 3b7887ca35 Wizard: Detach saved account from wizard
Fixes #5408 #5407.

The problem was that cleanup of the credentials page set the
credentials of the account back to dummy, thereby overriding
things like shib usernames.

This should be broken since a932eac832.
2016-12-21 15:31:12 +01:00
Piotr Mrówczyński d781e63fab Add capability to disable parallel chunked upload #5364 - technical review (#5403) 2016-12-21 15:08:45 +01:00
Kyle Fazzari d1237cdda3 Correctly handle possible missing GIT_SHA1. (#5401)
Currently, if get_git_head_revision() doesn't define GIT_SHA1 (which it
doesn't in some cases) it's possible to end up with the following error:

    CMake Error at CMakeLists.txt:69 (if):
      if given arguments:

        "STREQUAL" "GITDIR-NOTFOUND"

      Unknown arguments specified

Fix this by making sure both left and right hand arguments to STREQUAL
are always strings, even if GIT_SHA1 is undefined.

Signed-off-by: Kyle Fazzari <kyle@canonical.com>
2016-12-21 14:14:26 +01:00
Christian Kamm 030e3a5d4a Increase initial bandwidth estimates #4428 #5390
To 2 MB/s and 10 files/s.
2016-12-21 08:53:47 +01:00
Jenkins for ownCloud 4fa4a6a5ed [tx-robot] updated from transifex 2016-12-21 02:18:28 +01:00
Phil Davis 23fb07240b Fix Mac PATH command
Reported in the doc repo owncloud/documentation#1618
This version as suggested by @jturcotte
2016-12-20 20:01:38 +01:00
Christian Kamm 3912dba33a Move qDeclareMetatype from Folder to SyncEngine 2016-12-20 11:43:39 +01:00
Christian Kamm d8c479ab1e Don't wipe db if check fails while disk space is low #5357
An experimental fix for the issue, merged because it's low risk and
makes testing easier.
2016-12-20 09:33:59 +01:00
Jenkins for ownCloud bec67455c1 [tx-robot] updated from transifex 2016-12-20 02:18:27 +01:00
Jenkins for ownCloud ba6a37a601 [tx-robot] updated from transifex 2016-12-19 02:18:28 +01:00
Jenkins for ownCloud 03f5091e73 [tx-robot] updated from transifex 2016-12-18 02:18:28 +01:00
Jenkins for ownCloud 6b6ff08821 [tx-robot] updated from transifex 2016-12-17 02:18:27 +01:00
Jenkins for ownCloud 35a0ee4893 [tx-robot] updated from transifex 2016-12-16 02:18:29 +01:00
Jenkins for ownCloud 3519391119 [tx-robot] updated from transifex 2016-12-15 02:18:37 +01:00
Olivier Goffart 775a1c9ad8 FolderStatusModel: Fix insert/remove items when there are labels
Otherwise it might happen that the model is inconsistant and this can
lead to crash in the worst case.

(For example, if there was a "fetching" label, and we hide it because it
was a 404. In this case, we would not call begin/endRemoveRows, so the
view could still call the model with an index of row 0, that used to be
for the label, but now correspond to the first element of _subs. And
because _subs is empty, this could lead to crashes)
2016-12-14 14:13:47 +01:00
Olivier Goffart ac95844ebd Propagator: make sure every network job has a parent
This could make sure that the network job gets deleted if the parent job gets
deleted, and would avoid crashes like:

Crash: EXCEPTION_ACCESS_VIOLATION_READ at 0xffffffff8b008a04
  File "qiodevice.cpp", line 1617, in QIODevice::errorString
  File "propagatedownload.cpp", line 264, in OCC::GETFileJob::slotReadyRead
  File "moc_propagatedownload.cpp", line 85, in OCC::GETFileJob::qt_static_metacall
  File "qobject.cpp", line 3716, in QMetaObject::activate
  File "moc_qiodevice.cpp", line 154, in QIODevice::readyRead
  File "qnetworkreplyhttpimpl.cpp", line 1045, in QNetworkReplyHttpImplPrivate::replyDownloadData

(#5329)
2016-12-14 14:13:47 +01:00
Olivier Goffart c5b90d9507 Account::slotHandleSslErrors: add guards in case the reply gets deleted in the dialog event loop
Since slotHandleSslErrors will show a dialog with an eventloop, it could be
That the reply gets deleted. Guard against that.

(#5329)
2016-12-14 14:13:47 +01:00
Christian Kamm d631f2e070 Sync now: Disable on disconnect, rename while running #2158 2016-12-13 15:28:52 +01:00
Jonathan Kawohl 5bae2ed5ef fixed merge conflicts 2016-12-13 09:12:50 +01:00
Jenkins for ownCloud 5af2a657ca [tx-robot] updated from transifex 2016-12-13 02:18:28 +01:00
Jenkins for ownCloud 71231026a0 [tx-robot] updated from transifex 2016-12-12 02:18:28 +01:00
Jenkins for ownCloud dfca67b63a [tx-robot] updated from transifex 2016-12-11 02:18:27 +01:00
Jenkins for ownCloud 7dc6a3b89f [tx-robot] updated from transifex 2016-12-10 02:18:32 +01:00
Jocelyn Turcotte f985111b62 Fix the log window not showing csync logs
The csync log level was only set up on startup, and for log files.
Fix the issue by making Logger::isNoop rely on being explicitly activated
for the log window instead of relying on the presence of a connected
signal, and move the csync log level logic in Logger.
2016-12-09 10:03:46 +01:00
Jocelyn Turcotte e8d734b1c2 Fix the sync direction being wrong on MSVC
The compiler seems to use signed enums and we need to reserve an extra
bit for the sign to avoid the 2 value to overflow and being interpreted
as -2 when read, and thus not being correctly compared to the full enum
value.
2016-12-09 10:03:46 +01:00
Jenkins for ownCloud a38864fcb4 [tx-robot] updated from transifex 2016-12-09 02:18:28 +01:00
Jenkins for ownCloud 47bab51474 [tx-robot] updated from transifex 2016-12-08 02:18:27 +01:00
Jocelyn Turcotte d0d5b2b4ee Don't try to deploy the mng image format plugin on macOS
Qt now only build it if the system library is available since libmng
isn't active enough to make its security reliable enough. We don't
use that image format ourselves anyway.
2016-12-07 15:26:23 +01:00
Jocelyn Turcotte 36967122db Rebase Qt patches on 5.6 #3449
Also get rid of the list of different version. We always only support one Qt version
for macOS and Windows, and the list of patches will be based on that supported
version.
2016-12-07 15:26:23 +01:00
Jenkins for ownCloud 3fd67b9fb6 [tx-robot] updated from transifex 2016-12-07 02:18:34 +01:00
ckamm 5bef1aa402 Merge pull request #5045 from owncloud/dbjournal_per_account
Allow a folder to be synced to several accounts. This changes the path of the sync journal file!
2016-12-06 10:55:58 +01:00
Jenkins for ownCloud de9ea19e7e [tx-robot] updated from transifex 2016-12-06 02:18:34 +01:00
Olivier Goffart 4ac2b764a4 libsync: Clear the upload info after several retries (#5345)
Issue #5344
2016-12-05 17:21:36 +01:00
Jenkins for ownCloud 0614cda337 [tx-robot] updated from transifex 2016-12-05 02:18:32 +01:00
Jenkins for ownCloud 9e895b9b3e [tx-robot] updated from transifex 2016-12-04 02:18:28 +01:00
Jenkins for ownCloud f501211c63 [tx-robot] updated from transifex 2016-12-03 02:18:25 +01:00
Jenkins for ownCloud 77ac1b46dd [tx-robot] updated from transifex 2016-12-02 02:18:35 +01:00
Jenkins for ownCloud 745c21623c [tx-robot] updated from transifex 2016-12-01 02:18:28 +01:00
Jenkins for ownCloud b91c116518 [tx-robot] updated from transifex 2016-11-30 02:18:34 +01:00
Felix Tiede d090a3330a Generate .desktop file with OEM name directly.
Instead of renaming the .desktop file at install time it is now
generated with its OEM name during configure time.
2016-11-29 18:36:26 +01:00
Felix Tiede d04e7841e2 Fix file installation source path.
By default the file is copied from the source and not the build
directory which will fail with the configure-time built file.
2016-11-29 18:36:26 +01:00
Felix Tiede d7a4726544 Extend OEM configurability to dolphin desktop file.
OEM configurability creates binaries with OEM names which the .desktop
file doesn't take into account and thus dolphin integration does not
work if OEM changes the binary's name(s).
These changes are now integrated into the .desktop file at compile time.
2016-11-29 18:36:26 +01:00
Olivier Goffart 19d2677db1 libsync: use the new webdav url if the server reports it
The rules to select the webdav url are now:

 - If the server reports that the new chunking algorithm is working,
   always use remote.php/dav/files/<username>
   This capability can be overriden with an environment variable

 - Otherwise, use the dav path provided by the theme, which defaults to
   remote.php/webdav

This means that with the newer server, the branding can no longer override
the webdav URL. If there is still an usecase for the branding to do so, we
need to find another way to override it. But it is now more complicated to
configure as might need include the username and need different endpoint
depending on the operations (chunks or not)

Issue #4007
2016-11-29 16:16:20 +01:00
Christian Kamm a139d1a279 FolderWizard: pass AccountPtr by const&
For review of #5045
2016-11-29 10:39:20 +01:00
Christian Kamm 13e624c38f Fix compilation with Qt < 5.1
For review of #5045
2016-11-29 10:39:08 +01:00
Christian Kamm acb155503b Ensure the 'Sync paused' state is used after pausing #5290 2016-11-29 09:56:45 +01:00
Jenkins for ownCloud 4cb80b08a2 [tx-robot] updated from transifex 2016-11-29 02:18:28 +01:00
Jenkins for ownCloud cd85b7c6d7 [tx-robot] updated from transifex 2016-11-28 02:18:33 +01:00
Olivier Goffart 109056e676 owncloudcmd: Don't put the password in the URL
As the URL might be print on the logs.
Also don't change the scheme from http to owncloud.

This was required before when we were using neon through csync, but now that
we use QNAM for everything we don't need it. The credentials from the account
are used.
2016-11-26 12:57:44 +01:00
Jenkins for ownCloud 51a1bea5de [tx-robot] updated from transifex 2016-11-26 02:18:36 +01:00
Christian Kamm 68f99bcc27 AccountSettings: Add a "Force sync now" context menu option 2016-11-25 14:23:56 +01:00
Christian Kamm 276985f6c3 Fix perl tests for sync journal db name 2016-11-25 13:21:34 +01:00
Jenkins for ownCloud 7523db354d [tx-robot] updated from transifex 2016-11-25 02:18:27 +01:00
Jenkins for ownCloud 4919c9e7b1 [tx-robot] updated from transifex 2016-11-24 02:18:38 +01:00
Christian Kamm 045498c71a Account: Rename user() to davUser()
Avoids potential confusion with credentials->user()
2016-11-23 17:08:17 +01:00
Christian Kamm 49f8143f00 Bugfixes for sync journal name generation and usage
* Use 'user' value for journal name generation
* Save journal name in settings
* Make owncloudcmd choose the right db
2016-11-23 16:48:15 +01:00
Christian Kamm bea7241910 Don't wipe each journal on each start 2016-11-23 16:48:15 +01:00
Christian Kamm 61b4da944c Split folders configuration locations for backwards compatibility 2016-11-23 16:48:15 +01:00
Christian Kamm 6fe1868693 Always migrate .csync_journal to ._sync_xxx 2016-11-23 16:48:15 +01:00
Christian Kamm 9641c7a1e7 Rename sync journal to ._sync_xxx.db.
The added underscore means that older clients will also ignore the
file.
2016-11-23 16:48:15 +01:00
Christian Kamm 3e59a9b316 Merge branch 'master' into dbjournal_per_account 2016-11-23 16:47:56 +01:00
Markus Goetz 679ac0d26a Wizard: Show if server asks for client certificate #2799 #69 (#5261)
This also nicely displays the 'Untrusted domain' message of oC.
The link to add a trusted domain (via web browser) is clickable.
2016-11-23 11:43:15 +01:00
Markus Goetz 2e3a3bcf84 Folder: Make folder only accessible by user #5282 (#5315)
Because on OS X the parent folder might not protect
against access.
2016-11-23 11:05:41 +01:00
Jonathan Kawohl ad437a49f9 Merge branch 'Kawohl-master'
fix conflict
2016-11-23 11:01:52 +01:00
Jonathan Kawohl 6b2282bf0d Merge branch 'master' of https://github.com/owncloud/client into Kawohl-master
fix conflict
2016-11-23 10:59:18 +01:00
Jonathan Kawohl 42aed56a5a Merge branch 'master' of https://gthub.com/Kawohl/client into Kawohl-master
fix conflict
2016-11-23 10:56:29 +01:00
Jonathan Kawohl ca9ec46253 fixed note 2016-11-23 09:17:33 +01:00
Jonathan Kawohl a92eec160a fixed review https://github.com/owncloud/client/pull/5259#pullrequestreview-9743725 2016-11-23 09:10:58 +01:00
Jenkins for ownCloud cc91c42dfa [tx-robot] updated from transifex 2016-11-23 02:18:37 +01:00
Olivier Goffart d22d0e7e30 Propagator: don't use dynamic_cast for QObject
qobject_cast is better. (no need to use RTTI when we have QMetaObject
2016-11-22 17:37:41 +01:00
Samuel 4998303c42 Fixing a typo on a message
This refers to the message shown when copying the list of unsynced items on the activity tab
2016-11-22 12:14:03 +01:00
Christian Kamm ceef2f2d46 FolderMan: Never schedule paused folders #5290
Previously the last folder in the queue was scheduled, regardless
of whether it was paused or not.
2016-11-22 10:53:15 +01:00
Jenkins for ownCloud 8b18600d7e [tx-robot] updated from transifex 2016-11-22 02:18:29 +01:00
Jonathan Kawohl 6cc63462b3 adjusted minimum version. 2016-11-21 13:53:59 +01:00
Olivier Goffart a1dc4069c9 libsync: Don't store the remote URI in the csync or in the SyncEngine
We are going to change the webdav path depending on the capabilities.
But the SyncEngine and csync might have been created before the capabilities
are retrieved.

The main raison why we gave the path to the sync engine was to pass it to csync.
But the thing is that csync don't need anymore this url as everything is done by the
discovery classes in libsync that use the network jobs that use the account for the urls.
So csync do not need the remote URI.

shortenFilename in folderstatusmodel.cpp was useless because the string is the
_file of a SyncFileItem which is the relative file name, that name never
starts with owncloud://.

All the csync test creates the folder because csync use to check if the folder
exists. But we don't need to do that anymore
2016-11-21 08:09:11 +01:00
Jenkins for ownCloud 86846af59d [tx-robot] updated from transifex 2016-11-21 02:18:27 +01:00
Jenkins for ownCloud 5bfa02602d [tx-robot] updated from transifex 2016-11-20 02:18:28 +01:00
Jenkins for ownCloud 9be23984eb [tx-robot] updated from transifex 2016-11-19 02:18:35 +01:00
Christian Kamm eb8de8e3c0 Enable clicking on 'not synced' items #5306 2016-11-18 16:19:36 +01:00
ckamm ec7333a4bf Merge pull request #5272 from owncloud/licensefix-pending
License: Adjust license of GPLv2 source files to GPLv2+
2016-11-18 15:14:47 +01:00
Christian Kamm e485c5c008 Always send a progress message at the end of a sync #5290
Some listeners detect whether a sync is finished by checking
for isUpdatingEstimates and completedFiles >= totalFiles. But
if a sync didn't transfer any files we never sent signal
with these values. Now we do.
2016-11-18 12:33:44 +01:00
Christian Kamm 6451eb3ade Tray: Add a 'New account...' action if no account is configured #5307
Useful when left-clicking the tray icon isn't working for some reason.
2016-11-18 12:17:05 +01:00
Jenkins for ownCloud 01528427b5 [tx-robot] updated from transifex 2016-11-18 02:18:35 +01:00
Jenkins for ownCloud cec4d7b9ff [tx-robot] updated from transifex 2016-11-17 02:18:43 +01:00
Olivier Goffart efa7821dd2 Revert "Discovery: consider also the "shared by me" as shared"
This reverts pull request 5313 (commit
2d6e473a40 and
2f3db04e87)

The problem is that this loads the server too much.
2016-11-16 17:45:40 +01:00
Markus Goetz 89f55cf9df Folder: Add comments after discussion about pre-selected selective sync 2016-11-16 14:08:05 +01:00
Markus Goetz 52552a4204 Merge pull request #5102 from owncloud/chunking-ng
Chunking ng
2016-11-15 15:56:52 +01:00
Olivier Goffart 2f3db04e87 Rename SyncFileStatus::sharedWithMe to shared
Last commit for issue #4788 made the meaning to be simply shared
(with the user or from the user)
2016-11-15 14:32:20 +01:00
Olivier Goffart 2d6e473a40 Discovery: consider also the "shared by me" as shared
The "S" in the permission is only for the "Shared with me" files.
It is only used to show the shared status in the overlay icons.
But we also wish to show the shared status for files that are shared
"by" the users. We can find that out using the 'share-types' webdav
property. If set, then we are sharing the object.
We fake a 'S' in the permission as for our purpose, they mean the same.

Issue #4788
2016-11-15 14:32:20 +01:00
Olivier Goffart 92027e8692 SyncEngineTestUtils: Do don't allocate a buffer for the whole file
As the file can be some hunreds of megabytes, allocating such big arrays may
cause problems.

Also make the timeout a bit bigger so the test can rununder valgrind.
2016-11-15 11:39:40 +01:00
Olivier Goffart 2723cd225e FolderStatusDelegate: Fix compiler warning.
QStyleOptionProgressBarV2 is deprecated in Qt5.
2016-11-15 10:16:41 +01:00
Jenkins for ownCloud acd151102c [tx-robot] updated from transifex 2016-11-15 02:18:36 +01:00
Olivier Goffart 77e790d2ee Merge pull request #5304 from owncloud/Kawohl-linktocentral
documnetation.
2016-11-14 12:43:10 +01:00
Olivier Goffart 899c675f0a Merge pull request #5267 from payload/fix_4608
nautilus integration: "share" extension for syncing folders
2016-11-14 12:35:18 +01:00
Olivier Goffart fb76487e76 Merge pull request #5266 from rmekarni/patch-1
Fix find_library FindCMocka.cmake
2016-11-14 12:20:24 +01:00
Tobias Haeussler 0c0a3ca0a5 Add manifest file on Windows to make the application UAC aware. 2016-11-14 12:16:58 +01:00
Olivier Goffart 5377d1e283 Chunking-NG: code cleanup after review 2016-11-14 10:42:07 +01:00
Jenkins for ownCloud 676ad530e7 [tx-robot] updated from transifex 2016-11-14 02:18:26 +01:00
Jenkins for ownCloud fbcb01ed27 [tx-robot] updated from transifex 2016-11-13 02:18:26 +01:00
Jenkins for ownCloud c2b006e857 [tx-robot] updated from transifex 2016-11-12 02:18:26 +01:00
Jenkins for ownCloud 0e7ccea588 [tx-robot] updated from transifex 2016-11-11 02:18:27 +01:00
Jenkins for ownCloud c16deb3e44 [tx-robot] updated from transifex 2016-11-10 02:18:27 +01:00
Jenkins for ownCloud 019544fcfd [tx-robot] updated from transifex 2016-11-10 01:15:14 +01:00
Jonathan Kawohl 5f0167b19e removed openssl_version variable, 2016-11-09 10:25:32 +01:00
Jonathan Kawohl 29d3c33eb2 added missing quotes 2016-11-09 08:59:14 +01:00
Jonathan Kawohl 469eca1f5f added link to central 2016-11-09 08:59:14 +01:00
Jonathan Kawohl 0864d67a9a fixing wrong files Revert "fix for https://github.com/owncloud/client/issues/1251"
This reverts commit 4f1feab845.
2016-11-09 08:59:14 +01:00
Jonathan Kawohl e9503664f5 fix for https://github.com/owncloud/client/issues/1251 2016-11-09 08:59:14 +01:00
Jonathan Kawohl 58cee61624 added info on qtkeychain
added installation info on qtkeychain
2016-11-09 08:59:14 +01:00
Jonathan Kawohl d23d07f99b Correcting for PR comments 2016-11-09 08:59:14 +01:00
Jonathan Kawohl d70db810dd updated link for documentation and added more info to osx build 2016-11-09 08:59:14 +01:00
Jenkins for ownCloud 842129f99d [tx-robot] updated from transifex 2016-11-09 02:18:28 +01:00
ckamm 36d61ef3a9 Doc: Add sync algorithm overview and comments (#5277)
* Doc: Add sync algorithm overview and comments
2016-11-08 16:10:55 +01:00
Christian Kamm f1f27221a7 Conflicts: Use the local mtime for the conflict file name #5273
Otherwise local conflict files may be overridden in a restore
situation. See ticket for details.
2016-11-08 14:47:51 +01:00
Christian Kamm eb012d26ee FolderStatusModel: Minor cleanups. 2016-11-08 14:01:07 +01:00
Christian Kamm 9ee8187083 Sort folder list alphabetically #5299 2016-11-08 14:01:07 +01:00
Christian Kamm b0c45cfc89 Test: Don't fail when DST change is near #5284 2016-11-08 11:13:19 +01:00
Christian Kamm 90cea69692 Network: Add "Accept" header for some firewalls #5298 2016-11-08 11:01:49 +01:00
Jenkins for ownCloud 155bdfbffe [tx-robot] updated from transifex 2016-11-08 02:18:26 +01:00
Christian Kamm 0e2782d369 Terminate sync when pausing from context menu #5290 2016-11-07 12:50:06 +01:00
Jenkins for ownCloud 6b3d0e69aa [tx-robot] updated from transifex 2016-11-07 02:18:26 +01:00
Jenkins for ownCloud f30aee6d4e [tx-robot] updated from transifex 2016-11-06 02:18:34 +01:00
Jenkins for ownCloud 82f86eb019 [tx-robot] updated from transifex 2016-11-05 02:18:29 +01:00
Olivier Goffart 9573c5e64d Merge remote-tracking branch '2.2' into master
For the reanslation. Now transifex should be updated to update master.
This should normally be the last merge from 2.2

 Conflicts:
	mirall.desktop.in
	translations/client_sl.ts
	translations/client_th.ts
2016-11-04 16:51:58 +01:00
Olivier Goffart 15f2b911d9 ChunkingNG: remove stale files when resuming 2016-11-04 16:43:01 +01:00
Jenkins for ownCloud f5aff70398 [tx-robot] updated from transifex 2016-11-04 16:41:40 +01:00
Olivier Goffart e3a4c3989a SyncEngine: disable heuristics for backup restoration for server >= 9.1
The ownCloud 9.1 server has a data-fingerprint property that the admin must
change in case of backup restoration. When this change, the client understands
that a backup was restored, and will generate conflict files and re-upload
new files.

The heuristics based system checks that there is at least two files wose mtime
is put back in the past and no files that goes forward. In that case we ask the
user before creating the conflicts.

This commit disable the heuristics for newer server that have the data-fingerpint.
And change the heuristics to two hours because we want to avoid false positive due
to some clock error, and that 2 hours of lost due to backup restoration is probably
not so bad.

We only ask the user in the heuristics based aproach so in practice this mean that
the "backup-detected" dialog will no longer appear with newer server.

Relates issues #5260, #5109
2016-11-04 16:30:58 +01:00
Jenkins for ownCloud 3e954bc17f [tx-robot] updated from transifex 2016-11-04 02:18:27 +01:00
Jenkins for ownCloud 2527569bb8 [tx-robot] updated from transifex 2016-11-03 02:18:27 +01:00
Jenkins for ownCloud 1e197531cb [tx-robot] updated from transifex 2016-11-02 02:18:28 +01:00
Jenkins for ownCloud 8b876576eb [tx-robot] updated from transifex 2016-11-01 02:18:29 +01:00
Piotr Mrówczyński a2287c9657 Merge pull request #5274 from owncloud/reduce_loops_dirjob
Cache the value of last unfinished job in the PropagateDerectory scheduleNextJob
2016-10-31 22:07:50 +01:00
Piotr M 34c59ba9ed reduce number of loops 2016-10-31 19:45:24 +01:00
Olivier Goffart c8014a0afd ChunkingNG: Add Test 2016-10-31 15:16:53 +01:00
Olivier Goffart 456d82715e Fix compile after merge 2016-10-31 11:29:33 +01:00
Olivier Goffart 8ca3eb7883 Merge remote-tracking branch 'origin/master' into chunking-ng 2016-10-31 11:09:12 +01:00
Jenkins for ownCloud c110745330 [tx-robot] updated from transifex 2016-10-31 02:18:27 +01:00
Jenkins for ownCloud 19521863a0 [tx-robot] updated from transifex 2016-10-30 02:18:24 +01:00
Jenkins for ownCloud c256896165 [tx-robot] updated from transifex 2016-10-30 02:18:26 +02:00
Jenkins for ownCloud ef922f60fa [tx-robot] updated from transifex 2016-10-29 02:18:28 +02:00
Jenkins for ownCloud 733ea90e6b [tx-robot] updated from transifex 2016-10-28 02:18:28 +02:00
Jenkins for ownCloud a4e1fa9dcf [tx-robot] updated from transifex 2016-10-27 02:18:30 +02:00
Jenkins for ownCloud 1a1684ca2a [tx-robot] updated from transifex 2016-10-26 02:18:34 +02:00
Gilbert Röhrbein 9c8572e335 nautilus integration: refactored _connectToSocketServer, removed superfluous check 2016-10-25 21:45:47 +02:00
Gilbert Röhrbein e675a34fbb nautilus integration: use os.path.join, os.sep and tempfile.gettempdir instead of string concats 2016-10-25 20:15:17 +02:00
Christian Kamm 5f47c01346 Account: Rearrange for readability 2016-10-25 13:20:23 +02:00
Christian Kamm 10644d3568 Move concatUrl and settingsWithGroup to Utility
There was little reason to keep them cluttering Account.
2016-10-25 12:05:28 +02:00
Christian Kamm 9ee3144358 Account: Remove wasMigrated/setMigrated
It was unused since early in the multi-account work:
a932eac832
2016-10-25 11:43:06 +02:00
Christian Kamm cf48ea2e00 Remove unused functions
Account::changed and AbstractCredentials::changed have not been needed
in a long while.
2016-10-25 11:33:38 +02:00
Christian Kamm db24f60ae3 License: Adjust license of GPLv2 source files to GPLv2+
See #5180
2016-10-25 11:06:54 +02:00
Christian Kamm 6026148692 FolderMan: Clean up API
Many public slots didn't need to be public or slots.
2016-10-25 09:44:34 +02:00
Christian Kamm a2222228c9 FolderMan: Document and clean up folder scheduling 2016-10-25 09:44:34 +02:00
Jenkins for ownCloud 9e2d3f5bc7 [tx-robot] updated from transifex 2016-10-25 02:18:32 +02:00
Marcus Hoffmann fe984b61d7 Add script to create a caja plugin. (#5262)
Caja is a fork of nautilus maintained by the Mate project.
This adds a script to create a caja plugin from the nautilus plugin.
It replaces all occurences of nautilus with caja (case sensitive).
This is done in the same way the nemo plugin is generated from the nautilus one.
2016-10-24 15:36:23 +02:00
Jonathan Kawohl ffac3f6213 fixing wrong files Revert "fix for https://github.com/owncloud/client/issues/1251"
This reverts commit 4f1feab845.
2016-10-24 15:16:06 +02:00
Jonathan Kawohl 4f1feab845 fix for https://github.com/owncloud/client/issues/1251 2016-10-24 15:09:25 +02:00
Jonathan Kawohl f738cfd7fe added info on qtkeychain
added installation info on qtkeychain
2016-10-24 09:00:07 +02:00
Jenkins for ownCloud e6be670e49 [tx-robot] updated from transifex 2016-10-24 02:18:28 +02:00
Jenkins for ownCloud 46ce2f4722 [tx-robot] updated from transifex 2016-10-23 02:18:28 +02:00
Gilbert Röhrbein 166a0f60ca nautilus integration: "share" extension for syncing folders
Issue #4608

* folder state is either OK or SYNC usually
* this extension does not know about if a folder is shareable
* a OK folder is shareable
* a SYNC folder could be uploaded or not uploaded
* this commit looks into file entries below this folder
* if one exists with state OK or SYNC
   this folder must have been uploaded
* better would be if the server (gui) tells us
   if the folder is uploaded
2016-10-22 23:26:44 +02:00
Romain Mekarni a9019ccbad Fix find_library FindCMocka.cmake 2016-10-22 14:52:27 +02:00
Jenkins for ownCloud 0a4806af44 [tx-robot] updated from transifex 2016-10-22 02:18:28 +02:00
Olivier Goffart e33b89c222 Chunking-NG: Enable if the server supports it 2016-10-21 16:42:27 +02:00
Olivier Goffart 6b899be895 Merge remote-tracking branch 'origin/2.2' into master 2016-10-21 10:27:33 +02:00
Jenkins for ownCloud 641785298f [tx-robot] updated from transifex 2016-10-21 02:18:31 +02:00
Jonathan Kawohl 092c935422 Correcting for PR comments 2016-10-20 13:05:56 +02:00
Olivier Goffart 273590fdfc ChunkingNG: Use the 'If' header
As discussed in https://github.com/owncloud/core/pull/26368
2016-10-20 11:16:06 +02:00
Olivier Goffart 0960058842 Merge remote-tracking branch 'origin/master' into chunking-ng 2016-10-20 09:25:03 +02:00
Jenkins for ownCloud 1f78ea0fd1 [tx-robot] updated from transifex 2016-10-20 02:18:28 +02:00
Jonathan Kawohl 72d8175032 updated link for documentation and added more info to osx build 2016-10-19 11:12:11 +02:00
Jenkins for ownCloud 2fd9767892 [tx-robot] updated from transifex 2016-10-19 02:18:33 +02:00
Christian Kamm 69a1e46d0c Progress: Reset lastCompletedItem #5256
Otherwise progress listeners think it's still the last-completed
item when the next sync starts. This lead to spurious entries in
the "Recent Changes" list.
2016-10-18 12:29:52 +02:00
Christian Kamm e020a5327e Force a remote discovery when upgrading to this version #5242
A remote discovery will fix up any lingering problems caused by #5190.
2016-10-18 11:21:01 +02:00
Christian Kamm 1b04489887 Remove stale commented code
These functions don't even exist anymore.
2016-10-18 11:21:01 +02:00
Olivier Goffart 36a19703db SyncEngine: Permission error in subfolder of a folder that cannnot be added is a SoftError
Issue #5059
2016-10-17 12:22:04 +02:00
Jenkins for ownCloud f3a345a23b [tx-robot] updated from transifex 2016-10-17 02:18:29 +02:00
Jenkins for ownCloud 826459eae7 [tx-robot] updated from transifex 2016-10-17 01:15:13 +02:00
Jenkins for ownCloud c2c36b85cb [tx-robot] updated from transifex 2016-10-16 02:18:28 +02:00
Jenkins for ownCloud 7b2f8ae6f7 [tx-robot] updated from transifex 2016-10-15 02:18:29 +02:00
Markus Goetz d600fdc89b OS X: Use monochrome tray icon by default (#5229) 2016-10-14 14:26:31 +02:00
Markus Goetz 8c5ea8dc90 Propagator: Also upload more in parallel (#5230)
Fix for https://github.com/owncloud/client/issues/4986#issuecomment-227071801

This is before we have bundling at some point.
2016-10-14 14:23:55 +02:00
Jenkins for ownCloud 0eddcd6384 [tx-robot] updated from transifex 2016-10-14 02:18:29 +02:00
Klaas Freitag 9f2ae5dd17 Add a note that the source repositories need to be enabled. (#5239)
* Add a note that the source repositories need to be enabled.

* Fix typo, is => are.
2016-10-13 16:22:54 +02:00
Olivier Goffart 766d9ae1ac QProgressIndicator: update copy from upstream
Update from commit 05ce8a23cdc12e825532dc6de06c267fb8d48b4f from
https://github.com/dragotin/QProgressIndicator
Which itself is forked from commit e5ba0fd09bfd43b067ee3646d70b294c7efcb558 from
upstream, with additional license header.

It was relicensed to MIT according to
https://github.com/mojocorp/QProgressIndicator/commit/14bb9d10e29407175fdf4b9f03ed9cc7bb124f93

Relates to issues #5180 and #5184
2016-10-13 12:05:59 +02:00
Jenkins for ownCloud 21128ed762 [tx-robot] updated from transifex 2016-10-13 02:18:28 +02:00
Markus Goetz 5000d40619 Fixup previous commit
Thanks @ogoffart for spotting.
2016-10-12 19:10:56 +02:00
Klaas Freitag 16e28567a6 Folderman: Some comments for the checkPathValidityForNewFolder method. 2016-10-12 18:16:53 +02:00
Klaas Freitag 3bef42db6b folderman: checkPathValidityForNewFolder - correct file path comparison
It now checks based on the correct case sensitivity and also using the new
method for filename comparison.
2016-10-12 14:50:10 +02:00
Klaas Freitag 27d23edacc Utility: Add a function to check if two filenames are equal plus test.
It calls canonical path always and works with the correct case preserving
depending on the platform.
2016-10-12 14:48:00 +02:00
Jenkins for ownCloud 0d321050a6 [tx-robot] updated from transifex 2016-10-12 02:18:34 +02:00
Markus Goetz fc7aaf792b Auto Start: Only set on first account setup, not all later ones 2016-10-11 20:28:14 +02:00
Markus Goetz f6355e15a3 sqlite: Update bundled version to 3.14.2
For OS X and Windows.
2016-10-11 20:06:43 +02:00
Olivier Goffart d80d5a8ee4 SyncEngine: Fix renaming a folder should keep the selective sync state
Issue #5224

Two problems:

 - In the discovery phase, we need to check the selective sync entries of
   the source path in case of renames.

 - When the rename is done, we need to actually update the black list in the
   database.
2016-10-11 14:38:25 +02:00
Olivier Goffart e0a36ab313 TestFolderMan: don't pollute user's settings 2016-10-11 14:27:14 +02:00
Olivier Goffart 9d3e78ed54 AccountManager: do not load invalid account
Some tests (such as FolderManTest) can polute the config file with invalid
accounts.

(That's because most of the code, (even in libsync) always instentiate a ConfigFile)
2016-10-11 14:27:14 +02:00
Olivier Goffart b6079bfe4f Remove usused variable 2016-10-11 12:12:28 +02:00
Olivier Goffart f75106fd8e SyncJournalDB: check the return value of the prepare statements in checkConnect
Relates to #5199
2016-10-11 11:35:26 +02:00
Olivier Goffart 57fe7b800f Theme: Fix compiler warning
Relates #5227
2016-10-11 10:31:47 +02:00
Jenkins for ownCloud 089ecf8222 [tx-robot] updated from transifex 2016-10-11 02:18:32 +02:00
Klaas Freitag e1a48e3c33 Move the journal file name generation to the syncjournaldb class.
As requested by Olivier.
2016-10-10 16:59:17 +02:00
Olivier Goffart c2fa9b5bbf AccoutWizard: Change the set policy of a radio button
In an attempt to make sure the button next to it don't get too small.

Issue #5209
2016-10-10 13:27:28 +02:00
Olivier Goffart 86522cbbf0 OwnSQL: avoid crashing in SqlQuery::reset_and_clear_bindings
The crash reporter shows a lot of crashes in sqlite3_clear_bindings
which seems to indicate that _stmt is null. We should guard against
a null value in order to avoid crashing.

This should only happen if the prepare call fails. We don't usually
check the return value of the prepare call, but if _stmt is null, the
exec call should return false, not true. We check the result of the
exec call, so this should then abort the sync with an error, rather
than crashing.
2016-10-10 13:27:12 +02:00
Jenkins for ownCloud d54f8adac5 [tx-robot] updated from transifex 2016-10-10 02:18:29 +02:00
Jenkins for ownCloud d35ecafa0b [tx-robot] updated from transifex 2016-10-09 02:18:27 +02:00
Jenkins for ownCloud 2ca807280a [tx-robot] updated from transifex 2016-10-08 02:18:33 +02:00
Klaas Freitag 5d13f9290f Fix the folderman test, adopting the checkPathValidity method tests. 2016-10-07 16:24:09 +02:00
Klaas Freitag c84140d293 checkPathValidityForNewFolder: Catch sync folders underneath sym links.
plus some whitespace changes.
2016-10-07 16:23:13 +02:00
Christian Kamm 91b6b88883 Tray: Fix crash on startup for non-OSX oses 2016-10-07 13:32:42 +02:00
Christian Kamm f36d4562a1 Doc: Remove mention of "F5 to reset database" #5130 2016-10-07 13:22:43 +02:00
Tommy Sparber 67ecca492b Improve macOS SysTray/StatusBar monochrome icon (#5227)
- Use a white icon if the context menu is visible.
- Enable `QIcon::setIsMask` if compiled on Qt >= 5.6 to allow automatic
  macOS color handling.
- No changes if the colored icons are used.
2016-10-06 17:18:51 +02:00
Markus Goetz 84c925dc58 503: Also parse other server error message (#5228)
From https://github.com/owncloud/core/pull/26145
2016-10-06 14:45:04 +02:00
Jenkins for ownCloud e1a01c75d9 [tx-robot] updated from transifex 2016-10-06 02:18:30 +02:00
Jenkins for ownCloud 6a4adbc87e [tx-robot] updated from transifex 2016-10-05 02:18:30 +02:00
Jenkins for ownCloud 89974ab1d4 [tx-robot] updated from transifex 2016-10-04 02:18:30 +02:00
Jenkins for ownCloud 8d0c313486 [tx-robot] updated from transifex 2016-10-03 02:18:39 +02:00
Jenkins for ownCloud aab0cdf12a [tx-robot] updated from transifex 2016-10-02 02:18:29 +02:00
Jenkins for ownCloud a89520043e [tx-robot] updated from transifex 2016-10-01 02:18:30 +02:00
Jenkins for ownCloud 6382a142cd [tx-robot] updated from transifex 2016-10-01 01:15:17 +02:00
Klaas Freitag 838c072ccc Folder Setup: Allow to set up more sync connects to the same folder.
One local folder can now be configured as sync target for multiple
accounts as long as their url and user differ.

Also this patch accepts that the sync folder is behind a symlink.
Also this patch fixes a bug that before the user input was taken
canonically which was not working for the symlink handling.
2016-09-30 14:08:00 +02:00
Jenkins for ownCloud 02c403e360 [tx-robot] updated from transifex 2016-09-30 02:18:34 +02:00
Klaas Freitag ed6a708460 SyncJournalDb: Migrate the old csync journal to the new name.
Migration strategy to the new filename.
2016-09-29 16:41:11 +02:00
Klaas Freitag 0c9dcdafc2 csync: Only free the statedb filename on destroy.
The filename must not be wiped in csync_commit as that is
happening after every sync. It is only set once in the
constructor of the SyncEngine in csync_init().
2016-09-29 16:36:14 +02:00
Christian Kamm 5f2b1999f6 Package: Fix nautilus plugin name collision when branded
As suggested by @olifre in #5183
2016-09-28 13:10:48 +02:00
Christian Kamm bd2bcad3ba ShareDialog: Remove context help button
Ticket #5203
2016-09-28 13:00:52 +02:00
Christian Kamm 598a7cec5d Merge remote-tracking branch 'origin/2.2' 2016-09-28 12:07:45 +02:00
Jenkins for ownCloud 46d934bd95 [tx-robot] updated from transifex 2016-09-28 02:18:31 +02:00
Markus Goetz e8c8943a30 VERSION.cmake: We're at 2.2.5 2016-09-27 18:21:55 +02:00
Markus Goetz f1e2e42d99 2.2.4: Set release date 2016-09-27 10:52:18 +02:00
Markus Goetz 95c479aa07 Wizard: Do the system proxy lookup in a thread (#5160)
This is analogous to the code in ConnectionValidator.
2016-09-26 15:45:30 +02:00
ckamm 035442b6da Improve the "new big folder" UI #5202 (#5204)
Instead of using the regular selective-sync UI (where it's unclear what
the "Cancel" button would even mean in this context), provide a
different set of buttons that allow the user to quickly synchronize
all pending big folders, none of them, or perform manual changes
as usual.
2016-09-23 13:47:57 +02:00
ckamm 98efb07535 Tray: Workaround collection (#5179)
Tray: Workaround collection

* QDBus workaround for Qt 5.5.0 only, there were reports of the tray
  working fine with 5.5.1. #5164
* OWNCLOUD_FORCE_QDBUS_TRAY_WORKAROUND to force the workaround on an off
* OWNCLOUD_TRAY_UPDATE_WHILE_VISIBLE to enable or disable updating of
  the menu while it's visible - disable by default due to problems on OSX and Xubuntu.
* Track the visibility of the tray menu with aboutToShow/aboutToHide
  only on OSX - the aboutToHide signal doesn't trigger reliably on linux
* Refactor such that setupContextMenu is different from updateContextMenu
* Don't use on-demand updating of the tray menu when the qdbus workaround
  is active, instead to occasional (30s) updates of the tray menu.
2016-09-23 10:44:54 +02:00
Olivier Goffart bc04f79959 Missing Inc -> GmbH (#5181) 2016-09-22 15:32:12 +02:00
Christian Kamm e10c97573f Warning if mailto url fails #5142 2016-09-22 14:16:58 +02:00
Christian Kamm 383479fbfd Fix Windows build with WITH_UNIT_TESTING 2016-09-22 13:55:48 +02:00
Olivier Goffart fca5f1b210 owncloudcmd: fix --silent
We ignored csync log, but we also need to silent Qt debug output.
We need to ignore it at the very begining because there might be
qDebug also in account creation.

Issue #5196
2016-09-22 10:32:27 +02:00
Christian Kamm 0cea3d85f5 Add log messages for LockWatcher use #5190 2016-09-22 09:57:42 +02:00
Olivier Goffart 85b8ab178e SyncEngine: Fix renaming of folder when file are changed (#5195)
Two bugs:
 - The change filed are not considered as move, they are re-downloaded
   but the old file was not removed from the database. The change in
   owncloudpropagator.cpp takes care of removing the old entries.

 - Next sync would then remove the file in the server in the old folder
   This was not a problem until we start reusing the sync engine, and
   that the _renamedFolders map is not cleared. We were before deleting
   a non-existing file. But now we delete the actual file.

Also improve the tests to be able to do move on the server.
This include support for file id.

Issue #5192
2016-09-22 09:02:47 +02:00
Jenkins for ownCloud ea9d17b41d [tx-robot] updated from transifex 2016-09-22 01:15:16 +02:00
Piotr Mrówczyński b7eb37dc03 Merge pull request #5170 from owncloud/add_capabilities_owncloudcmd
add server capabilities to owncloudcmd
2016-09-21 22:28:41 +02:00
Olivier Goffart 98bfa8d5de Propagator: properly send the success flag (#5189)
In case of the root directory, it may happen that the _item
is empty and the _item->_status is NoStatus.  But we still need to report
the proper success or error of the whole propagation. We should really
use _hasError for that. However, _hasError is also defined to NoStatus
if there was no error, so in that case we need to set Success.

This fixes the problem in which the data-fingerprint is not saved on the
database because the SyncEngine think that the sync failed. (Issue #5185)
2016-09-21 16:35:42 +02:00
Olivier Goffart ff701bd473 ConnectionValidator: properly handle error in status.php (#5188)
We wwer enot connecting to the right signal from the check server
job, and therefore we were not catching the condition in which the
json was invalid. We would then never terminate the ConnectionValidator job.

Note that instanceNotFound is also emited if there is a network error.

The log looked like this:

10:25:51.247 OCC::CheckServerJob::finished: status.php from server is not valid JSON!
10:25:51.248 OCC::CheckServerJob::finished: status.php returns:  QMap()   QNetworkReply::NetworkError(NoError)  Reply:  QNetworkReplyHttpImpl(0x2b6a790)
10:25:51.248 OCC::CheckServerJob::finished: No proper answer on  QUrl("http://localhost/~owncloud/status.php")
10:26:23.235 OCC::AccountState::checkConnectivity: ConnectionValidator already running, ignoring "owncloud@localhost"
10:26:55.235 OCC::AccountState::checkConnectivity: ConnectionValidator already running, ignoring "owncloud@localhost"
[...]
2016-09-20 11:55:43 +02:00
Jocelyn Turcotte 31aaf956f5 Merge pull request #5182 from jturcotte/msvcBuild
Fix the MSVC build
2016-09-20 10:39:14 +02:00
Jocelyn Turcotte a221ac1e4d Fix unit testing build warning on Linux
The compiler complained about the PathComponent reference on the lambdas comes from the anonymous namespace.
2016-09-16 17:55:28 +02:00
Jocelyn Turcotte 2b274e9460 Fix the MSVC build
- Replace functions that are provided by MinGW with a Win32-based
  implementation
- Explicitly export needed symbols from ocsync.dll
- Rename share.h to sharemanager.h since the name clashes with one
  of the Windows headers and get included from there
- Remove the timestamp from the fallback csync stderr logging, it's
  not used since we always provide a log callback
2016-09-16 17:43:39 +02:00
Olivier Goffart da26e59770 Chunking-NG: add some headers when uploading chunks
These are not understood by owncloud yet, but were requested for CernBox

OC-Total-Length in the MKCOL: The full lenght of the file
OC-Chunk-Offset in the PUT: The offset within the file in which this chunk belongs
OC-Checksum in the MOVE: The transission checksum
2016-09-16 16:36:46 +02:00
Olivier Goffart 3c24d5a148 Chunking-NG: The MOVE will return the code 204 if the file was already there 2016-09-16 16:20:40 +02:00
Olivier Goffart c222793525 Chunking-NG: use OC-If-Destination-Match instread of If-Match
For the MOVE command, because If-Match in Webdav relates to the source, not
the destination
2016-09-16 16:15:09 +02:00
Olivier Goffart 28018e8590 Chunking-NG: Fix destination URL 2016-09-16 16:14:53 +02:00
Olivier Goffart 4c79ce2ae6 ConnectionValidator: fetch the account name.
This is needed for the new webdav path used by the new chunking.
The user might not be the same as the one used to connect
2016-09-16 15:49:43 +02:00
Markus Goetz aa5d3055be Folder/Watcher: Fix up #5174 #5153 (#5186)
It was surprising to have a broken symlink return empty for
canonical path.
2016-09-15 14:56:37 +02:00
Christian Kamm 3e1690ff7a Improvements to file recall 2016-09-14 15:42:19 +02:00
Jenkins for ownCloud 826a675f32 [tx-robot] updated from transifex 2016-09-27 02:18:32 +02:00
Jenkins for ownCloud 323ebf9bf2 [tx-robot] updated from transifex 2016-09-26 02:18:30 +02:00
Jenkins for ownCloud e4bf3ec19a [tx-robot] updated from transifex 2016-09-25 02:18:36 +02:00
Jenkins for ownCloud f2721aff1d [tx-robot] updated from transifex 2016-09-24 02:18:33 +02:00
Markus Goetz 29bd8658bb ChangeLog: 2.2.4 2016-09-22 15:41:30 +02:00
Klaas Freitag 8b9ca63eeb Dolphin Plugin: Use the Application name for the socket path (#5172)
do not hardcode.

This should fix #5165
(cherry picked from commit 2d110540ee)
2016-09-22 09:20:47 +02:00
Olivier Goffart 6f1b03c560 SyncEngine: Fix renaming of folder when file are changed (#5195)
Two bugs:
 - The change filed are not considered as move, they are re-downloaded
   but the old file was not removed from the database. The change in
   owncloudpropagator.cpp takes care of removing the old entries.

 - Next sync would then remove the file in the server in the old folder
   This was not a problem until we start reusing the sync engine, and
   that the _renamedFolders map is not cleared. We were before deleting
   a non-existing file. But now we delete the actual file.

Also improve the tests to be able to do move on the server.
This include support for file id.

Issue #5192
(cherry picked from commit 85b8ab178e)
2016-09-22 09:05:09 +02:00
Jenkins for ownCloud 3bd3ffb8e2 [tx-robot] updated from transifex 2016-09-22 02:18:32 +02:00
Olivier Goffart a810d69daa ConnectionValidator: properly handle error in status.php (#5188)
We wwer enot connecting to the right signal from the check server
job, and therefore we were not catching the condition in which the
json was invalid. We would then never terminate the ConnectionValidator job.

Note that instanceNotFound is also emited if there is a network error.

The log looked like this:

10:25:51.247 OCC::CheckServerJob::finished: status.php from server is not valid JSON!
10:25:51.248 OCC::CheckServerJob::finished: status.php returns:  QMap()   QNetworkReply::NetworkError(NoError)  Reply:  QNetworkReplyHttpImpl(0x2b6a790)
10:25:51.248 OCC::CheckServerJob::finished: No proper answer on  QUrl("http://localhost/~owncloud/status.php")
10:26:23.235 OCC::AccountState::checkConnectivity: ConnectionValidator already running, ignoring "owncloud@localhost"
10:26:55.235 OCC::AccountState::checkConnectivity: ConnectionValidator already running, ignoring "owncloud@localhost"
[...]
(cherry picked from commit ff701bd473)
2016-09-21 14:30:36 +02:00
Jenkins for ownCloud 8496817db2 [tx-robot] updated from transifex 2016-09-21 02:18:30 +02:00
Jenkins for ownCloud 3d06f4b7c9 [tx-robot] updated from transifex 2016-09-20 09:12:39 +02:00
Olivier Goffart b228488eb7 Revert "FolderWatcher: Act on relative paths #5116 (#5153)"
This is not sufficient as it is not working for the Socket API.
Next commit will fix it in another layer.

Also, not ignoring paths that are not inside the folder is wrong
as it might still happen if the name has a different casing

This reverts commit d5a481f132.

(cherry picked from commit 904cd46f75)
2016-09-15 16:26:25 +02:00
Piotr M 7fd00b2cd5 add server capabilities to owncloudcmd 2016-09-12 14:43:40 +02:00
Markus Goetz 907918dca3 FolderWatcher: Act on relative paths #5116 (#5153)
(cherry picked from commit d5a481f132)
2016-09-12 14:09:13 +02:00
Christian Kamm 5ffaf3a90f Set discovery thread priority to low #5017
(cherry picked from commit bd7ec19644)
2016-09-12 14:09:13 +02:00
Olivier Goffart 1040e7b57b ExcludeFiles: Fix when the folder casing is not the same in the settings and in the FS
If the folder has different case in the settings and in the FS, we should
not ignore all the files. This is important for the files system watcher.

(cherry picked from commit 98268d102f)
2016-09-12 14:09:12 +02:00
Olivier Goffart 65c49e1de6 CleanupPollsJob: Fix possible leak
Missing deleteLater when the CleanupPollsJob aborts.
This is only a problem if the SyncEngine is kept alive a long time. Which is
usually not the case in the configuration where poll jobs are used.

(cherry picked from commit 3465024898)
2016-09-12 14:09:12 +02:00
Christian Kamm 4abaee7736 Recall: Copy instead of move recalled file #5150
That was an unintentional change in
2662203fb7

Also expand the test case to cover this.

(cherry picked from commit af9c4d0e2f)
2016-09-12 14:09:12 +02:00
Markus Goetz 3cdcd8dea0 Selective Sync: Fix request loop and show error in view (#5154)
I got into a situation where the model would endlessly request the directory
contents from the server because we did not notice yet that the server
is actually in maintenance mode while we were expanding the tree view when
changing the tab to the account or when just expanding it by clicking.
(cherry picked from commit 524220d090)
2016-09-12 14:09:12 +02:00
Christian Kamm cb19ebc9e3 ShareLink: Ensure the password line edit is enabled #5117
(cherry picked from commit b541fea793)
2016-09-12 14:09:12 +02:00
Daniel Molkentin 37adaa7872 Update owner to be ownCloud GmbH
Fixes #5079

(cherry picked from commit a83c5598e8)
2016-09-12 14:09:12 +02:00
Christian Kamm 9d93afb2a1 Switch target version of this branch to 2.2.4 2016-09-12 14:07:33 +02:00
Olivier Goffart 7c75a39bc1 Chunking-NG: Some fixup after feedback from the pull request #5102 2016-09-10 12:30:14 +02:00
Jenkins for ownCloud 7c24ed769e [tx-robot] updated from transifex 2016-09-06 02:18:30 +02:00
Jenkins for ownCloud 65110f7a91 [tx-robot] updated from transifex 2016-09-05 02:18:30 +02:00
Jenkins for ownCloud c33abd468d [tx-robot] updated from transifex 2016-09-04 02:18:30 +02:00
Jenkins for ownCloud 584b205bd5 [tx-robot] updated from transifex 2016-09-03 02:18:31 +02:00
Klaas Freitag f0dc3b2deb FolderWatcher: Also ignore the new sync journal file name format. 2016-09-02 16:19:10 +02:00
Klaas Freitag 84ede3f01f Make sync journal name generating a method of SyncJournal.
Before it was in Folder, however, the command line client does not
have the Folder class. To not duplicate code, the function to generate
the sync journal name went to SyncEngine class.
2016-09-02 16:19:10 +02:00
Klaas Freitag 2daf895e43 Documentation: Mention the new format for the journal file. 2016-09-02 16:19:10 +02:00
Klaas Freitag 3b651b2da9 folderman: Clean some comments 2016-09-02 16:19:04 +02:00
Klaas Freitag 6fd930908c csync_tests: Adopted to new cmocka API. 2016-09-02 15:49:54 +02:00
Klaas Freitag 62125a442d csync_exclude: Also exclude the new syncjournal filename. 2016-09-02 15:49:21 +02:00
Klaas Freitag 2d54fb2ff9 csync_update: Do not check to exclude .csync_journal.db
It is indeed already handled by csync_exclude.
2016-09-02 15:48:45 +02:00
Klaas Freitag e46fad52bb Make the sync journal file name a method of the Folder class.
The sync journal name has a dependency on the remote url now.
2016-09-02 12:29:21 +02:00
Jenkins for ownCloud b75f50d62c [tx-robot] updated from transifex 2016-09-02 02:18:31 +02:00
Jenkins for ownCloud 14457e93e6 [tx-robot] updated from transifex 2016-09-01 02:18:31 +02:00
Olivier Goffart c41f6ed76b Chunking-NG: use new dav URL for the move 2016-08-31 12:12:34 +02:00
Olivier Goffart 818b5854ce Chunking-NG: Qt4 compile 2016-08-31 10:28:44 +02:00
Olivier Goffart 79abb8b4e3 ChunkingNg: enable depending on an environment variable 2016-08-31 10:28:15 +02:00
Olivier Goffart fad387b6b8 Chunking-Ng: Resume 2016-08-31 10:28:15 +02:00
Olivier Goffart a1558100b8 WIP: new chunking algorithm
Current limitations of this WiP
 - No resuming implemented yet
 - No parallel chunks
 - Hackish way to get the webdav paths
2016-08-31 10:28:15 +02:00
Olivier Goffart 4f3f642da6 Upload: refactor the upload in two classes so the new chuning can be implemented 2016-08-31 10:28:15 +02:00
Jenkins for ownCloud 9c0ecad420 [tx-robot] updated from transifex 2016-08-31 02:18:30 +02:00
Jenkins for ownCloud 85b5fdb3d3 [tx-robot] updated from transifex 2016-08-30 02:18:35 +02:00
Jenkins for ownCloud f2c6669224 [tx-robot] updated from transifex 2016-08-29 02:18:30 +02:00
Jenkins for ownCloud d8f9bf3a0b [tx-robot] updated from transifex 2016-08-28 02:18:32 +02:00
Jenkins for ownCloud d5fa8faa91 [tx-robot] updated from transifex 2016-08-27 02:18:32 +02:00
Jenkins for ownCloud d1a1b95926 [tx-robot] updated from transifex 2016-08-26 02:18:32 +02:00
Jenkins for ownCloud ee2a67e332 [tx-robot] updated from transifex 2016-08-25 02:18:31 +02:00
Klaas Freitag f3cfd2b70b csync: Free statedb file member before realloc 2016-07-17 21:13:17 +02:00
Klaas Freitag 78caa1a712 Fix tests for syncjournaldb 2016-07-17 21:10:07 +02:00
Klaas Freitag 0884ad6517 owncloudcmd: Adopt to new syncJournalDb MD5 based name schema. 2016-07-10 13:05:09 +02:00
Klaas Freitag 37fc4e4332 SyncJournalDb: Cleanup of Constructor interface.
The parameter path is not longer needed.
2016-07-10 13:04:29 +02:00
Klaas Freitag 9cc90159f1 FolderMan: ensureJournalGone needs to know the exact journal name, WIP 2016-07-10 12:57:35 +02:00
Klaas Freitag 4ceee86c66 SyncEngine: Calculate a uniq journal name using the remote account.
That should allow to sync the same local folder to multiple remote destinations.

see #3764
2016-07-10 12:56:43 +02:00
Klaas Freitag b9ea7c3414 csync: Do not compute the journal name in csync_update any more.
Rely on the name that was passed to csync_init()
2016-07-10 12:54:33 +02:00
Klaas Freitag 3033e693be Folder: For wipe reuse the journal name from SyncEngine.
Do not compute on its own any more.
2016-07-10 12:52:47 +02:00
Klaas Freitag a1bc01d3b1 SyncJournalDb: Add a method to set the name of the db file. 2016-07-10 12:51:42 +02:00
394 arquivos alterados com 38943 adições e 30264 exclusões
+12 -2
Ver Arquivo
@@ -1,6 +1,9 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(VERSION 2.8.0)
if(POLICY CMP0020)
cmake_policy(SET CMP0020 NEW)
endif()
project(client)
@@ -55,9 +58,12 @@ if( UNIX AND NOT APPLE )
endif()
####
# Enable Q_ASSERT etc. in all builds
add_definitions( -DQT_FORCE_ASSERTS )
include(GNUInstallDirs)
include(DefineInstallationPaths)
include(GenerateExportHeader)
include(GetGitRevisionDescription)
@@ -66,7 +72,7 @@ get_git_head_revision(GIT_REFSPEC GIT_SHA1)
# if we cannot get it from git, directly try .tag (packages)
# this will work if the tar balls have been properly created
# via git-archive.
if (${GIT_SHA1} STREQUAL "GITDIR-NOTFOUND")
if ("${GIT_SHA1}" STREQUAL "GITDIR-NOTFOUND")
file(READ ${CMAKE_SOURCE_DIR}/.tag sha1_candidate)
string(REPLACE "\n" "" sha1_candidate ${sha1_candidate})
if (NOT ${sha1_candidate} STREQUAL "$Format:%H$")
@@ -166,6 +172,9 @@ find_package(SQLite3 3.8.0 REQUIRED)
# On some OS, we want to use our own, not the system sqlite
if (USE_OUR_OWN_SQLITE3)
include_directories(BEFORE ${SQLITE3_INCLUDE_DIR})
if (WIN32)
add_definitions(-DSQLITE_API=__declspec\(dllimport\))
endif()
endif()
find_package(ZLIB)
@@ -180,6 +189,7 @@ add_definitions(-DUNICODE)
add_definitions(-D_UNICODE)
if( WIN32 )
add_definitions( -D__USE_MINGW_ANSI_STDIO=1 )
add_definitions( -DNOMINMAX )
endif( WIN32 )
# Handle Translations, pick all client_* files from trans directory.
+48
Ver Arquivo
@@ -1,6 +1,54 @@
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
* 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)
* Conflicts: Use the local mtime for the conflict file name (#5273)
* "Sync now" menu item
* SSL Client certificate support improved (Show UI, Store keys in keychain)
* Propagator: Upload more small files in parallel
* Sync Engine: Read data-fingerprint property to detect backups (#2325)
* GUI: Show link to ceate an app password/token for syncing
* Share dialog: Add 'Mail link' button
* Caja file manager plugin
* Make "backup detected" message to not trigger in wrong cases
* SyncEngine: Fix renaming of folder when file are changed (#5192)
* Fix reconnect bug if status.php intermittently returns wrong data (#5188)
* Improve sync scheduling (#5317)
* Overlay icons: Improvements in correctnes
* Tray menu: Only update on demand to fix Linux desktop integration glitches
* Progress: Better time/bandwidth estimations
* Network: Follow certain HTTP redirects (#2791)
* Network: Remove all cookies (including load balancers etc) when logging out
* Discovery thread: Low priority
* owncloudsync.log: Write during propagation
* Better error message for files with trailing spaces on Windows
* Excludes: Consider files in hidden folders excluded (#5163)
* Allow sync directory to be a symlinked directory
* Add manifest file on Windows to make the application UAC aware
* macOS: Improve monochrome tray icons
* Don't blacklist 507 Insufficent Storage #5346 (#5424)
* Shibboleth bugfixes
* Fixes with regards to low disk space
* A ton of other bugfixes
* Refactorings
* Improved documentation
* Crash fixes
version 2.2.4 (release 2016-09-27)
* Dolphin Plugin: Use the Application name for the socket path (#5172)
* SyncEngine: Fix renaming of folder when file are changed (#5195)
* Selective Sync: Fix HTTP request loop and show error in view (#5154)
* ConnectionValidator: properly handle error in status.php request (#5188)
* Discovery: Set thread priority to low (#5017)
* ExcludeFiles: Fix when the folder casing is not the same in the settings and in the FS
* ShareLink: Ensure the password line edit is enabled (#5117)
version 2.2.3 (release 2016-08-08)
* SyncEngine: Fix detection of backup (#5104)
* Fix bug with overriding URL in config (#5016)
+1 -1
Ver Arquivo
@@ -27,7 +27,7 @@ https://github.com/owncloud/client.
## Building the source code
[Building the Client](http://doc.owncloud.org/desktop/2.0/building.html)
[Building the Client](http://doc.owncloud.org/desktop/2.2/building.html)
in the ownCloud Desktop Client manual.
## Maintainers and Contributors
+2 -2
Ver Arquivo
@@ -5,7 +5,8 @@
#
# ownCloud is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# ownCLoud is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -39,7 +40,6 @@ QT_PLUGINS = [
'imageformats/libqico.dylib',
'imageformats/libqjpeg.dylib',
'imageformats/libqsvg.dylib',
'imageformats/libqmng.dylib',
]
QT_PLUGINS_SEARCH_PATH=[
@@ -1,42 +0,0 @@
From ea4dcc5931d455e4ee3e958ffa54a9f54ab022c8 Mon Sep 17 00:00:00 2001
From: Daniel Molkentin <daniel@molkentin.de>
Date: Mon, 5 Jan 2015 10:45:25 +0100
Subject: [PATCH 1/3] Fix crash on Mac OS if PAC URL contains non-URL legal
chars
macQueryInternal() was retrieving the PAC URL string as-entered by
the user in the 'Proxies' tab of the system network settings dialog
and passing it to CFURLCreateWithString().
CFURLCreateWithString() returns null if the input string contains
non-URL legal chars or is empty.
Change-Id: I9166d0433a62c7b2274b5435a7dea0a16997d10e
Patch-By: Robert Knight
Task-number: QTBUG-36787
Reviewed-by: Peter Hartmann <phartmann@blackberry.com>
Reviewed-by: Markus Goetz <markus@woboq.com>
---
src/network/kernel/qnetworkproxy_mac.cpp | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/network/kernel/qnetworkproxy_mac.cpp b/src/network/kernel/qnetworkproxy_mac.cpp
index 7d26246..81bce0c 100644
--- a/src/network/kernel/qnetworkproxy_mac.cpp
+++ b/src/network/kernel/qnetworkproxy_mac.cpp
@@ -221,7 +221,11 @@ QList<QNetworkProxy> macQueryInternal(const QNetworkProxyQuery &query)
int enabled;
if (CFNumberGetValue(pacEnabled, kCFNumberIntType, &enabled) && enabled) {
// PAC is enabled
- CFStringRef cfPacLocation = (CFStringRef)CFDictionaryGetValue(dict, kSCPropNetProxiesProxyAutoConfigURLString);
+ // kSCPropNetProxiesProxyAutoConfigURLString returns the URL string
+ // as entered in the system proxy configuration dialog
+ CFStringRef pacLocationSetting = (CFStringRef)CFDictionaryGetValue(dict, kSCPropNetProxiesProxyAutoConfigURLString);
+ QCFType<CFStringRef> cfPacLocation = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, pacLocationSetting, NULL, NULL,
+ kCFStringEncodingUTF8);
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) {
QCFType<CFDataRef> pacData;
--
1.8.3.4 (Apple Git-47)
@@ -1,38 +0,0 @@
From a83e4d1d9dd90d4563ce60f27dfb7802a780e33e Mon Sep 17 00:00:00 2001
From: Daniel Molkentin <daniel@molkentin.de>
Date: Mon, 5 Jan 2015 11:42:52 +0100
Subject: [PATCH 2/3] Fix possible crash when passing an invalid PAC URL
This commit checks whether CFURLCreateWithString() succeeded.
It does not appear to be possible to enter an empty URL directly in the
PAC configuration dialog but I can't rule out the possibility
that it could find its way into the settings via some other means.
Change-Id: I6c2053d385503bf0330f5ae9fb1ec36a473d425d
Patch-By: Robert Knight
Task-number: QTBUG-36787
Reviewed-by: Markus Goetz <markus@woboq.com>
Reviewed-by: Peter Hartmann <phartmann@blackberry.com>
---
src/network/kernel/qnetworkproxy_mac.cpp | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/network/kernel/qnetworkproxy_mac.cpp b/src/network/kernel/qnetworkproxy_mac.cpp
index 81bce0c..6be032e 100644
--- a/src/network/kernel/qnetworkproxy_mac.cpp
+++ b/src/network/kernel/qnetworkproxy_mac.cpp
@@ -230,6 +230,10 @@ QList<QNetworkProxy> macQueryInternal(const QNetworkProxyQuery &query)
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) {
QCFType<CFDataRef> pacData;
QCFType<CFURLRef> pacUrl = CFURLCreateWithString(kCFAllocatorDefault, cfPacLocation, NULL);
+ if (!pacUrl) {
+ qWarning("Invalid PAC URL \"%s\"", qPrintable(QCFString::toQString(cfPacLocation)));
+ return result;
+ }
SInt32 errorCode;
if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, pacUrl, &pacData, NULL, NULL, &errorCode)) {
QString pacLocation = QCFString::toQString(cfPacLocation);
--
1.8.3.4 (Apple Git-47)
@@ -1,39 +0,0 @@
From 83bd9393e5564ea9168fda90c0f44456633a483a Mon Sep 17 00:00:00 2001
From: Daniel Molkentin <daniel@molkentin.de>
Date: Mon, 5 Jan 2015 15:22:57 +0100
Subject: [PATCH 3/3] Fix crash if PAC script retrieval returns a null CFData
instance
The documentation for CFURLCreateDataAndPropertiesFromResource()
does not make this clear but from looking at the CFNetwork implementation
and a user stacktrace it appears that this function can return true
but not set the data argument under certain circumstances.
Change-Id: I48034a640d6f47a51cd5883bbafacad4bcbd0415
Task-number: QTBUG-36787
Patch-By: Robert Knight
Reviewed-by: Markus Goetz <markus@woboq.com>
Reviewed-by: Peter Hartmann <phartmann@blackberry.com>
---
src/network/kernel/qnetworkproxy_mac.cpp | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/network/kernel/qnetworkproxy_mac.cpp b/src/network/kernel/qnetworkproxy_mac.cpp
index 6be032e..a1ac349 100644
--- a/src/network/kernel/qnetworkproxy_mac.cpp
+++ b/src/network/kernel/qnetworkproxy_mac.cpp
@@ -240,7 +240,10 @@ QList<QNetworkProxy> macQueryInternal(const QNetworkProxyQuery &query)
qWarning("Unable to get the PAC script at \"%s\" (%s)", qPrintable(pacLocation), cfurlErrorDescription(errorCode));
return result;
}
-
+ if (!pacData) {
+ qWarning("\"%s\" returned an empty PAC script", qPrintable(QCFString::toQString(cfPacLocation)));
+ return result;
+ }
QCFType<CFStringRef> pacScript = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, pacData, kCFStringEncodingISOLatin1);
if (!pacScript) {
// This should never happen, but the documentation says it may return NULL if there was a problem creating the object.
--
1.8.3.4 (Apple Git-47)
@@ -1,32 +0,0 @@
From 22f3d359350fd65e4bbe2e9420fcc4460e8a590a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= <morten.sorvig@digia.com>
Date: Tue, 10 Mar 2015 22:37:39 +0100
Subject: [PATCH] Cocoa: Fix systray SVG icons.
Regression caused by f3699510.
Task-number: QTBUG-44686
Change-Id: I546422a67d4da29fac196025b09bddcb45c1b641
Reviewed-by: Timur Pocheptsov <Timur.Pocheptsov@digia.com>
---
src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
index e449fd3..8a35705 100755
--- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
@@ -234,6 +234,10 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
}
}
+ // Handle SVG icons, which do not return anything for availableSizes().
+ if (!selectedSize.isValid())
+ selectedSize = icon.actualSize(QSize(maxPixmapHeight, maxPixmapHeight), mode);
+
QPixmap pixmap = icon.pixmap(selectedSize, mode);
// Draw a low-resolution icon if there is not enough pixels for a retina
--
1.9.1
@@ -1,115 +0,0 @@
From ee7fea33383726f0bb72e8082a357820e3ee3675 Mon Sep 17 00:00:00 2001
From: Jocelyn Turcotte <jturcotte@woboq.com>
Date: Tue, 24 Feb 2015 17:02:02 +0100
Subject: [PATCH] OSX Fix disapearing tray icon
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
It would happen together with an error:
QPainter::begin: Paint device returned engine == 0
and would be caused by the size provided to QIcon::pixmap being empty,
itself caused by the availableSizes list being empty for the Selected
mode.
This bug was most often hidden by the fact that the Selected icon mode
was not triggered properly since we usually only set menuVisible after
calling updateIcon, and most of the time when it did, we would overwrite
it right after with a Normal mode icon.
Fix the issue by disabling the broken feature completely since the
default Selected icon is grayed out while tray icons are now usually
black (or white when selected). To support the dark menu bar mode on
10.10 we'll need to use NSImage's setTemplate anyway and that
knowing in advance if we can invert the colors ourselves would also
better solve the menuVisible usecase.
Task-number: QTBUG-42910
Change-Id: If9ec9659af28ecceb841bfc2f11721e6029fe891
Reviewed-by: Morten Johan Sørvig <morten.sorvig@theqtcompany.com>
---
src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm | 17 +++--------------
1 file changed, 3 insertions(+), 14 deletions(-)
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
index 8a35705..d366a3c 100755
--- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
@@ -102,7 +102,6 @@ QT_USE_NAMESPACE
QCocoaSystemTrayIcon *systray;
NSStatusItem *item;
QCocoaMenu *menu;
- bool menuVisible;
QIcon icon;
QT_MANGLE_NAMESPACE(QNSImageView) *imageCell;
}
@@ -202,8 +201,6 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
m_sys->item->icon = icon;
- const bool menuVisible = m_sys->item->menu && m_sys->item->menuVisible;
-
// The reccomended maximum title bar icon height is 18 points
// (device independent pixels). The menu height on past and
// current OS X versions is 22 points. Provide some future-proofing
@@ -218,9 +215,8 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
// devicePixelRatio for the "best" screen on the system.
qreal devicePixelRatio = qApp->devicePixelRatio();
const int maxPixmapHeight = maxImageHeight * devicePixelRatio;
- const QIcon::Mode mode = menuVisible ? QIcon::Selected : QIcon::Normal;
QSize selectedSize;
- Q_FOREACH (const QSize& size, sortByHeight(icon.availableSizes(mode))) {
+ Q_FOREACH (const QSize& size, sortByHeight(icon.availableSizes())) {
// Select a pixmap based on the height. We want the largest pixmap
// with a height smaller or equal to maxPixmapHeight. The pixmap
// may rectangular; assume it has a reasonable size. If there is
@@ -236,9 +232,9 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
// Handle SVG icons, which do not return anything for availableSizes().
if (!selectedSize.isValid())
- selectedSize = icon.actualSize(QSize(maxPixmapHeight, maxPixmapHeight), mode);
+ selectedSize = icon.actualSize(QSize(maxPixmapHeight, maxPixmapHeight));
- QPixmap pixmap = icon.pixmap(selectedSize, mode);
+ QPixmap pixmap = icon.pixmap(selectedSize);
// Draw a low-resolution icon if there is not enough pixels for a retina
// icon. This prevents showing a small icon on retina displays.
@@ -385,9 +381,6 @@ QT_END_NAMESPACE
Q_UNUSED(notification);
down = NO;
- parent->systray->updateIcon(parent->icon);
- parent->menuVisible = false;
-
[self setNeedsDisplay:YES];
}
@@ -397,8 +390,6 @@ QT_END_NAMESPACE
int clickCount = [mouseEvent clickCount];
[self setNeedsDisplay:YES];
- parent->systray->updateIcon(parent->icon);
-
if (clickCount == 2) {
[self menuTrackingDone:nil];
[parent doubleClickSelector:self];
@@ -454,7 +445,6 @@ QT_END_NAMESPACE
if (self) {
item = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
menu = 0;
- menuVisible = false;
systray = sys;
imageCell = [[QNSImageView alloc] initWithParent:self];
[item setView: imageCell];
@@ -498,7 +488,6 @@ QT_END_NAMESPACE
selector:@selector(menuTrackingDone:)
name:NSMenuDidEndTrackingNotification
object:m];
- menuVisible = true;
[item popUpStatusItemMenu: m];
}
}
--
1.9.1
@@ -1,691 +0,0 @@
From cff39fba10ffc10ee4dcfdc66ff6528eb26462d3 Mon Sep 17 00:00:00 2001
From: Markus Goetz <markus@woboq.com>
Date: Fri, 10 Apr 2015 14:09:53 +0200
Subject: [PATCH] QNAM: Fix upload corruptions when server closes connection
This patch fixes several upload corruptions if the server closes the connection
while/before we send data into it. They happen inside multiple places in the HTTP
layer and are explained in the comments.
Corruptions are:
* The upload byte device has an in-flight signal with pending upload data, if
it gets reset (because server closes the connection) then the re-send of the
request was sometimes taking this stale in-flight pending upload data.
* Because some signals were DirectConnection and some were QueuedConnection, there
was a chance that a direct signal overtakes a queued signal. The state machine
then sent data down the socket which was buffered there (and sent later) although
it did not match the current state of the state machine when it was actually sent.
* A socket was seen as being able to have requests sent even though it was not
encrypted yet. This relates to the previous corruption where data is stored inside
the socket's buffer and then sent later.
The included auto test produces all fixed corruptions, I detected no regressions
via the other tests.
This code also adds a bit of sanity checking to protect from possible further
problems.
[ChangeLog][QtNetwork] Fix HTTP(s) upload corruption when server closes connection
Change-Id: I54c883925ec897050941498f139c4b523030432e
Reviewed-by: Peter Hartmann <peter-qt@hartmann.tk>
---
src/corelib/io/qnoncontiguousbytedevice.cpp | 18 +++
src/corelib/io/qnoncontiguousbytedevice_p.h | 4 +
.../access/qhttpnetworkconnectionchannel.cpp | 35 ++++-
.../access/qhttpnetworkconnectionchannel_p.h | 2 +
src/network/access/qhttpprotocolhandler.cpp | 7 +
src/network/access/qhttpthreaddelegate_p.h | 36 ++++-
src/network/access/qnetworkreplyhttpimpl.cpp | 25 ++-
src/network/access/qnetworkreplyhttpimpl_p.h | 7 +-
.../access/qnetworkreply/tst_qnetworkreply.cpp | 175 ++++++++++++++++++++-
9 files changed, 279 insertions(+), 30 deletions(-)
diff --git a/src/corelib/io/qnoncontiguousbytedevice.cpp b/src/corelib/io/qnoncontiguousbytedevice.cpp
index 11510a8..760ca3d 100644
--- a/src/corelib/io/qnoncontiguousbytedevice.cpp
+++ b/src/corelib/io/qnoncontiguousbytedevice.cpp
@@ -236,6 +236,11 @@ qint64 QNonContiguousByteDeviceByteArrayImpl::size()
return byteArray->size();
}
+qint64 QNonContiguousByteDeviceByteArrayImpl::pos()
+{
+ return currentPosition;
+}
+
QNonContiguousByteDeviceRingBufferImpl::QNonContiguousByteDeviceRingBufferImpl(QSharedPointer<QRingBuffer> rb)
: QNonContiguousByteDevice(), currentPosition(0)
{
@@ -273,6 +278,11 @@ bool QNonContiguousByteDeviceRingBufferImpl::atEnd()
return currentPosition >= size();
}
+qint64 QNonContiguousByteDeviceRingBufferImpl::pos()
+{
+ return currentPosition;
+}
+
bool QNonContiguousByteDeviceRingBufferImpl::reset()
{
if (resetDisabled)
@@ -406,6 +416,14 @@ qint64 QNonContiguousByteDeviceIoDeviceImpl::size()
return device->size() - initialPosition;
}
+qint64 QNonContiguousByteDeviceIoDeviceImpl::pos()
+{
+ if (device->isSequential())
+ return -1;
+
+ return device->pos();
+}
+
QByteDeviceWrappingIoDevice::QByteDeviceWrappingIoDevice(QNonContiguousByteDevice *bd) : QIODevice((QObject*)0)
{
byteDevice = bd;
diff --git a/src/corelib/io/qnoncontiguousbytedevice_p.h b/src/corelib/io/qnoncontiguousbytedevice_p.h
index c05ae11..4d7b7b0 100644
--- a/src/corelib/io/qnoncontiguousbytedevice_p.h
+++ b/src/corelib/io/qnoncontiguousbytedevice_p.h
@@ -61,6 +61,7 @@ public:
virtual const char* readPointer(qint64 maximumLength, qint64 &len) = 0;
virtual bool advanceReadPointer(qint64 amount) = 0;
virtual bool atEnd() = 0;
+ virtual qint64 pos() { return -1; }
virtual bool reset() = 0;
void disableReset();
bool isResetDisabled() { return resetDisabled; }
@@ -106,6 +107,7 @@ public:
bool atEnd();
bool reset();
qint64 size();
+ qint64 pos() Q_DECL_OVERRIDE;
protected:
QByteArray* byteArray;
qint64 currentPosition;
@@ -121,6 +123,7 @@ public:
bool atEnd();
bool reset();
qint64 size();
+ qint64 pos() Q_DECL_OVERRIDE;
protected:
QSharedPointer<QRingBuffer> ringBuffer;
qint64 currentPosition;
@@ -138,6 +141,7 @@ public:
bool atEnd();
bool reset();
qint64 size();
+ qint64 pos() Q_DECL_OVERRIDE;
protected:
QIODevice* device;
QByteArray* currentReadBuffer;
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 9f63280..49c6793 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -106,15 +106,19 @@ void QHttpNetworkConnectionChannel::init()
socket->setProxy(QNetworkProxy::NoProxy);
#endif
+ // We want all signals (except the interactive ones) be connected as QueuedConnection
+ // because else we're falling into cases where we recurse back into the socket code
+ // and mess up the state. Always going to the event loop (and expecting that when reading/writing)
+ // is safer.
QObject::connect(socket, SIGNAL(bytesWritten(qint64)),
this, SLOT(_q_bytesWritten(qint64)),
- Qt::DirectConnection);
+ Qt::QueuedConnection);
QObject::connect(socket, SIGNAL(connected()),
this, SLOT(_q_connected()),
- Qt::DirectConnection);
+ Qt::QueuedConnection);
QObject::connect(socket, SIGNAL(readyRead()),
this, SLOT(_q_readyRead()),
- Qt::DirectConnection);
+ Qt::QueuedConnection);
// The disconnected() and error() signals may already come
// while calling connectToHost().
@@ -143,13 +147,13 @@ void QHttpNetworkConnectionChannel::init()
// won't be a sslSocket if encrypt is false
QObject::connect(sslSocket, SIGNAL(encrypted()),
this, SLOT(_q_encrypted()),
- Qt::DirectConnection);
+ Qt::QueuedConnection);
QObject::connect(sslSocket, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(_q_sslErrors(QList<QSslError>)),
Qt::DirectConnection);
QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)),
this, SLOT(_q_encryptedBytesWritten(qint64)),
- Qt::DirectConnection);
+ Qt::QueuedConnection);
if (ignoreAllSslErrors)
sslSocket->ignoreSslErrors();
@@ -186,8 +190,11 @@ void QHttpNetworkConnectionChannel::close()
// pendingEncrypt must only be true in between connected and encrypted states
pendingEncrypt = false;
- if (socket)
+ if (socket) {
+ // socket can be 0 since the host lookup is done from qhttpnetworkconnection.cpp while
+ // there is no socket yet.
socket->close();
+ }
}
@@ -353,6 +360,14 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
}
return false;
}
+
+ // This code path for ConnectedState
+ if (pendingEncrypt) {
+ // Let's only be really connected when we have received the encrypted() signal. Else the state machine seems to mess up
+ // and corrupt the things sent to the server.
+ return false;
+ }
+
return true;
}
@@ -659,6 +674,12 @@ bool QHttpNetworkConnectionChannel::isSocketReading() const
void QHttpNetworkConnectionChannel::_q_bytesWritten(qint64 bytes)
{
Q_UNUSED(bytes);
+ if (ssl) {
+ // In the SSL case we want to send data from encryptedBytesWritten signal since that one
+ // is the one going down to the actual network, not only into some SSL buffer.
+ return;
+ }
+
// bytes have been written to the socket. write even more of them :)
if (isSocketWriting())
sendRequest();
@@ -734,7 +755,7 @@ void QHttpNetworkConnectionChannel::_q_connected()
// ### FIXME: if the server closes the connection unexpectedly, we shouldn't send the same broken request again!
//channels[i].reconnectAttempts = 2;
- if (pendingEncrypt) {
+ if (ssl || pendingEncrypt) { // FIXME: Didn't work properly with pendingEncrypt only, we should refactor this into an EncrypingState
#ifndef QT_NO_SSL
if (connection->sslContext().isNull()) {
// this socket is making the 1st handshake for this connection,
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
index 692c0e6..231fe11 100644
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
@@ -83,6 +83,8 @@ typedef QPair<QHttpNetworkRequest, QHttpNetworkReply*> HttpMessagePair;
class QHttpNetworkConnectionChannel : public QObject {
Q_OBJECT
public:
+ // TODO: Refactor this to add an EncryptingState (and remove pendingEncrypt).
+ // Also add an Unconnected state so IdleState does not have double meaning.
enum ChannelState {
IdleState = 0, // ready to send request
ConnectingState = 1, // connecting to host
diff --git a/src/network/access/qhttpprotocolhandler.cpp b/src/network/access/qhttpprotocolhandler.cpp
index 28e10f7..3357948 100644
--- a/src/network/access/qhttpprotocolhandler.cpp
+++ b/src/network/access/qhttpprotocolhandler.cpp
@@ -368,6 +368,13 @@ bool QHttpProtocolHandler::sendRequest()
// nothing to read currently, break the loop
break;
} else {
+ if (m_channel->written != uploadByteDevice->pos()) {
+ // Sanity check. This was useful in tracking down an upload corruption.
+ qWarning() << "QHttpProtocolHandler: Internal error in sendRequest. Expected to write at position" << m_channel->written << "but read device is at" << uploadByteDevice->pos();
+ Q_ASSERT(m_channel->written == uploadByteDevice->pos());
+ m_connection->d_func()->emitReplyError(m_socket, m_reply, QNetworkReply::ProtocolFailure);
+ return false;
+ }
qint64 currentWriteSize = m_socket->write(readPointer, currentReadSize);
if (currentWriteSize == -1 || currentWriteSize != currentReadSize) {
// socket broke down
diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h
index 1661082..b553409 100644
--- a/src/network/access/qhttpthreaddelegate_p.h
+++ b/src/network/access/qhttpthreaddelegate_p.h
@@ -187,6 +187,7 @@ protected:
QByteArray m_dataArray;
bool m_atEnd;
qint64 m_size;
+ qint64 m_pos; // to match calls of haveDataSlot with the expected position
public:
QNonContiguousByteDeviceThreadForwardImpl(bool aE, qint64 s)
: QNonContiguousByteDevice(),
@@ -194,7 +195,8 @@ public:
m_amount(0),
m_data(0),
m_atEnd(aE),
- m_size(s)
+ m_size(s),
+ m_pos(0)
{
}
@@ -202,6 +204,11 @@ public:
{
}
+ qint64 pos() Q_DECL_OVERRIDE
+ {
+ return m_pos;
+ }
+
const char* readPointer(qint64 maximumLength, qint64 &len)
{
if (m_amount > 0) {
@@ -229,11 +236,10 @@ public:
m_amount -= a;
m_data += a;
+ m_pos += a;
- // To main thread to inform about our state
- emit processedData(a);
-
- // FIXME possible optimization, already ask user thread for some data
+ // To main thread to inform about our state. The m_pos will be sent as a sanity check.
+ emit processedData(m_pos, a);
return true;
}
@@ -250,10 +256,21 @@ public:
{
m_amount = 0;
m_data = 0;
+ m_dataArray.clear();
+
+ if (wantDataPending) {
+ // had requested the user thread to send some data (only 1 in-flight at any moment)
+ wantDataPending = false;
+ }
// Communicate as BlockingQueuedConnection
bool b = false;
emit resetData(&b);
+ if (b) {
+ // the reset succeeded, we're at pos 0 again
+ m_pos = 0;
+ // the HTTP code will anyway abort the request if !b.
+ }
return b;
}
@@ -264,8 +281,13 @@ public:
public slots:
// From user thread:
- void haveDataSlot(QByteArray dataArray, bool dataAtEnd, qint64 dataSize)
+ void haveDataSlot(qint64 pos, QByteArray dataArray, bool dataAtEnd, qint64 dataSize)
{
+ if (pos != m_pos) {
+ // Sometimes when re-sending a request in the qhttpnetwork* layer there is a pending haveData from the
+ // user thread on the way to us. We need to ignore it since it is the data for the wrong(later) chunk.
+ return;
+ }
wantDataPending = false;
m_dataArray = dataArray;
@@ -285,7 +307,7 @@ signals:
// to main thread:
void wantData(qint64);
- void processedData(qint64);
+ void processedData(qint64 pos, qint64 amount);
void resetData(bool *b);
};
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index 4ce7303..974a101 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -424,6 +424,7 @@ QNetworkReplyHttpImplPrivate::QNetworkReplyHttpImplPrivate()
, synchronous(false)
, state(Idle)
, statusCode(0)
+ , uploadByteDevicePosition(false)
, uploadDeviceChoking(false)
, outgoingData(0)
, bytesUploaded(-1)
@@ -863,9 +864,9 @@ void QNetworkReplyHttpImplPrivate::postRequest()
q, SLOT(uploadByteDeviceReadyReadSlot()),
Qt::QueuedConnection);
- // From main thread to user thread:
- QObject::connect(q, SIGNAL(haveUploadData(QByteArray,bool,qint64)),
- forwardUploadDevice, SLOT(haveDataSlot(QByteArray,bool,qint64)), Qt::QueuedConnection);
+ // From user thread to http thread:
+ QObject::connect(q, SIGNAL(haveUploadData(qint64,QByteArray,bool,qint64)),
+ forwardUploadDevice, SLOT(haveDataSlot(qint64,QByteArray,bool,qint64)), Qt::QueuedConnection);
QObject::connect(uploadByteDevice.data(), SIGNAL(readyRead()),
forwardUploadDevice, SIGNAL(readyRead()),
Qt::QueuedConnection);
@@ -873,8 +874,8 @@ void QNetworkReplyHttpImplPrivate::postRequest()
// From http thread to user thread:
QObject::connect(forwardUploadDevice, SIGNAL(wantData(qint64)),
q, SLOT(wantUploadDataSlot(qint64)));
- QObject::connect(forwardUploadDevice, SIGNAL(processedData(qint64)),
- q, SLOT(sentUploadDataSlot(qint64)));
+ QObject::connect(forwardUploadDevice,SIGNAL(processedData(qint64, qint64)),
+ q, SLOT(sentUploadDataSlot(qint64,qint64)));
QObject::connect(forwardUploadDevice, SIGNAL(resetData(bool*)),
q, SLOT(resetUploadDataSlot(bool*)),
Qt::BlockingQueuedConnection); // this is the only one with BlockingQueued!
@@ -1268,12 +1269,22 @@ void QNetworkReplyHttpImplPrivate::replySslConfigurationChanged(const QSslConfig
void QNetworkReplyHttpImplPrivate::resetUploadDataSlot(bool *r)
{
*r = uploadByteDevice->reset();
+ if (*r) {
+ // reset our own position which is used for the inter-thread communication
+ uploadByteDevicePosition = 0;
+ }
}
// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
-void QNetworkReplyHttpImplPrivate::sentUploadDataSlot(qint64 amount)
+void QNetworkReplyHttpImplPrivate::sentUploadDataSlot(qint64 pos, qint64 amount)
{
+ if (uploadByteDevicePosition + amount != pos) {
+ // Sanity check, should not happen.
+ error(QNetworkReply::UnknownNetworkError, "");
+ return;
+ }
uploadByteDevice->advanceReadPointer(amount);
+ uploadByteDevicePosition += amount;
}
// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
@@ -1298,7 +1309,7 @@ void QNetworkReplyHttpImplPrivate::wantUploadDataSlot(qint64 maxSize)
QByteArray dataArray(data, currentUploadDataLength);
// Communicate back to HTTP thread
- emit q->haveUploadData(dataArray, uploadByteDevice->atEnd(), uploadByteDevice->size());
+ emit q->haveUploadData(uploadByteDevicePosition, dataArray, uploadByteDevice->atEnd(), uploadByteDevice->size());
}
void QNetworkReplyHttpImplPrivate::uploadByteDeviceReadyReadSlot()
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
index 77d9c5a..1940922 100644
--- a/src/network/access/qnetworkreplyhttpimpl_p.h
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -120,7 +120,7 @@ public:
Q_PRIVATE_SLOT(d_func(), void resetUploadDataSlot(bool *r))
Q_PRIVATE_SLOT(d_func(), void wantUploadDataSlot(qint64))
- Q_PRIVATE_SLOT(d_func(), void sentUploadDataSlot(qint64))
+ Q_PRIVATE_SLOT(d_func(), void sentUploadDataSlot(qint64,qint64))
Q_PRIVATE_SLOT(d_func(), void uploadByteDeviceReadyReadSlot())
Q_PRIVATE_SLOT(d_func(), void emitReplyUploadProgress(qint64, qint64))
Q_PRIVATE_SLOT(d_func(), void _q_cacheSaveDeviceAboutToClose())
@@ -144,7 +144,7 @@ signals:
void startHttpRequestSynchronously();
- void haveUploadData(QByteArray dataArray, bool dataAtEnd, qint64 dataSize);
+ void haveUploadData(const qint64 pos, QByteArray dataArray, bool dataAtEnd, qint64 dataSize);
};
class QNetworkReplyHttpImplPrivate: public QNetworkReplyPrivate
@@ -195,6 +195,7 @@ public:
// upload
QNonContiguousByteDevice* createUploadByteDevice();
QSharedPointer<QNonContiguousByteDevice> uploadByteDevice;
+ qint64 uploadByteDevicePosition;
bool uploadDeviceChoking; // if we couldn't readPointer() any data at the moment
QIODevice *outgoingData;
QSharedPointer<QRingBuffer> outgoingDataBuffer;
@@ -283,7 +284,7 @@ public:
// From QNonContiguousByteDeviceThreadForwardImpl in HTTP thread:
void resetUploadDataSlot(bool *r);
void wantUploadDataSlot(qint64);
- void sentUploadDataSlot(qint64);
+ void sentUploadDataSlot(qint64, qint64);
// From user's QNonContiguousByteDevice
void uploadByteDeviceReadyReadSlot();
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index 3ccedf6..d2edf67 100644
--- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -457,6 +457,10 @@ private Q_SLOTS:
void putWithRateLimiting();
+#ifndef QT_NO_SSL
+ void putWithServerClosingConnectionImmediately();
+#endif
+
// NOTE: This test must be last!
void parentingRepliesToTheApp();
private:
@@ -4718,18 +4722,22 @@ void tst_QNetworkReply::ioPostToHttpNoBufferFlag()
class SslServer : public QTcpServer {
Q_OBJECT
public:
- SslServer() : socket(0) {};
+ SslServer() : socket(0), m_ssl(true) {}
void incomingConnection(qintptr socketDescriptor) {
QSslSocket *serverSocket = new QSslSocket;
serverSocket->setParent(this);
if (serverSocket->setSocketDescriptor(socketDescriptor)) {
+ connect(serverSocket, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
+ if (!m_ssl) {
+ emit newPlainConnection(serverSocket);
+ return;
+ }
QString testDataDir = QFileInfo(QFINDTESTDATA("rfc3252.txt")).absolutePath();
if (testDataDir.isEmpty())
testDataDir = QCoreApplication::applicationDirPath();
connect(serverSocket, SIGNAL(encrypted()), this, SLOT(encryptedSlot()));
- connect(serverSocket, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
serverSocket->setProtocol(QSsl::AnyProtocol);
connect(serverSocket, SIGNAL(sslErrors(QList<QSslError>)), serverSocket, SLOT(ignoreSslErrors()));
serverSocket->setLocalCertificate(testDataDir + "/certs/server.pem");
@@ -4740,11 +4748,12 @@ public:
}
}
signals:
- void newEncryptedConnection();
+ void newEncryptedConnection(QSslSocket *s);
+ void newPlainConnection(QSslSocket *s);
public slots:
void encryptedSlot() {
socket = (QSslSocket*) sender();
- emit newEncryptedConnection();
+ emit newEncryptedConnection(socket);
}
void readyReadSlot() {
// for the incoming sockets, not the server socket
@@ -4753,6 +4762,7 @@ public slots:
public:
QSslSocket *socket;
+ bool m_ssl;
};
// very similar to ioPostToHttpUploadProgress but for SSL
@@ -4780,7 +4790,7 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress()
QNetworkReplyPtr reply(manager.post(request, sourceFile));
QSignalSpy spy(reply.data(), SIGNAL(uploadProgress(qint64,qint64)));
- connect(&server, SIGNAL(newEncryptedConnection()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ connect(&server, SIGNAL(newEncryptedConnection(QSslSocket*)), &QTestEventLoop::instance(), SLOT(exitLoop()));
connect(reply, SIGNAL(sslErrors(QList<QSslError>)), reply.data(), SLOT(ignoreSslErrors()));
// get the request started and the incoming socket connected
@@ -4788,7 +4798,7 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress()
QVERIFY(!QTestEventLoop::instance().timeout());
QTcpSocket *incomingSocket = server.socket;
QVERIFY(incomingSocket);
- disconnect(&server, SIGNAL(newEncryptedConnection()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ disconnect(&server, SIGNAL(newEncryptedConnection(QSslSocket*)), &QTestEventLoop::instance(), SLOT(exitLoop()));
incomingSocket->setReadBufferSize(1*1024);
@@ -7905,6 +7915,159 @@ void tst_QNetworkReply::putWithRateLimiting()
}
+#ifndef QT_NO_SSL
+
+class PutWithServerClosingConnectionImmediatelyHandler: public QObject
+{
+ Q_OBJECT
+public:
+ bool m_parsedHeaders;
+ QByteArray m_receivedData;
+ QByteArray m_expectedData;
+ QSslSocket *m_socket;
+ PutWithServerClosingConnectionImmediatelyHandler(QSslSocket *s, QByteArray expected) :m_parsedHeaders(false), m_expectedData(expected), m_socket(s)
+ {
+ m_socket->setParent(this);
+ connect(m_socket, SIGNAL(readyRead()), SLOT(readyReadSlot()));
+ connect(m_socket, SIGNAL(disconnected()), SLOT(disconnectedSlot()));
+ }
+signals:
+ void correctFileUploadReceived();
+ void corruptFileUploadReceived();
+
+public slots:
+ void closeDelayed() {
+ m_socket->close();
+ }
+
+ void readyReadSlot()
+ {
+ QByteArray data = m_socket->readAll();
+ m_receivedData += data;
+ if (!m_parsedHeaders && m_receivedData.contains("\r\n\r\n")) {
+ m_parsedHeaders = true;
+ QTimer::singleShot(qrand()%10, this, SLOT(closeDelayed())); // simulate random network latency
+ // This server simulates a web server connection closing, e.g. because of Apaches MaxKeepAliveRequests or KeepAliveTimeout
+ // In this case QNAM needs to re-send the upload data but it had a bug which then corrupts the upload
+ // This test catches that.
+ }
+
+ }
+ void disconnectedSlot()
+ {
+ if (m_parsedHeaders) {
+ //qDebug() << m_receivedData.left(m_receivedData.indexOf("\r\n\r\n"));
+ m_receivedData = m_receivedData.mid(m_receivedData.indexOf("\r\n\r\n")+4); // check only actual data
+ }
+ if (m_receivedData.length() > 0 && !m_expectedData.startsWith(m_receivedData)) {
+ // We had received some data but it is corrupt!
+ qDebug() << "CORRUPT" << m_receivedData.count();
+
+ // Use this to track down the pattern of the corruption and conclude the source
+// QFile a("/tmp/corrupt");
+// a.open(QIODevice::WriteOnly);
+// a.write(m_receivedData);
+// a.close();
+
+// QFile b("/tmp/correct");
+// b.open(QIODevice::WriteOnly);
+// b.write(m_expectedData);
+// b.close();
+ //exit(1);
+ emit corruptFileUploadReceived();
+ } else {
+ emit correctFileUploadReceived();
+ }
+ }
+};
+
+class PutWithServerClosingConnectionImmediatelyServer: public SslServer
+{
+ Q_OBJECT
+public:
+ int m_correctUploads;
+ int m_corruptUploads;
+ int m_repliesFinished;
+ int m_expectedReplies;
+ QByteArray m_expectedData;
+ PutWithServerClosingConnectionImmediatelyServer() : SslServer(), m_correctUploads(0), m_corruptUploads(0), m_repliesFinished(0), m_expectedReplies(0)
+ {
+ QObject::connect(this, SIGNAL(newEncryptedConnection(QSslSocket*)), this, SLOT(createHandlerForConnection(QSslSocket*)));
+ QObject::connect(this, SIGNAL(newPlainConnection(QSslSocket*)), this, SLOT(createHandlerForConnection(QSslSocket*)));
+ }
+
+public slots:
+ void createHandlerForConnection(QSslSocket* s) {
+ PutWithServerClosingConnectionImmediatelyHandler *handler = new PutWithServerClosingConnectionImmediatelyHandler(s, m_expectedData);
+ handler->setParent(this);
+ QObject::connect(handler, SIGNAL(correctFileUploadReceived()), this, SLOT(increaseCorrect()));
+ QObject::connect(handler, SIGNAL(corruptFileUploadReceived()), this, SLOT(increaseCorrupt()));
+ }
+ void increaseCorrect() {
+ m_correctUploads++;
+ }
+ void increaseCorrupt() {
+ m_corruptUploads++;
+ }
+ void replyFinished() {
+ m_repliesFinished++;
+ if (m_repliesFinished == m_expectedReplies) {
+ QTestEventLoop::instance().exitLoop();
+ }
+ }
+};
+
+
+
+void tst_QNetworkReply::putWithServerClosingConnectionImmediately()
+{
+ const int numUploads = 40;
+ qint64 wantedSize = 512*1024; // 512 kB
+ QByteArray sourceFile;
+ for (int i = 0; i < wantedSize; ++i) {
+ sourceFile += (char)'a' +(i%26);
+ }
+ bool withSsl = false;
+
+ for (int s = 0; s <= 1; s++) {
+ withSsl = (s == 1);
+ // Test also needs to run several times because of 9c2ecf89
+ for (int j = 0; j < 20; j++) {
+ // emulate a minimal https server
+ PutWithServerClosingConnectionImmediatelyServer server;
+ server.m_ssl = withSsl;
+ server.m_expectedData = sourceFile;
+ server.m_expectedReplies = numUploads;
+ server.listen(QHostAddress(QHostAddress::LocalHost), 0);
+
+ for (int i = 0; i < numUploads; i++) {
+ // create the request
+ QUrl url = QUrl(QString("http%1://127.0.0.1:%2/file=%3").arg(withSsl ? "s" : "").arg(server.serverPort()).arg(i));
+ QNetworkRequest request(url);
+ QNetworkReply *reply = manager.put(request, sourceFile);
+ connect(reply, SIGNAL(sslErrors(QList<QSslError>)), reply, SLOT(ignoreSslErrors()));
+ connect(reply, SIGNAL(finished()), &server, SLOT(replyFinished()));
+ reply->setParent(&server);
+ }
+
+ // get the request started and the incoming socket connected
+ QTestEventLoop::instance().enterLoop(10);
+
+ //qDebug() << "correct=" << server.m_correctUploads << "corrupt=" << server.m_corruptUploads << "expected=" <<numUploads;
+
+ // Sanity check because ecause of 9c2ecf89 most replies will error out but we want to make sure at least some of them worked
+ QVERIFY(server.m_correctUploads > 5);
+ // Because actually important is that we don't get any corruption:
+ QCOMPARE(server.m_corruptUploads, 0);
+
+ server.close();
+ }
+ }
+
+
+}
+
+#endif
// NOTE: This test must be last testcase in tst_qnetworkreply!
void tst_QNetworkReply::parentingRepliesToTheApp()
--
1.9.1
@@ -1,434 +0,0 @@
From eae0cb09f1310e755c2aff7c1112f7a6c09d7a53 Mon Sep 17 00:00:00 2001
From: Markus Goetz <markus@woboq.com>
Date: Fri, 19 Jun 2015 15:35:34 +0200
Subject: [PATCH] Network: Fix up previous corruption patch
This is a fix-up for cff39fba10ffc10ee4dcfdc66ff6528eb26462d3.
That patch lead to some internal state issues that lead to the QTBUG-47048
or to QNetworkReply objects erroring with "Connection Closed" when
the server closed the Keep-Alive connection.
This patch changes the QNAM socket slot connections to be DirectConnection.
We don't close the socket anymore in slots where it is anyway in a closed state
afterwards. This prevents event/stack recursions.
We also flush QSslSocket/QTcpSocket receive buffers when receiving a disconnect
so that the developer always gets the full decrypted data from the buffers.
[ChangeLog][QtNetwork] Fix HTTP issues with "Unknown Error" and "Connection Closed"
[ChangeLog][QtNetwork][Sockets] Read OS/encrypted read buffers when connection
closed by server.
Change-Id: Ib4d6a2d0d988317e3a5356f36e8dbcee4590beed
Task-number: QTBUG-47048
Reviewed-by: Kai Koehne <kai.koehne@theqtcompany.com>
Reviewed-by: Richard J. Moore <rich@kde.org>
---
src/network/access/qhttpnetworkconnection.cpp | 1 -
.../access/qhttpnetworkconnectionchannel.cpp | 108 +++++++++++++--------
.../access/qhttpnetworkconnectionchannel_p.h | 1 +
src/network/access/qhttpnetworkreply.cpp | 2 +-
src/network/access/qhttpprotocolhandler.cpp | 1 -
src/network/socket/qabstractsocket.cpp | 7 +-
src/network/ssl/qsslsocket.cpp | 8 ++
src/network/ssl/qsslsocket_openssl.cpp | 7 ++
.../access/qnetworkreply/tst_qnetworkreply.cpp | 9 +-
9 files changed, 94 insertions(+), 50 deletions(-)
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 365ce55..543c70e 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -917,7 +917,6 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
for (int i = 0; i < channelCount; ++i) {
if (channels[i].resendCurrent && (channels[i].state != QHttpNetworkConnectionChannel::ClosingState)) {
channels[i].resendCurrent = false;
- channels[i].state = QHttpNetworkConnectionChannel::IdleState;
// if this is not possible, error will be emitted and connection terminated
if (!channels[i].resetUploadData())
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 49c6793..e2f6307 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -58,6 +58,11 @@ QT_BEGIN_NAMESPACE
// TODO: Put channel specific stuff here so it does not polute qhttpnetworkconnection.cpp
+// Because in-flight when sending a request, the server might close our connection (because the persistent HTTP
+// connection times out)
+// We use 3 because we can get a _q_error 3 times depending on the timing:
+static const int reconnectAttemptsDefault = 3;
+
QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel()
: socket(0)
, ssl(false)
@@ -69,7 +74,7 @@ QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel()
, resendCurrent(false)
, lastStatus(0)
, pendingEncrypt(false)
- , reconnectAttempts(2)
+ , reconnectAttempts(reconnectAttemptsDefault)
, authMethod(QAuthenticatorPrivate::None)
, proxyAuthMethod(QAuthenticatorPrivate::None)
, authenticationCredentialsSent(false)
@@ -106,19 +111,18 @@ void QHttpNetworkConnectionChannel::init()
socket->setProxy(QNetworkProxy::NoProxy);
#endif
- // We want all signals (except the interactive ones) be connected as QueuedConnection
- // because else we're falling into cases where we recurse back into the socket code
- // and mess up the state. Always going to the event loop (and expecting that when reading/writing)
- // is safer.
+ // After some back and forth in all the last years, this is now a DirectConnection because otherwise
+ // the state inside the *Socket classes gets messed up, also in conjunction with the socket notifiers
+ // which behave slightly differently on Windows vs Linux
QObject::connect(socket, SIGNAL(bytesWritten(qint64)),
this, SLOT(_q_bytesWritten(qint64)),
- Qt::QueuedConnection);
+ Qt::DirectConnection);
QObject::connect(socket, SIGNAL(connected()),
this, SLOT(_q_connected()),
- Qt::QueuedConnection);
+ Qt::DirectConnection);
QObject::connect(socket, SIGNAL(readyRead()),
this, SLOT(_q_readyRead()),
- Qt::QueuedConnection);
+ Qt::DirectConnection);
// The disconnected() and error() signals may already come
// while calling connectToHost().
@@ -129,10 +133,10 @@ void QHttpNetworkConnectionChannel::init()
qRegisterMetaType<QAbstractSocket::SocketError>();
QObject::connect(socket, SIGNAL(disconnected()),
this, SLOT(_q_disconnected()),
- Qt::QueuedConnection);
+ Qt::DirectConnection);
QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(_q_error(QAbstractSocket::SocketError)),
- Qt::QueuedConnection);
+ Qt::DirectConnection);
#ifndef QT_NO_NETWORKPROXY
@@ -147,13 +151,13 @@ void QHttpNetworkConnectionChannel::init()
// won't be a sslSocket if encrypt is false
QObject::connect(sslSocket, SIGNAL(encrypted()),
this, SLOT(_q_encrypted()),
- Qt::QueuedConnection);
+ Qt::DirectConnection);
QObject::connect(sslSocket, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(_q_sslErrors(QList<QSslError>)),
Qt::DirectConnection);
QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)),
this, SLOT(_q_encryptedBytesWritten(qint64)),
- Qt::QueuedConnection);
+ Qt::DirectConnection);
if (ignoreAllSslErrors)
sslSocket->ignoreSslErrors();
@@ -397,7 +401,7 @@ void QHttpNetworkConnectionChannel::allDone()
// reset the reconnection attempts after we receive a complete reply.
// in case of failures, each channel will attempt two reconnects before emitting error.
- reconnectAttempts = 2;
+ reconnectAttempts = reconnectAttemptsDefault;
// now the channel can be seen as free/idle again, all signal emissions for the reply have been done
if (state != QHttpNetworkConnectionChannel::ClosingState)
@@ -651,6 +655,15 @@ void QHttpNetworkConnectionChannel::closeAndResendCurrentRequest()
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
}
+void QHttpNetworkConnectionChannel::resendCurrentRequest()
+{
+ requeueCurrentlyPipelinedRequests();
+ if (reply)
+ resendCurrent = true;
+ if (qobject_cast<QHttpNetworkConnection*>(connection))
+ QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
+}
+
bool QHttpNetworkConnectionChannel::isSocketBusy() const
{
return (state & QHttpNetworkConnectionChannel::BusyState);
@@ -694,8 +707,8 @@ void QHttpNetworkConnectionChannel::_q_disconnected()
return;
}
- // read the available data before closing
- if (isSocketWaiting() || isSocketReading()) {
+ // read the available data before closing (also done in _q_error for other codepaths)
+ if ((isSocketWaiting() || isSocketReading()) && socket->bytesAvailable()) {
if (reply) {
state = QHttpNetworkConnectionChannel::ReadingState;
_q_receiveReply();
@@ -707,7 +720,8 @@ void QHttpNetworkConnectionChannel::_q_disconnected()
state = QHttpNetworkConnectionChannel::IdleState;
requeueCurrentlyPipelinedRequests();
- close();
+
+ pendingEncrypt = false;
}
@@ -789,11 +803,19 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
errorCode = QNetworkReply::ConnectionRefusedError;
break;
case QAbstractSocket::RemoteHostClosedError:
- // try to reconnect/resend before sending an error.
- // while "Reading" the _q_disconnected() will handle this.
- if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) {
+ // This error for SSL comes twice in a row, first from SSL layer ("The TLS/SSL connection has been closed") then from TCP layer.
+ // Depending on timing it can also come three times in a row (first time when we try to write into a closing QSslSocket).
+ // The reconnectAttempts handling catches the cases where we can re-send the request.
+ if (!reply && state == QHttpNetworkConnectionChannel::IdleState) {
+ // Not actually an error, it is normal for Keep-Alive connections to close after some time if no request
+ // is sent on them. No need to error the other replies below. Just bail out here.
+ // The _q_disconnected will handle the possibly pipelined replies
+ return;
+ } else if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) {
+ // Try to reconnect/resend before sending an error.
+ // While "Reading" the _q_disconnected() will handle this.
if (reconnectAttempts-- > 0) {
- closeAndResendCurrentRequest();
+ resendCurrentRequest();
return;
} else {
errorCode = QNetworkReply::RemoteHostClosedError;
@@ -818,24 +840,15 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
// we can ignore the readbuffersize as the data is already
// in memory and we will not receive more data on the socket.
reply->setReadBufferSize(0);
+ reply->setDownstreamLimited(false);
_q_receiveReply();
-#ifndef QT_NO_SSL
- if (ssl) {
- // QT_NO_OPENSSL. The QSslSocket can still have encrypted bytes in the plainsocket.
- // So we need to check this if the socket is a QSslSocket. When the socket is flushed
- // it will force a decrypt of the encrypted data in the plainsocket.
- QSslSocket *sslSocket = static_cast<QSslSocket*>(socket);
- qint64 beforeFlush = sslSocket->encryptedBytesAvailable();
- while (sslSocket->encryptedBytesAvailable()) {
- sslSocket->flush();
- _q_receiveReply();
- qint64 afterFlush = sslSocket->encryptedBytesAvailable();
- if (afterFlush == beforeFlush)
- break;
- beforeFlush = afterFlush;
- }
+ if (!reply) {
+ // No more reply assigned after the previous call? Then it had been finished successfully.
+ requeueCurrentlyPipelinedRequests();
+ state = QHttpNetworkConnectionChannel::IdleState;
+ QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
+ return;
}
-#endif
}
errorCode = QNetworkReply::RemoteHostClosedError;
@@ -846,7 +859,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
case QAbstractSocket::SocketTimeoutError:
// try to reconnect/resend before sending an error.
if (state == QHttpNetworkConnectionChannel::WritingState && (reconnectAttempts-- > 0)) {
- closeAndResendCurrentRequest();
+ resendCurrentRequest();
return;
}
errorCode = QNetworkReply::TimeoutError;
@@ -860,7 +873,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
case QAbstractSocket::ProxyConnectionClosedError:
// try to reconnect/resend before sending an error.
if (reconnectAttempts-- > 0) {
- closeAndResendCurrentRequest();
+ resendCurrentRequest();
return;
}
errorCode = QNetworkReply::ProxyConnectionClosedError;
@@ -868,7 +881,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
case QAbstractSocket::ProxyConnectionTimeoutError:
// try to reconnect/resend before sending an error.
if (reconnectAttempts-- > 0) {
- closeAndResendCurrentRequest();
+ resendCurrentRequest();
return;
}
errorCode = QNetworkReply::ProxyTimeoutError;
@@ -916,8 +929,18 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
// send the next request
QMetaObject::invokeMethod(that, "_q_startNextRequest", Qt::QueuedConnection);
- if (that) //signal emission triggered event loop
- close();
+ if (that) {
+ //signal emission triggered event loop
+ if (!socket)
+ state = QHttpNetworkConnectionChannel::IdleState;
+ else if (socket->state() == QAbstractSocket::UnconnectedState)
+ state = QHttpNetworkConnectionChannel::IdleState;
+ else
+ state = QHttpNetworkConnectionChannel::ClosingState;
+
+ // pendingEncrypt must only be true in between connected and encrypted states
+ pendingEncrypt = false;
+ }
}
#ifndef QT_NO_NETWORKPROXY
@@ -941,7 +964,8 @@ void QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired(const QNetwor
void QHttpNetworkConnectionChannel::_q_uploadDataReadyRead()
{
- sendRequest();
+ if (reply)
+ sendRequest();
}
#ifndef QT_NO_SSL
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
index 231fe11..a834b7d 100644
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
@@ -169,6 +169,7 @@ public:
void handleUnexpectedEOF();
void closeAndResendCurrentRequest();
+ void resendCurrentRequest();
bool isSocketBusy() const;
bool isSocketWriting() const;
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index 55863a3..8b71bd8 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -191,7 +191,7 @@ QByteArray QHttpNetworkReply::readAny()
return QByteArray();
// we'll take the last buffer, so schedule another read from http
- if (d->downstreamLimited && d->responseData.bufferCount() == 1)
+ if (d->downstreamLimited && d->responseData.bufferCount() == 1 && !isFinished())
d->connection->d_func()->readMoreLater(this);
return d->responseData.read();
}
diff --git a/src/network/access/qhttpprotocolhandler.cpp b/src/network/access/qhttpprotocolhandler.cpp
index 3357948..380aaac 100644
--- a/src/network/access/qhttpprotocolhandler.cpp
+++ b/src/network/access/qhttpprotocolhandler.cpp
@@ -250,7 +250,6 @@ bool QHttpProtocolHandler::sendRequest()
if (!m_reply) {
// heh, how should that happen!
qWarning() << "QAbstractProtocolHandler::sendRequest() called without QHttpNetworkReply";
- m_channel->state = QHttpNetworkConnectionChannel::IdleState;
return false;
}
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index 2666771..0e82d4a 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -768,6 +768,7 @@ bool QAbstractSocketPrivate::canReadNotification()
void QAbstractSocketPrivate::canCloseNotification()
{
Q_Q(QAbstractSocket);
+ // Note that this method is only called on Windows. Other platforms close in the canReadNotification()
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocketPrivate::canCloseNotification()");
@@ -777,7 +778,11 @@ void QAbstractSocketPrivate::canCloseNotification()
if (isBuffered) {
// Try to read to the buffer, if the read fail we can close the socket.
newBytes = buffer.size();
- if (!readFromSocket()) {
+ qint64 oldReadBufferMaxSize = readBufferMaxSize;
+ readBufferMaxSize = 0; // temporarily disable max read buffer, we want to empty the OS buffer
+ bool hadReadFromSocket = readFromSocket();
+ readBufferMaxSize = oldReadBufferMaxSize;
+ if (!hadReadFromSocket) {
q->disconnectFromHost();
return;
}
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index c1fab94..2b9e923 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -2294,6 +2294,14 @@ void QSslSocketPrivate::_q_errorSlot(QAbstractSocket::SocketError error)
qCDebug(lcSsl) << "\tstate =" << q->state();
qCDebug(lcSsl) << "\terrorString =" << q->errorString();
#endif
+ // this moves encrypted bytes from plain socket into our buffer
+ if (plainSocket->bytesAvailable()) {
+ qint64 tmpReadBufferMaxSize = readBufferMaxSize;
+ readBufferMaxSize = 0; // reset temporarily so the plain sockets completely drained drained
+ transmit();
+ readBufferMaxSize = tmpReadBufferMaxSize;
+ }
+
q->setSocketError(plainSocket->error());
q->setErrorString(plainSocket->errorString());
emit q->error(error);
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index ac4336a..94655fe 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -1419,6 +1419,13 @@ void QSslSocketBackendPrivate::disconnected()
{
if (plainSocket->bytesAvailable() <= 0)
destroySslContext();
+ else {
+ // Move all bytes into the plain buffer
+ qint64 tmpReadBufferMaxSize = readBufferMaxSize;
+ readBufferMaxSize = 0; // reset temporarily so the plain socket buffer is completely drained
+ transmit();
+ readBufferMaxSize = tmpReadBufferMaxSize;
+ }
//if there is still buffered data in the plain socket, don't destroy the ssl context yet.
//it will be destroyed when the socket is deleted.
}
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index d2edf67..138f528 100644
--- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -1051,7 +1051,7 @@ protected:
// clean up QAbstractSocket's residue:
while (client->bytesToWrite() > 0) {
qDebug() << "Still having" << client->bytesToWrite() << "bytes to write, doing that now";
- if (!client->waitForBytesWritten(2000)) {
+ if (!client->waitForBytesWritten(10000)) {
qDebug() << "ERROR: FastSender:" << client->error() << "cleaning up residue";
return;
}
@@ -1071,7 +1071,7 @@ protected:
measuredSentBytes += writeNextData(client, bytesToWrite);
while (client->bytesToWrite() > 0) {
- if (!client->waitForBytesWritten(2000)) {
+ if (!client->waitForBytesWritten(10000)) {
qDebug() << "ERROR: FastSender:" << client->error() << "during blocking write";
return;
}
@@ -7946,7 +7946,7 @@ public slots:
m_receivedData += data;
if (!m_parsedHeaders && m_receivedData.contains("\r\n\r\n")) {
m_parsedHeaders = true;
- QTimer::singleShot(qrand()%10, this, SLOT(closeDelayed())); // simulate random network latency
+ QTimer::singleShot(qrand()%60, this, SLOT(closeDelayed())); // simulate random network latency
// This server simulates a web server connection closing, e.g. because of Apaches MaxKeepAliveRequests or KeepAliveTimeout
// In this case QNAM needs to re-send the upload data but it had a bug which then corrupts the upload
// This test catches that.
@@ -8052,11 +8052,12 @@ void tst_QNetworkReply::putWithServerClosingConnectionImmediately()
// get the request started and the incoming socket connected
QTestEventLoop::instance().enterLoop(10);
+ QVERIFY(!QTestEventLoop::instance().timeout());
//qDebug() << "correct=" << server.m_correctUploads << "corrupt=" << server.m_corruptUploads << "expected=" <<numUploads;
// Sanity check because ecause of 9c2ecf89 most replies will error out but we want to make sure at least some of them worked
- QVERIFY(server.m_correctUploads > 5);
+ QVERIFY(server.m_correctUploads > 2);
// Because actually important is that we don't get any corruption:
QCOMPARE(server.m_corruptUploads, 0);
--
1.9.1
@@ -1,64 +0,0 @@
From bc32c0ebc0bc00db84ca2f28eb16ab2e5b53a1b6 Mon Sep 17 00:00:00 2001
From: Markus Goetz <markus@woboq.com>
Date: Fri, 24 Jul 2015 09:53:20 +0200
Subject: [PATCH] QNAM: Fix reply deadlocks on server closing connection
The _q_readyRead can also be called from readMoreLater() because we implemented
it so that bandwidth limited reading can be implemented.
This can lead to a race condition if the socket is closing at the specific moment
and then deadlock the channel: It will stay unusable with a zombie request.
The fix in QHttpProtocolaHandler checks if there is actually bytes available to read
from the socket and only then continue.
The fix in the HTTP channel needs to be done to properly finish the reply in
cases of a server replying with HTTP/1.0 or "Connection: close".
The delayed incovation of _q_receiveReply will properly finish up the reply.
Change-Id: I19ce2ae595f91d56386cc7406ccacc9935672b6b
Reviewed-by: Richard J. Moore <rich@kde.org>
---
src/network/access/qhttpnetworkconnectionchannel.cpp | 4 ++++
src/network/access/qhttpprotocolhandler.cpp | 7 ++++++-
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 7428f9b..257aa13 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -829,11 +829,15 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
if (!reply->d_func()->expectContent()) {
// No content expected, this is a valid way to have the connection closed by the server
+ // We need to invoke this asynchronously to make sure the state() of the socket is on QAbstractSocket::UnconnectedState
+ QMetaObject::invokeMethod(this, "_q_receiveReply", Qt::QueuedConnection);
return;
}
if (reply->contentLength() == -1 && !reply->d_func()->isChunked()) {
// There was no content-length header and it's not chunked encoding,
// so this is a valid way to have the connection closed by the server
+ // We need to invoke this asynchronously to make sure the state() of the socket is on QAbstractSocket::UnconnectedState
+ QMetaObject::invokeMethod(this, "_q_receiveReply", Qt::QueuedConnection);
return;
}
// ok, we got a disconnect even though we did not expect it
diff --git a/src/network/access/qhttpprotocolhandler.cpp b/src/network/access/qhttpprotocolhandler.cpp
index ab2e3da..a208315 100644
--- a/src/network/access/qhttpprotocolhandler.cpp
+++ b/src/network/access/qhttpprotocolhandler.cpp
@@ -237,7 +237,12 @@ void QHttpProtocolHandler::_q_readyRead()
}
if (m_channel->isSocketWaiting() || m_channel->isSocketReading()) {
- m_channel->state = QHttpNetworkConnectionChannel::ReadingState;
+ if (m_socket->bytesAvailable()) {
+ // We might get a spurious call from readMoreLater()
+ // call of the QHttpNetworkConnection even while the socket is disconnecting.
+ // Therefore check if there is actually bytes available before changing the channel state.
+ m_channel->state = QHttpNetworkConnectionChannel::ReadingState;
+ }
if (m_reply)
_q_receiveReply();
}
--
1.9.1
@@ -1,33 +0,0 @@
From 63cf5d3d26a6f65938c3cdec1734eac9faaaf8cb Mon Sep 17 00:00:00 2001
From: Markus Goetz <markus@woboq.com>
Date: Tue, 22 Sep 2015 14:26:24 -0400
Subject: [PATCH] QNAM: Assign proper channel before sslErrors() emission
There can be a race condition where another channel connects
and gets the sslErrors() from the socket first. Then the
QSslConfiguration from the wrong socket (the default
channel 0's socket) was used.
Task-number: QTBUG-18722
Change-Id: Ibbfa48c27f181563745daf540fa792a57cc09682
Reviewed-by: Richard J. Moore <rich@kde.org>
---
src/network/access/qhttpnetworkconnectionchannel.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 257aa13..477cba2 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -1066,6 +1066,8 @@ void QHttpNetworkConnectionChannel::_q_sslErrors(const QList<QSslError> &errors)
connection->d_func()->pauseConnection();
if (pendingEncrypt && !reply)
connection->d_func()->dequeueRequest(socket);
+ if (reply) // a reply was actually dequeued.
+ reply->d_func()->connectionChannel = this; // set correct channel like in sendRequest() and queueRequest();
if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP) {
if (reply)
emit reply->sslErrors(errors);
--
1.9.1
@@ -1,121 +0,0 @@
From 0df5d079290b4c3b13e58e9397fabdc1dfdba96b Mon Sep 17 00:00:00 2001
From: Ulf Hermann <ulf.hermann@theqtcompany.com>
Date: Fri, 25 Sep 2015 13:23:46 +0200
Subject: [PATCH] Don't let closed http sockets pass as valid connections
A QAbstractSocket can be close()'d at any time, independently of its
current connection state. being closed means that we cannot use it to
read or write data, but internally it might still have some data to
send or receive, for example to an http server. We can even get a
connected() signal after close()'ing the socket.
We need to catch this condition and mark any pending data not yet
written to the socket for resending.
Task-number: QTBUG-48326
Change-Id: I6f61c35f2c567f2a138f8cfe9ade7fd1ec039be6
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
---
.../access/qhttpnetworkconnectionchannel.cpp | 7 ++-
.../tst_qhttpnetworkconnection.cpp | 54 ++++++++++++++++++++++
2 files changed, 60 insertions(+), 1 deletion(-)
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 293909c..b4eda34 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -272,7 +272,12 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
QAbstractSocket::SocketState socketState = socket->state();
// resend this request after we receive the disconnected signal
- if (socketState == QAbstractSocket::ClosingState) {
+ // If !socket->isOpen() then we have already called close() on the socket, but there was still a
+ // pending connectToHost() for which we hadn't seen a connected() signal, yet. The connected()
+ // has now arrived (as indicated by socketState != ClosingState), but we cannot send anything on
+ // such a socket anymore.
+ if (socketState == QAbstractSocket::ClosingState ||
+ (socketState != QAbstractSocket::UnconnectedState && !socket->isOpen())) {
if (reply)
resendCurrent = true;
return false;
diff --git a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
index 5d072af..0d188a8 100644
--- a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
+++ b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
@@ -36,6 +36,7 @@
#include "private/qhttpnetworkconnection_p.h"
#include "private/qnoncontiguousbytedevice_p.h"
#include <QAuthenticator>
+#include <QTcpServer>
#include "../../../network-settings.h"
@@ -106,6 +107,8 @@ private Q_SLOTS:
void getAndThenDeleteObject();
void getAndThenDeleteObject_data();
+
+ void overlappingCloseAndWrite();
};
tst_QHttpNetworkConnection::tst_QHttpNetworkConnection()
@@ -1112,6 +1115,57 @@ void tst_QHttpNetworkConnection::getAndThenDeleteObject()
}
}
+class TestTcpServer : public QTcpServer
+{
+ Q_OBJECT
+public:
+ TestTcpServer() : errorCodeReports(0)
+ {
+ connect(this, &QTcpServer::newConnection, this, &TestTcpServer::onNewConnection);
+ QVERIFY(listen(QHostAddress::LocalHost));
+ }
+
+ int errorCodeReports;
+
+public slots:
+ void onNewConnection()
+ {
+ QTcpSocket *socket = nextPendingConnection();
+ if (!socket)
+ return;
+ // close socket instantly!
+ connect(socket, &QTcpSocket::readyRead, socket, &QTcpSocket::close);
+ }
+
+ void onReply(QNetworkReply::NetworkError code)
+ {
+ QCOMPARE(code, QNetworkReply::RemoteHostClosedError);
+ ++errorCodeReports;
+ }
+};
+
+void tst_QHttpNetworkConnection::overlappingCloseAndWrite()
+{
+ // server accepts connections, but closes the socket instantly
+ TestTcpServer server;
+ QNetworkAccessManager accessManager;
+
+ // ten requests are scheduled. All should result in an RemoteHostClosed...
+ QUrl url;
+ url.setScheme(QStringLiteral("http"));
+ url.setHost(server.serverAddress().toString());
+ url.setPort(server.serverPort());
+ for (int i = 0; i < 10; ++i) {
+ QNetworkRequest request(url);
+ QNetworkReply *reply = accessManager.get(request);
+ // Not using Qt5 connection syntax here because of overly baroque syntax to discern between
+ // different error() methods.
+ QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
+ &server, SLOT(onReply(QNetworkReply::NetworkError)));
+ }
+
+ QTRY_COMPARE(server.errorCodeReports, 10);
+}
QTEST_MAIN(tst_QHttpNetworkConnection)
--
1.9.1
@@ -1,113 +0,0 @@
From c056e63cea1915667997c982f48296ce5acdcc80 Mon Sep 17 00:00:00 2001
From: Lorn Potter <lorn.potter@gmail.com>
Date: Tue, 2 Jun 2015 13:22:23 +1000
Subject: [PATCH] Make sure to report correct NetworkAccessibility
Task-number: QTBUG-46323
Change-Id: Ibdeb3280091a97d785d4314340678a63e88fb219
Reviewed-by: Markus Goetz (Woboq GmbH) <markus@woboq.com>
Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
---
src/network/access/qnetworkaccessmanager.cpp | 25 +++++++++++++++++--------
src/network/access/qnetworkaccessmanager_p.h | 2 ++
2 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index e878feb..84931cb 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -472,11 +472,11 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent)
// the QNetworkSession's signals
connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)),
SLOT(_q_onlineStateChanged(bool)));
- // we would need all active configurations to check for
- // d->networkConfigurationManager.isOnline(), which is asynchronous
- // and potentially expensive. We can just check the configuration here
- d->online = (d->networkConfiguration.state() & QNetworkConfiguration::Active);
}
+ // we would need all active configurations to check for
+ // d->networkConfigurationManager.isOnline(), which is asynchronous
+ // and potentially expensive. We can just check the configuration here
+ d->online = (d->networkConfiguration.state() & QNetworkConfiguration::Active);
#endif
}
@@ -946,6 +946,7 @@ QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const
void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkAccessibility accessible)
{
Q_D(QNetworkAccessManager);
+ d->defaultAccessControl = false;
if (d->networkAccessible != accessible) {
NetworkAccessibility previous = networkAccessible();
@@ -964,7 +965,6 @@ void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkA
QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccessible() const
{
Q_D(const QNetworkAccessManager);
-
if (d->networkSessionRequired) {
QSharedPointer<QNetworkSession> networkSession(d->getNetworkSession());
if (networkSession) {
@@ -975,7 +975,13 @@ QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccess
return NotAccessible;
} else {
// Network accessibility is either disabled or unknown.
- return (d->networkAccessible == NotAccessible) ? NotAccessible : UnknownAccessibility;
+ if (d->defaultAccessControl) {
+ if (d->online)
+ return d->networkAccessible;
+ else
+ return NotAccessible;
+ }
+ return (d->networkAccessible);
}
} else {
if (d->online)
@@ -1568,7 +1574,7 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co
if (!networkSessionStrongRef) {
online = false;
- if (networkAccessible == QNetworkAccessManager::NotAccessible)
+ if (networkAccessible == QNetworkAccessManager::NotAccessible || !online)
emit q->networkAccessibleChanged(QNetworkAccessManager::NotAccessible);
else
emit q->networkAccessibleChanged(QNetworkAccessManager::UnknownAccessibility);
@@ -1616,11 +1622,14 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession
if (online) {
if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) {
online = false;
- emit q->networkAccessibleChanged(QNetworkAccessManager::NotAccessible);
+ networkAccessible = QNetworkAccessManager::NotAccessible;
+ emit q->networkAccessibleChanged(networkAccessible);
}
} else {
if (state == QNetworkSession::Connected || state == QNetworkSession::Roaming) {
online = true;
+ if (defaultAccessControl)
+ networkAccessible = QNetworkAccessManager::Accessible;
emit q->networkAccessibleChanged(networkAccessible);
}
}
diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h
index f513324..c715da0 100644
--- a/src/network/access/qnetworkaccessmanager_p.h
+++ b/src/network/access/qnetworkaccessmanager_p.h
@@ -84,6 +84,7 @@ public:
initializeSession(true),
#endif
cookieJarCreated(false),
+ defaultAccessControl(true),
authenticationManager(QSharedPointer<QNetworkAccessAuthenticationManager>::create())
{ }
~QNetworkAccessManagerPrivate();
@@ -164,6 +165,7 @@ public:
#endif
bool cookieJarCreated;
+ bool defaultAccessControl;
// The cache with authorization data:
QSharedPointer<QNetworkAccessAuthenticationManager> authenticationManager;
--
1.9.1
@@ -1,233 +0,0 @@
From bb281eea179d50a413f4ec1ff172d27ee48d3a41 Mon Sep 17 00:00:00 2001
From: Lorn Potter <lorn.potter@gmail.com>
Date: Fri, 17 Jul 2015 15:32:23 +1000
Subject: [PATCH] Make sure networkAccessibilityChanged is emitted
Task-number: QTBUG-46323
Change-Id: I8297072b62763136f457ca6ae15282d1c22244f4
Reviewed-by: Timo Jyrinki <timo.jyrinki@canonical.com>
Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
---
src/network/access/qnetworkaccessmanager.cpp | 70 +++++++++++++++-------
src/network/access/qnetworkaccessmanager_p.h | 14 ++++-
.../tst_qnetworkaccessmanager.cpp | 31 +++++-----
3 files changed, 77 insertions(+), 38 deletions(-)
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 84931cb..f9e9513 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -278,7 +278,8 @@ static void ensureInitialized()
\snippet code/src_network_access_qnetworkaccessmanager.cpp 4
- Network requests can be reenabled again by calling
+ Network requests can be re-enabled again, and this property will resume to
+ reflect the actual device state by calling
\snippet code/src_network_access_qnetworkaccessmanager.cpp 5
@@ -467,16 +468,12 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent)
qRegisterMetaType<QSharedPointer<char> >();
#ifndef QT_NO_BEARERMANAGEMENT
- if (!d->networkSessionRequired) {
- // if a session is required, we track online state through
- // the QNetworkSession's signals
- connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)),
- SLOT(_q_onlineStateChanged(bool)));
- }
- // we would need all active configurations to check for
- // d->networkConfigurationManager.isOnline(), which is asynchronous
- // and potentially expensive. We can just check the configuration here
- d->online = (d->networkConfiguration.state() & QNetworkConfiguration::Active);
+ // if a session is required, we track online state through
+ // the QNetworkSession's signals if a request is already made.
+ // we need to track current accessibility state by default
+ //
+ connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)),
+ SLOT(_q_onlineStateChanged(bool)));
#endif
}
@@ -946,7 +943,8 @@ QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const
void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkAccessibility accessible)
{
Q_D(QNetworkAccessManager);
- d->defaultAccessControl = false;
+
+ d->defaultAccessControl = accessible == NotAccessible ? false : true;
if (d->networkAccessible != accessible) {
NetworkAccessibility previous = networkAccessible();
@@ -965,6 +963,10 @@ void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkA
QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccessible() const
{
Q_D(const QNetworkAccessManager);
+
+ if (d->networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined))
+ return UnknownAccessibility;
+
if (d->networkSessionRequired) {
QSharedPointer<QNetworkSession> networkSession(d->getNetworkSession());
if (networkSession) {
@@ -1622,32 +1624,56 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession
if (online) {
if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) {
online = false;
- networkAccessible = QNetworkAccessManager::NotAccessible;
- emit q->networkAccessibleChanged(networkAccessible);
+ if (networkAccessible != QNetworkAccessManager::NotAccessible) {
+ networkAccessible = QNetworkAccessManager::NotAccessible;
+ emit q->networkAccessibleChanged(networkAccessible);
+ }
}
} else {
if (state == QNetworkSession::Connected || state == QNetworkSession::Roaming) {
online = true;
if (defaultAccessControl)
- networkAccessible = QNetworkAccessManager::Accessible;
- emit q->networkAccessibleChanged(networkAccessible);
+ if (networkAccessible != QNetworkAccessManager::Accessible) {
+ networkAccessible = QNetworkAccessManager::Accessible;
+ emit q->networkAccessibleChanged(networkAccessible);
+ }
}
}
}
void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline)
{
- // if the user set a config, we only care whether this one is active.
+ Q_Q(QNetworkAccessManager);
+ // if the user set a config, we only care whether this one is active.
// Otherwise, this QNAM is online if there is an online config.
if (customNetworkConfiguration) {
online = (networkConfiguration.state() & QNetworkConfiguration::Active);
} else {
- if (isOnline && online != isOnline) {
- networkSessionStrongRef.clear();
- networkSessionWeakRef.clear();
+ if (online != isOnline) {
+ if (isOnline) {
+ networkSessionStrongRef.clear();
+ networkSessionWeakRef.clear();
+ }
+ online = isOnline;
+ }
+ }
+ if (online) {
+ if (defaultAccessControl) {
+ if (networkAccessible != QNetworkAccessManager::Accessible) {
+ networkAccessible = QNetworkAccessManager::Accessible;
+ emit q->networkAccessibleChanged(networkAccessible);
+ }
+ }
+ } else if (networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined)) {
+ if (networkAccessible != QNetworkAccessManager::UnknownAccessibility) {
+ networkAccessible = QNetworkAccessManager::UnknownAccessibility;
+ emit q->networkAccessibleChanged(networkAccessible);
+ }
+ } else {
+ if (networkAccessible != QNetworkAccessManager::NotAccessible) {
+ networkAccessible = QNetworkAccessManager::NotAccessible;
+ emit q->networkAccessibleChanged(networkAccessible);
}
-
- online = isOnline;
}
}
diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h
index c715da0..54ae114 100644
--- a/src/network/access/qnetworkaccessmanager_p.h
+++ b/src/network/access/qnetworkaccessmanager_p.h
@@ -78,7 +78,6 @@ public:
customNetworkConfiguration(false),
networkSessionRequired(networkConfigurationManager.capabilities()
& QNetworkConfigurationManager::NetworkSessionRequired),
- networkAccessible(QNetworkAccessManager::Accessible),
activeReplyCount(0),
online(false),
initializeSession(true),
@@ -86,7 +85,18 @@ public:
cookieJarCreated(false),
defaultAccessControl(true),
authenticationManager(QSharedPointer<QNetworkAccessAuthenticationManager>::create())
- { }
+ {
+#ifndef QT_NO_BEARERMANAGEMENT
+ // we would need all active configurations to check for
+ // d->networkConfigurationManager.isOnline(), which is asynchronous
+ // and potentially expensive. We can just check the configuration here
+ online = (networkConfiguration.state().testFlag(QNetworkConfiguration::Active));
+ if (online)
+ networkAccessible = QNetworkAccessManager::Accessible;
+ else
+ networkAccessible = QNetworkAccessManager::NotAccessible;
+#endif
+ }
~QNetworkAccessManagerPrivate();
void _q_replyFinished();
diff --git a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp
index b4e4b9c..8ecb57d 100644
--- a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp
+++ b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp
@@ -74,6 +74,10 @@ void tst_QNetworkAccessManager::networkAccessible()
// if there is no session, we cannot know in which state we are in
QNetworkAccessManager::NetworkAccessibility initialAccessibility =
manager.networkAccessible();
+
+ if (initialAccessibility == QNetworkAccessManager::UnknownAccessibility)
+ QSKIP("Unknown accessibility", SkipAll);
+
QCOMPARE(manager.networkAccessible(), initialAccessibility);
manager.setNetworkAccessible(QNetworkAccessManager::NotAccessible);
@@ -94,29 +98,28 @@ void tst_QNetworkAccessManager::networkAccessible()
QCOMPARE(manager.networkAccessible(), initialAccessibility);
QNetworkConfigurationManager configManager;
- bool sessionRequired = (configManager.capabilities()
- & QNetworkConfigurationManager::NetworkSessionRequired);
QNetworkConfiguration defaultConfig = configManager.defaultConfiguration();
if (defaultConfig.isValid()) {
manager.setConfiguration(defaultConfig);
- // the accessibility has not changed if no session is required
- if (sessionRequired) {
+ QCOMPARE(spy.count(), 0);
+
+ if (defaultConfig.state().testFlag(QNetworkConfiguration::Active))
+ QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::Accessible);
+ else
+ QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::NotAccessible);
+
+ manager.setNetworkAccessible(QNetworkAccessManager::NotAccessible);
+
+ if (defaultConfig.state().testFlag(QNetworkConfiguration::Active)) {
QCOMPARE(spy.count(), 1);
- QCOMPARE(spy.takeFirst().at(0).value<QNetworkAccessManager::NetworkAccessibility>(),
- QNetworkAccessManager::Accessible);
+ QCOMPARE(QNetworkAccessManager::NetworkAccessibility(spy.takeFirst().at(0).toInt()),
+ QNetworkAccessManager::NotAccessible);
} else {
QCOMPARE(spy.count(), 0);
}
- QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::Accessible);
-
- manager.setNetworkAccessible(QNetworkAccessManager::NotAccessible);
-
- QCOMPARE(spy.count(), 1);
- QCOMPARE(QNetworkAccessManager::NetworkAccessibility(spy.takeFirst().at(0).toInt()),
- QNetworkAccessManager::NotAccessible);
- QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::NotAccessible);
}
+ QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::NotAccessible);
#endif
}
--
1.9.1
@@ -1,52 +0,0 @@
From e996d68f6130847637ba287518cff1289cfa48e5 Mon Sep 17 00:00:00 2001
From: Lorn Potter <lorn.potter@gmail.com>
Date: Fri, 6 Nov 2015 14:22:44 +1000
Subject: [PATCH] Make UnknownAccessibility not block requests
This allows requests to proceed without needing bearer plugins.
Task-number: QTBUG-49267
Change-Id: Ie5ce188ddefebd14d666bb5846e8f93ee2925ed1
Reviewed-by: Markus Goetz (Woboq GmbH) <markus@woboq.com>
---
src/network/access/qnetworkaccessmanager.cpp | 3 +--
src/network/access/qnetworkaccessmanager_p.h | 2 ++
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 086140f..0e5870a 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -976,7 +976,6 @@ QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccess
else
return NotAccessible;
} else {
- // Network accessibility is either disabled or unknown.
if (d->defaultAccessControl) {
if (d->online)
return d->networkAccessible;
@@ -1161,7 +1160,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
#ifndef QT_NO_BEARERMANAGEMENT
// Return a disabled network reply if network access is disabled.
// Except if the scheme is empty or file://.
- if (!d->networkAccessible && !isLocalFile) {
+ if (d->networkAccessible == NotAccessible && !isLocalFile) {
return new QDisabledNetworkReply(this, req, op);
}
diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h
index 54ae114..3fc33b5 100644
--- a/src/network/access/qnetworkaccessmanager_p.h
+++ b/src/network/access/qnetworkaccessmanager_p.h
@@ -93,6 +93,8 @@ public:
online = (networkConfiguration.state().testFlag(QNetworkConfiguration::Active));
if (online)
networkAccessible = QNetworkAccessManager::Accessible;
+ else if (networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined))
+ networkAccessible = QNetworkAccessManager::UnknownAccessibility;
else
networkAccessible = QNetworkAccessManager::NotAccessible;
#endif
--
1.9.1
@@ -1,152 +0,0 @@
From ae9d3f4c6c1a732788cd1f24c6a928cee16c3991 Mon Sep 17 00:00:00 2001
From: Daniel Molkentin <daniel@molkentin.de>
Date: Tue, 27 Jan 2015 16:58:32 +0100
Subject: [PATCH] Win32: Re-init system proxy if internet settings change
Because Proxy Auto Configuration performs DNS lookups,
the proxy settings are being cached. For long-running
programs this means that once users switch e.g. from or
to company networks with a proxy, they instantly will
lose connectivity because we cache the old setting.
To remedy this, we monitor the Registry (locations
courtesy of Chromium's platform support) for changes
in its settings, and requery for the current proxy in
that case.
Task-number: QTBUG-3470
Task-number: QTBUG-29990
Change-Id: Id25a51387bcd232c5f879cea0371038986d0e2de
Reviewed-by: Oliver Wolff <oliver.wolff@theqtcompany.com>
---
src/network/kernel/qnetworkproxy_win.cpp | 86 +++++++++++++++++++++++++++++++-
1 file changed, 84 insertions(+), 2 deletions(-)
diff --git a/src/network/kernel/qnetworkproxy_win.cpp b/src/network/kernel/qnetworkproxy_win.cpp
index da2c020..f7741ce 100644
--- a/src/network/kernel/qnetworkproxy_win.cpp
+++ b/src/network/kernel/qnetworkproxy_win.cpp
@@ -345,12 +345,66 @@ static QList<QNetworkProxy> parseServerList(const QNetworkProxyQuery &query, con
return removeDuplicateProxies(result);
}
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+namespace {
+class QRegistryWatcher {
+public:
+ void addLocation(HKEY hive, const QString& path)
+ {
+ HKEY openedKey;
+ if (RegOpenKeyEx(hive, reinterpret_cast<const wchar_t*>(path.utf16()), 0, KEY_READ, &openedKey) != ERROR_SUCCESS)
+ return;
+
+ const DWORD filter = REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES |
+ REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_SECURITY;
+
+ // Watch the registry key for a change of value.
+ HANDLE handle = CreateEvent(NULL, true, false, NULL);
+ if (RegNotifyChangeKeyValue(openedKey, true, filter, handle, true) != ERROR_SUCCESS) {
+ CloseHandle(handle);
+ return;
+ }
+ m_watchEvents.append(handle);
+ m_registryHandles.append(openedKey);
+ }
+
+ bool hasChanged() const {
+ return !isEmpty() &&
+ WaitForMultipleObjects(m_watchEvents.size(), m_watchEvents.data(), false, 0) < WAIT_OBJECT_0 + m_watchEvents.size();
+ }
+
+ bool isEmpty() const {
+ return m_watchEvents.isEmpty();
+ }
+
+ void clear() {
+ foreach (HANDLE event, m_watchEvents)
+ CloseHandle(event);
+ foreach (HKEY key, m_registryHandles)
+ RegCloseKey(key);
+
+ m_watchEvents.clear();
+ m_registryHandles.clear();
+ }
+
+ ~QRegistryWatcher() {
+ clear();
+ }
+
+private:
+ QVector<HANDLE> m_watchEvents;
+ QVector<HKEY> m_registryHandles;
+};
+} // namespace
+#endif // !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+
class QWindowsSystemProxy
{
public:
QWindowsSystemProxy();
~QWindowsSystemProxy();
void init();
+ void reset();
QMutex mutex;
@@ -361,7 +415,9 @@ public:
QStringList proxyServerList;
QStringList proxyBypass;
QList<QNetworkProxy> defaultResult;
-
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+ QRegistryWatcher proxySettingsWatcher;
+#endif
bool initialized;
bool functional;
bool isAutoConfig;
@@ -381,16 +437,42 @@ QWindowsSystemProxy::~QWindowsSystemProxy()
ptrWinHttpCloseHandle(hHttpSession);
}
+void QWindowsSystemProxy::reset()
+{
+ autoConfigUrl.clear();
+ proxyServerList.clear();
+ proxyBypass.clear();
+ defaultResult.clear();
+ defaultResult << QNetworkProxy::NoProxy;
+ functional = false;
+ isAutoConfig = false;
+}
+
void QWindowsSystemProxy::init()
{
- if (initialized)
+ bool proxySettingsChanged = false;
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+ proxySettingsChanged = proxySettingsWatcher.hasChanged();
+#endif
+
+ if (initialized && !proxySettingsChanged)
return;
initialized = true;
+ reset();
+
#ifdef Q_OS_WINCE
// Windows CE does not have any of the following API
return;
#else
+
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+ proxySettingsWatcher.clear(); // needs reset to trigger a new detection
+ proxySettingsWatcher.addLocation(HKEY_CURRENT_USER, QStringLiteral("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"));
+ proxySettingsWatcher.addLocation(HKEY_LOCAL_MACHINE, QStringLiteral("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"));
+ proxySettingsWatcher.addLocation(HKEY_LOCAL_MACHINE, QStringLiteral("Software\\Policies\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"));
+#endif
+
// load the winhttp.dll library
QSystemLibrary lib(L"winhttp");
if (!lib.load())
--
1.9.1
@@ -1,32 +0,0 @@
From c1a67e7dc3a6f8876efa32cdbabbfde1c5a37bc6 Mon Sep 17 00:00:00 2001
From: Daniel Molkentin <daniel@molkentin.de>
Date: Tue, 31 Mar 2015 17:43:44 +0200
Subject: [PATCH] Windows: Do not crash if SSL context is gone after root cert
lookup
On Windows, we perform an extra certificate lookup for root CAs that
are not in Windows' (minimal) root store. This check can take up to
15 seconds. The SSL context can already be gone once we return. Hence
we now check for a non-null SSL context on Windows before proceeding.
Change-Id: I1951569d9b17da33fa604f7c9d8b33255acf200d
Reviewed-by: Richard J. Moore <rich@kde.org>
---
src/network/ssl/qsslsocket_openssl.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 0e1a3e5..b132aec 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -1281,7 +1281,7 @@ void QSslSocketBackendPrivate::_q_caRootLoaded(QSslCertificate cert, QSslCertifi
if (plainSocket)
plainSocket->resume();
paused = false;
- if (checkSslErrors())
+ if (checkSslErrors() && ssl)
continueHandshake();
}
--
1.9.1
@@ -1,39 +0,0 @@
From cf6881c03d9f08c6ace83defe461423bb87f30d8 Mon Sep 17 00:00:00 2001
From: =?utf8?q?Tor=20Arne=20Vestb=C3=B8?= <tor.arne.vestbo@theqtcompany.com>
Date: Fri, 15 Jan 2016 14:15:51 +0100
Subject: [PATCH] OS X: Ensure system tray icon is prepared even when menu bar
is hidden
On OS X 10.11 (El Capitan) the system menu bar can be automatically
hidden, in which case the menu bar height is reported to be 0 when
using the menuBarHeight API.
This resulted in failing to prepare an image for the system tray
icon item, making the tray item "invisible".
Instead we now use the [[NSStatusBar systemStatusBar] thickness]
API, which returns the correct height regardless of the menu bar
being hidden or not.
Task-number: QTBUG-48960
Change-Id: I208fb8df13754964a6f254cadfbff06dd56c6bab
---
src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
index a3ffb5b..8152c57 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
@@ -198,7 +198,7 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
// current OS X versions is 22 points. Provide some future-proofing
// by deriving the icon height from the menu height.
const int padding = 4;
- const int menuHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
+ const int menuHeight = [[NSStatusBar systemStatusBar] thickness];
const int maxImageHeight = menuHeight - padding;
// Select pixmap based on the device pixel height. Ideally we would use
--
2.6.2.2.g1b5ffa3
+11 -46
Ver Arquivo
@@ -1,55 +1,20 @@
## Patches used
There are our patches on top of Qt 5.4.0, which we are currently
using for our binary packages on Windows and Mac OS X. Most of them
There are our patches on top of Qt 5.6.2, which we are currently
using for our binary packages on Windows and macOS. Most of them
have been sent upstream and are part of newer Qt releases.
All changes are designed to up upstream, and all those that are
All changes are designed to be upstream, and all those that are
special hacks to Qt will bear a NOUPSTREAM in their name
The git-style numeration is ordered by order of creation, their
purpose is outlined in each patches' front matter.
You can apply those patches on a git clone using:
### Part of Qt v5.4.1 and later
* 0001-Fix-crash-on-Mac-OS-if-PAC-URL-contains-non-URL-lega.patch
* 0002-Fix-possible-crash-when-passing-an-invalid-PAC-URL.patch
* 0003-Fix-crash-if-PAC-script-retrieval-returns-a-null-CFD.patch
### Part of Qt v5.4.2 and later
* 0004-Cocoa-Fix-systray-SVG-icons.patch
* 0005-OSX-Fix-disapearing-tray-icon.patch
* 0007-QNAM-Fix-upload-corruptions-when-server-closes-conne.patch
* 0018-Windows-Do-not-crash-if-SSL-context-is-gone-after-ro.patch
### Part of Qt v5.5.0 and later
* 0017-Win32-Re-init-system-proxy-if-internet-settings-chan.patch
### Part of Qt v5.5.1 and later
* 0007-X-Network-Fix-up-previous-corruption-patch.patch
* 0008-QNAM-Fix-reply-deadlocks-on-server-closing-connectio.patch
* 0014-Fix-SNI-for-TlsV1_0OrLater-TlsV1_1OrLater-and-TlsV1_.patch
* 0016-Fix-possible-crash-when-passing-an-invalid-PAC-URL.patch
* 0011-Make-sure-to-report-correct-NetworkAccessibility.patch
### Part of Qt v5.5.2 (UNRELEASED!)
* 0009-QNAM-Assign-proper-channel-before-sslErrors-emission.patch
* 0010-Don-t-let-closed-http-sockets-pass-as-valid-connecti.patch
* 0012-Make-sure-networkAccessibilityChanged-is-emitted.patch
### Part of Qt v5.6 and later
* 0009-QNAM-Assign-proper-channel-before-sslErrors-emission.patch
* 0010-Don-t-let-closed-http-sockets-pass-as-valid-connecti.patch
* 0011-Make-sure-to-report-correct-NetworkAccessibility.patch
* 0012-Make-sure-networkAccessibilityChanged-is-emitted.patch
* 0013-Make-UnknownAccessibility-not-block-requests.patch
* 0019-Ensure-system-tray-icon-is-prepared-even-when-menu-bar.patch
### Part of Qt 5.7 and later
* 0015-Remove-legacy-platform-code-in-QSslSocket-for-OS-X-1.patch
### Not submitted upstream to be part of any release:
* 0006-Fix-force-debug-info-with-macx-clang_NOUPSTREAM.patch
This is only needed if you intent to harvest debugging symbols
for breakpad.
```
git am <client>/admin/qt/patches/qtbase/*.patch
```
You can update them using:
```
git format-patch -N --no-signature -o <client>/admin/qt/patches/qtbase/ <v5.x.y>
```
@@ -1,30 +1,27 @@
From f3cd07c11e0b7327ffc629f48a89c8c457cdba75 Mon Sep 17 00:00:00 2001
From 96c34ce85136cbdc16ef83effa8a13137f7ae4c5 Mon Sep 17 00:00:00 2001
From: Jocelyn Turcotte <jturcotte@woboq.com>
Date: Fri, 6 Mar 2015 16:12:37 +0100
Subject: [PATCH] Fix -force-debug-info with macx-clang
Subject: [PATCH] [NOUPSTREAM] Fix -force-debug-info with macx-clang
---
mkspecs/common/clang.conf | 2 ++
1 file changed, 2 insertions(+)
diff --git a/mkspecs/common/clang.conf b/mkspecs/common/clang.conf
index 2c29bb8..110d380 100644
index e003b94..e9b3291 100644
--- a/mkspecs/common/clang.conf
+++ b/mkspecs/common/clang.conf
@@ -20,11 +20,13 @@ QMAKE_CFLAGS_ISYSTEM = -isystem
QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
@@ -21,11 +21,13 @@ QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_
QMAKE_CFLAGS_USE_PRECOMPILE = -Xclang -include-pch -Xclang ${QMAKE_PCH_OUTPUT}
QMAKE_CFLAGS_LTCG = -flto
QMAKE_CFLAGS_DISABLE_LTCG = -fno-lto
+QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO = $$QMAKE_CFLAGS_OPTIMIZE -g
QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG
QMAKE_CXXFLAGS_CXX11 = -std=c++11
QMAKE_CXXFLAGS_DISABLE_LTCG = $$QMAKE_CFLAGS_DISABLE_LTCG
+QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
QMAKE_LFLAGS_CXX11 =
QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG
--
2.2.0
QMAKE_CXXFLAGS_CXX11 = -std=c++11
QMAKE_CXXFLAGS_CXX14 = -std=c++1y
QMAKE_CXXFLAGS_CXX1Z = -std=c++1z
@@ -1,7 +1,7 @@
From 06818f6d1c602aa3c4f9356324866432d2dd0195 Mon Sep 17 00:00:00 2001
From e6bccb1f0d8ca59acb1ffdac74a823c06346e7f3 Mon Sep 17 00:00:00 2001
From: Daniel Molkentin <daniel@molkentin.de>
Date: Mon, 16 Nov 2015 15:02:37 +0100
Subject: [PATCH 1/2] Remove legacy platform code in QSslSocket for OS X < 10.5
Subject: [PATCH] Remove legacy platform code in QSslSocket for OS X < 10.5
This avoids manual symbol lookups and makes the code more readable.
Mark identical code.
@@ -16,20 +16,18 @@ Reviewed-by: Markus Goetz (Woboq GmbH) <markus@woboq.com>
Conflicts:
src/network/ssl/qsslsocket_openssl.cpp
---
src/network/ssl/qsslsocket_openssl.cpp | 83 +++++++++++-----------------------
src/network/ssl/qsslsocket_openssl.cpp | 81 +++++++++++-----------------------
src/network/ssl/qsslsocket_p.h | 6 +--
2 files changed, 28 insertions(+), 61 deletions(-)
2 files changed, 26 insertions(+), 61 deletions(-)
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 13fc534..7d0fe00 100644
index 82644c1..415f147 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -69,14 +69,19 @@
#include <QtCore/qvarlengtharray.h>
#include <QLibrary> // for loading the security lib for the CA store
@@ -76,14 +76,17 @@
#include <string.h>
+#include <string.h>
+
+#ifdef Q_OS_DARWIN
+# include <private/qcore_mac_p.h>
+#endif
@@ -50,7 +48,7 @@ index 13fc534..7d0fe00 100644
PtrCertOpenSystemStoreW QSslSocketPrivate::ptrCertOpenSystemStoreW = 0;
PtrCertFindCertificateInStore QSslSocketPrivate::ptrCertFindCertificateInStore = 0;
PtrCertCloseStore QSslSocketPrivate::ptrCertCloseStore = 0;
@@ -482,23 +487,7 @@ void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
@@ -509,23 +512,7 @@ void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
#ifndef QT_NO_LIBRARY
//load symbols needed to receive certificates from system store
@@ -59,23 +57,23 @@ index 13fc534..7d0fe00 100644
- if (securityLib.load()) {
- ptrSecCertificateCopyData = (PtrSecCertificateCopyData) securityLib.resolve("SecCertificateCopyData");
- if (!ptrSecCertificateCopyData)
- qWarning("could not resolve symbols in security library"); // should never happen
- qCWarning(lcSsl, "could not resolve symbols in security library"); // should never happen
-
- ptrSecTrustSettingsCopyCertificates = (PtrSecTrustSettingsCopyCertificates) securityLib.resolve("SecTrustSettingsCopyCertificates");
- if (!ptrSecTrustSettingsCopyCertificates) { // method was introduced in Leopard, use legacy method if it's not there
- ptrSecTrustCopyAnchorCertificates = (PtrSecTrustCopyAnchorCertificates) securityLib.resolve("SecTrustCopyAnchorCertificates");
- if (!ptrSecTrustCopyAnchorCertificates)
- qWarning("could not resolve symbols in security library"); // should never happen
- qCWarning(lcSsl, "could not resolve symbols in security library"); // should never happen
- }
- } else {
- qWarning("could not load security library");
- qCWarning(lcSsl, "could not load security library");
- }
-#elif defined(Q_OS_WIN)
+#if defined(Q_OS_WIN)
HINSTANCE hLib = LoadLibraryW(L"Crypt32");
if (hLib) {
#if defined(Q_OS_WINCE)
@@ -635,40 +624,22 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
@@ -693,40 +680,22 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
timer.start();
#endif
QList<QSslCertificate> systemCerts;
@@ -101,7 +99,7 @@ index 13fc534..7d0fe00 100644
- data = ptrSecCertificateCopyData(cfCert);
-
- if (data == NULL) {
- qWarning("error retrieving a CA certificate from the system store");
- qCWarning(lcSsl, "error retrieving a CA certificate from the system store");
- } else {
- QByteArray rawCert = QByteArray::fromRawData((const char *)CFDataGetBytePtr(data), CFDataGetLength(data));
- systemCerts.append(QSslCertificate::fromData(rawCert, QSsl::Der));
@@ -127,15 +125,15 @@ index 13fc534..7d0fe00 100644
- }
- else {
- // no detailed error handling here
- qWarning("could not retrieve system CA certificates");
- qCWarning(lcSsl, "could not retrieve system CA certificates");
}
}
#elif defined(Q_OS_WIN)
diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h
index 6e7a2c5..c1a6f05 100644
index d651971..17cc7b4 100644
--- a/src/network/ssl/qsslsocket_p.h
+++ b/src/network/ssl/qsslsocket_p.h
@@ -145,11 +145,7 @@ public:
@@ -151,11 +151,7 @@ public:
static bool isMatchingHostname(const QSslCertificate &cert, const QString &peerName);
Q_AUTOTEST_EXPORT static bool isMatchingHostname(const QString &cn, const QString &hostname);
@@ -148,6 +146,3 @@ index 6e7a2c5..c1a6f05 100644
static PtrCertOpenSystemStoreW ptrCertOpenSystemStoreW;
static PtrCertFindCertificateInStore ptrCertFindCertificateInStore;
static PtrCertCloseStore ptrCertCloseStore;
--
1.9.1
@@ -1,7 +1,7 @@
From 6b9366e7748857f14d5b0f92ced70c08ab5235b7 Mon Sep 17 00:00:00 2001
From 9d1120db0973ea7741b13a6555b20ae61f6d037e Mon Sep 17 00:00:00 2001
From: Daniel Molkentin <danimo@owncloud.com>
Date: Wed, 25 Nov 2015 12:37:27 +0100
Subject: [PATCH 2/2] QSslSocket: evaluate CAs in all keychain categories
Subject: [PATCH] QSslSocket: evaluate CAs in all keychain categories
This will make sure that certs in the domainUser (login),
and domainAdmin (per machine) keychain are being picked up
@@ -15,7 +15,7 @@ it will be accepted.
[ChangeLog][Platform Specific Changes] OS X now accepts trusted
certificates from the login and system keychains.
(Backport of fe3a84138e266c425f11353f7d8dc28a588af89e to Qt 5.4)
(Backport of fe3a84138e266c425f11353f7d8dc28a588af89e)
Task-number: QTBUG-32898
Change-Id: Ia23083d5af74388eeee31ba07239735cbbe64368
@@ -29,10 +29,10 @@ Reviewed-by: Markus Goetz (Woboq GmbH) <markus@woboq.com>
create mode 100644 src/network/ssl/qsslsocket_mac_shared.cpp
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 8887f47..6347c20 100644
index 549906a..7b202b0 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -1446,6 +1446,10 @@ QList<QSslCertificate> QSslSocket::defaultCaCertificates()
@@ -1508,6 +1508,10 @@ QList<QSslCertificate> QSslSocket::defaultCaCertificates()
returned by defaultCaCertificates(). You can replace that database
with your own with setDefaultCaCertificates().
@@ -198,10 +198,10 @@ index 0000000..60fea4c
+
+QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 7d0fe00..7415e32 100644
index 415f147..7a3cb42 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -71,14 +71,6 @@
@@ -76,14 +76,6 @@
#include <string.h>
@@ -216,15 +216,15 @@ index 7d0fe00..7415e32 100644
QT_BEGIN_NAMESPACE
#if defined(Q_OS_WIN)
@@ -616,6 +608,7 @@ void QSslSocketPrivate::resetDefaultCiphers()
setDefaultCiphers(defaultCiphers);
@@ -672,6 +664,7 @@ void QSslSocketPrivate::resetDefaultEllipticCurves()
setDefaultSupportedEllipticCurves(curves);
}
+#ifndef Q_OS_DARWIN // Apple implementation in qsslsocket_mac_shared.cpp
QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
{
ensureInitialized();
@@ -624,25 +617,7 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
@@ -680,25 +673,7 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
timer.start();
#endif
QList<QSslCertificate> systemCerts;
@@ -251,7 +251,7 @@ index 7d0fe00..7415e32 100644
if (ptrCertOpenSystemStoreW && ptrCertFindCertificateInStore && ptrCertCloseStore) {
HCERTSTORE hSystemStore;
#if defined(Q_OS_WINCE)
@@ -719,6 +694,7 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
@@ -775,6 +750,7 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
return systemCerts;
}
@@ -260,10 +260,10 @@ index 7d0fe00..7415e32 100644
void QSslSocketBackendPrivate::startClientEncryption()
{
diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri
index 384e149..9546f18 100644
index 29c47cd..8eb605b 100644
--- a/src/network/ssl/ssl.pri
+++ b/src/network/ssl/ssl.pri
@@ -45,7 +45,9 @@ contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) {
@@ -62,7 +62,9 @@ contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) {
ssl/qsslsocket_openssl.cpp \
ssl/qsslsocket_openssl_symbols.cpp
@@ -274,6 +274,3 @@ index 384e149..9546f18 100644
# Add optional SSL libs
# Static linking of OpenSSL with msvc:
--
1.9.1
+2 -2
Ver Arquivo
@@ -9,6 +9,7 @@ StrCpy $PageReinstall_NEW_Field_3 "No instal·lar"
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Ja instal·lat"
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Trieu la manera com voleu instal·lar ${APPLICATION_NAME}."
StrCpy $PageReinstall_OLD_Field_1 "Una versió més recent de ${APPLICATION_NAME} ja està instal.lada!! No es recomana instal.lar una versió més antiga. Si realment voleu instal.lar una versió més antiga, és millor primer desinstal.lar la versió actual. Seleccioni l'operació que desitjeu realitzar i feu clic a Següent per a continuar."
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} ja està instal·lat.$\n$\nSeleccioneu la operació que voleu fer i feu clic a Següent per continuar."
StrCpy $PageReinstall_SAME_Field_2 "Afegir/Reinstal.lar components"
StrCpy $PageReinstall_SAME_Field_3 "Desinstal.lar ${APPLICATION_NAME}"
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstal.lar ${APPLICATION_NAME}"
@@ -37,7 +38,6 @@ StrCpy $UAC_ERROR_ELEVATE "No es pot elevar, error:"
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Aquest instal·lador requereix accés d'administrador, intenteu-ho de nou"
StrCpy $INIT_INSTALLER_RUNNING "L'instal·lador ja s'està executant."
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Aquest desinstal·lador requereix accés d'administrador, intenteu-ho de nou."
StrCpy $UAC_ERROR_LOGON_SERVICE "El servei de inici de sessió no s'està executant, s'està abortant!"
StrCpy $INIT_UNINSTALLER_RUNNING "El desinstal·lador ja s'està executant."
StrCpy $SectionGroup_Shortcuts "Dreceres"
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.$\r$\nSelect the operation you want to perform and click Next to continue."
StrCpy $UAC_ERROR_LOGON_SERVICE "Logon service is not running, aborting!"
+1 -1
Ver Arquivo
@@ -1,5 +1,5 @@
# Auto-generated - do not modify
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Toon opmerkingen bij deze uitgave"
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Toon opmerkingen bij deze versie"
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Gevonden ${APPLICATION_EXECUTABLE} proces(sen) moet worden gestopt.$\nWilt u dat het installatieprogramma dat voor u doet?"
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Stoppen ${APPLICATION_EXECUTABLE} processen."
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Het te stoppen proces is niet gevonden!"
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Mostrar notas de lançamento"
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Encontrados ${APPLICATION_EXECUTABLE} processo(s) em execução que precisa(m) de ser interrompido(s).$\nDeseja que o instalador o(s) termine por si?"
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "A terminar os processos de ${APPLICATION_EXECUTABLE}."
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Não foi encontrado nenhum processo para terminar!"
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Não foi encontrado o processo para terminar!"
StrCpy $PageReinstall_NEW_Field_1 "Está instalada no sistema uma versão antiga de ${APPLICATION_NAME}. É recomendado que desinstale a versão atual antes de instalar a mais recente. Selecione a operação que deseja executar e clique em $\"Seguinte$\" para continuar."
StrCpy $PageReinstall_NEW_Field_2 "Desinstalar antes de instalar"
StrCpy $PageReinstall_NEW_Field_3 "Não desinstale"
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Mostrar las notas de la versión"
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "El/los proceso/s ${APPLICATION_EXECUTABLE} debe/n ser detenidos.$\n¿Quiere que el instalador lo haga por usted?"
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Deteniendo el/los proceso/s ${APPLICATION_EXECUTABLE}."
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "¡Proceso para finalizar no encontrado!"
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "¡Proceso a finalizar no encontrado!"
StrCpy $PageReinstall_NEW_Field_1 "Una versión anterior de ${APPLICATION_NAME} se encuentra instalada en el sistema. Se recomienda de instalar la versión actual antes de instalar la nueva. Seleccione la operacion deseada y haga click en Siguiente para continuar."
StrCpy $PageReinstall_NEW_Field_2 "Desinstalar antes de instalar"
StrCpy $PageReinstall_NEW_Field_3 "No desinstalar"
+1 -1
Submodule binary updated: 0d89ac7766...741b49156b
+1 -1
Ver Arquivo
@@ -32,7 +32,7 @@ find_library(CMOCKA_LIBRARY
NAMES
cmocka
PATHS
${CMOCKA_ROOT_DIR}/include
${CMOCKA_ROOT_DIR}/lib
)
if (CMOCKA_LIBRARY)
+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"
+17 -15
Ver Arquivo
@@ -2,21 +2,23 @@
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING* file.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
if(CMAKE_COMPILER_IS_GNUCXX)
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION)
if(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
else(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION)
if(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
else(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
endif(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
endif(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
endif(CMAKE_COMPILER_IS_GNUCXX)
endif()
if(DEFINED MIRALL_FATAL_WARNINGS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
endif(DEFINED MIRALL_FATAL_WARNINGS)
if(DEFINED MIRALL_FATAL_WARNINGS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
endif(DEFINED MIRALL_FATAL_WARNINGS)
endif()
+13
Ver Arquivo
@@ -81,6 +81,13 @@ set(csync_HDRS
# Statically include sqlite
if (USE_OUR_OWN_SQLITE3)
list(APPEND csync_SRCS ${SQLITE3_SOURCE})
if (WIN32)
# We want to export sqlite symbols from the ocsync DLL without
# having to patch both sqlite3.h and the amalgation sqlite3.c,
# so do the import/export magic manually through the build system.
remove_definitions(-DSQLITE_API=__declspec\(dllimport\))
add_definitions(-DSQLITE_API=__declspec\(dllexport\))
endif()
endif()
include_directories(
@@ -91,6 +98,12 @@ include_directories(
add_library(${CSYNC_LIBRARY} SHARED ${csync_SRCS})
#add_library(${CSYNC_LIBRARY}_static STATIC ${csync_SRCS})
generate_export_header( ${CSYNC_LIBRARY}
BASE_NAME ${CSYNC_LIBRARY}
EXPORT_MACRO_NAME OCSYNC_EXPORT
EXPORT_FILE_NAME ocsynclib.h
)
target_link_libraries(${CSYNC_LIBRARY} ${CSYNC_LINK_LIBRARIES})
#target_link_libraries(${CSYNC_LIBRARY}_static ${CSYNC_LINK_LIBRARIES})
+10 -23
Ver Arquivo
@@ -30,7 +30,6 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdbool.h>
@@ -90,7 +89,7 @@ static int _data_cmp(const void *key, const void *data) {
return 0;
}
void csync_create(CSYNC **csync, const char *local, const char *remote) {
void csync_create(CSYNC **csync, const char *local) {
CSYNC *ctx;
size_t len = 0;
@@ -104,12 +103,6 @@ void csync_create(CSYNC **csync, const char *local, const char *remote) {
ctx->local.uri = c_strndup(local, len);
/* remove trailing slashes */
len = strlen(remote);
while(len > 0 && remote[len - 1] == '/') --len;
ctx->remote.uri = c_strndup(remote, len);
ctx->status_code = CSYNC_STATUS_OK;
ctx->current_fs = NULL;
@@ -121,7 +114,7 @@ void csync_create(CSYNC **csync, const char *local, const char *remote) {
*csync = ctx;
}
void csync_init(CSYNC *ctx) {
void csync_init(CSYNC *ctx, const char *db_file) {
assert(ctx);
/* Do not initialize twice */
@@ -132,6 +125,9 @@ void csync_init(CSYNC *ctx) {
ctx->remote.type = REMOTE_REPLICA;
SAFE_FREE(ctx->statedb.file);
ctx->statedb.file = c_strdup(db_file);
c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp);
c_rbtree_create(&ctx->remote.tree, _key_cmp, _data_cmp);
@@ -153,19 +149,11 @@ int csync_update(CSYNC *ctx) {
}
ctx->status_code = CSYNC_STATUS_OK;
/* create/load statedb */
rc = asprintf(&ctx->statedb.file, "%s/.csync_journal.db",
ctx->local.uri);
if (rc < 0) {
ctx->status_code = CSYNC_STATUS_MEMORY_ERROR;
return rc;
}
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Journal: %s", ctx->statedb.file);
if (csync_statedb_load(ctx, ctx->statedb.file, &ctx->statedb.db) < 0) {
/* Path of database file is set in csync_init */
if (csync_statedb_load(ctx, ctx->statedb.file, &ctx->statedb.db) < 0) {
rc = -1;
return rc;
}
}
ctx->status_code = CSYNC_STATUS_OK;
@@ -200,7 +188,7 @@ int csync_update(CSYNC *ctx) {
ctx->current = REMOTE_REPLICA;
ctx->replica = ctx->remote.type;
rc = csync_ftw(ctx, ctx->remote.uri, csync_walker, MAX_DEPTH);
rc = csync_ftw(ctx, "", csync_walker, MAX_DEPTH);
if (rc < 0) {
if(ctx->status_code == CSYNC_STATUS_OK) {
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_UPDATE_ERROR);
@@ -522,7 +510,6 @@ static void _csync_clean_ctx(CSYNC *ctx)
c_rbtree_free(ctx->local.tree);
c_rbtree_free(ctx->remote.tree);
SAFE_FREE(ctx->statedb.file);
SAFE_FREE(ctx->remote.root_perms);
}
@@ -579,8 +566,8 @@ int csync_destroy(CSYNC *ctx) {
_csync_clean_ctx(ctx);
SAFE_FREE(ctx->statedb.file);
SAFE_FREE(ctx->local.uri);
SAFE_FREE(ctx->remote.uri);
SAFE_FREE(ctx->error_string);
#ifdef WITH_ICONV
+32 -37
Ver Arquivo
@@ -33,10 +33,10 @@
#define _CSYNC_H
#include "std/c_private.h"
#include "ocsynclib.h"
#include <sys/stat.h>
#include <stdbool.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <config_csync.h>
@@ -44,11 +44,6 @@
extern "C" {
#endif
struct csync_client_certs_s {
char *certificatePath;
char *certificatePasswd;
};
enum csync_status_codes_e {
CSYNC_STATUS_OK = 0,
@@ -229,14 +224,14 @@ struct csync_vio_file_stat_s {
char *original_name; // only set if locale conversion fails
};
csync_vio_file_stat_t *csync_vio_file_stat_new(void);
csync_vio_file_stat_t *csync_vio_file_stat_copy(csync_vio_file_stat_t *file_stat);
csync_vio_file_stat_t OCSYNC_EXPORT *csync_vio_file_stat_new(void);
csync_vio_file_stat_t OCSYNC_EXPORT *csync_vio_file_stat_copy(csync_vio_file_stat_t *file_stat);
void csync_vio_file_stat_destroy(csync_vio_file_stat_t *fstat);
void OCSYNC_EXPORT csync_vio_file_stat_destroy(csync_vio_file_stat_t *fstat);
void csync_vio_file_stat_set_file_id( csync_vio_file_stat_t* dst, const char* src );
void OCSYNC_EXPORT csync_vio_file_stat_set_file_id( csync_vio_file_stat_t* dst, const char* src );
void csync_vio_set_file_id(char* dst, const char *src );
void OCSYNC_EXPORT csync_vio_set_file_id(char* dst, const char *src );
/**
@@ -317,7 +312,7 @@ typedef const char* (*csync_checksum_hook) (
*
* @param csync The context variable to allocate.
*/
void csync_create(CSYNC **csync, const char *local, const char *remote);
void OCSYNC_EXPORT csync_create(CSYNC **csync, const char *local);
/**
* @brief Initialize the file synchronizer.
@@ -326,7 +321,7 @@ void csync_create(CSYNC **csync, const char *local, const char *remote);
*
* @param ctx The context to initialize.
*/
void csync_init(CSYNC *ctx);
void OCSYNC_EXPORT csync_init(CSYNC *ctx, const char *db_file);
/**
* @brief Update detection
@@ -335,7 +330,7 @@ void csync_init(CSYNC *ctx);
*
* @return 0 on success, less than 0 if an error occurred.
*/
int csync_update(CSYNC *ctx);
int OCSYNC_EXPORT csync_update(CSYNC *ctx);
/**
* @brief Reconciliation
@@ -344,7 +339,7 @@ int csync_update(CSYNC *ctx);
*
* @return 0 on success, less than 0 if an error occurred.
*/
int csync_reconcile(CSYNC *ctx);
int OCSYNC_EXPORT csync_reconcile(CSYNC *ctx);
/**
* @brief Re-initializes the csync context
@@ -353,7 +348,7 @@ int csync_reconcile(CSYNC *ctx);
*
* @return 0 on success, less than 0 if an error occurred.
*/
int csync_commit(CSYNC *ctx);
int OCSYNC_EXPORT csync_commit(CSYNC *ctx);
/**
* @brief Destroy the csync context
@@ -364,7 +359,7 @@ int csync_commit(CSYNC *ctx);
*
* @return 0 on success, less than 0 if an error occurred.
*/
int csync_destroy(CSYNC *ctx);
int OCSYNC_EXPORT csync_destroy(CSYNC *ctx);
/**
* @brief Get the userdata saved in the context.
@@ -386,7 +381,7 @@ void *csync_get_userdata(CSYNC *ctx);
*
* @return 0 on success, less than 0 if an error occurred.
*/
int csync_set_userdata(CSYNC *ctx, void *userdata);
int OCSYNC_EXPORT csync_set_userdata(CSYNC *ctx, void *userdata);
/**
* @brief Get the authentication callback set.
@@ -396,7 +391,7 @@ int csync_set_userdata(CSYNC *ctx, void *userdata);
* @return The authentication callback set or NULL if an error
* occurred.
*/
csync_auth_callback csync_get_auth_callback(CSYNC *ctx);
csync_auth_callback OCSYNC_EXPORT csync_get_auth_callback(CSYNC *ctx);
/**
* @brief Set the authentication callback.
@@ -407,7 +402,7 @@ csync_auth_callback csync_get_auth_callback(CSYNC *ctx);
*
* @return 0 on success, less than 0 if an error occurred.
*/
int csync_set_auth_callback(CSYNC *ctx, csync_auth_callback cb);
int OCSYNC_EXPORT csync_set_auth_callback(CSYNC *ctx, csync_auth_callback cb);
/**
* @brief Set the log level.
@@ -416,14 +411,14 @@ int csync_set_auth_callback(CSYNC *ctx, csync_auth_callback cb);
*
* @return 0 on success, < 0 if an error occurred.
*/
int csync_set_log_level(int level);
int OCSYNC_EXPORT csync_set_log_level(int level);
/**
* @brief Get the log verbosity
*
* @return The log verbosity, -1 on error.
*/
int csync_get_log_level(void);
int OCSYNC_EXPORT csync_get_log_level(void);
/**
* @brief Get the logging callback set.
@@ -431,7 +426,7 @@ int csync_get_log_level(void);
* @return The logging callback set or NULL if an error
* occurred.
*/
csync_log_callback csync_get_log_callback(void);
csync_log_callback OCSYNC_EXPORT csync_get_log_callback(void);
/**
* @brief Set the logging callback.
@@ -440,14 +435,14 @@ csync_log_callback csync_get_log_callback(void);
*
* @return 0 on success, less than 0 if an error occurred.
*/
int csync_set_log_callback(csync_log_callback cb);
int OCSYNC_EXPORT csync_set_log_callback(csync_log_callback cb);
/**
* @brief get the userdata set for the logging callback.
*
* @return The userdata or NULL.
*/
void *csync_get_log_userdata(void);
void OCSYNC_EXPORT *csync_get_log_userdata(void);
/**
* @brief Set the userdata passed to the logging callback.
@@ -456,13 +451,13 @@ void *csync_get_log_userdata(void);
*
* @return 0 on success, less than 0 if an error occurred.
*/
int csync_set_log_userdata(void *data);
int OCSYNC_EXPORT csync_set_log_userdata(void *data);
/* Used for special modes or debugging */
CSYNC_STATUS csync_get_status(CSYNC *ctx);
CSYNC_STATUS OCSYNC_EXPORT csync_get_status(CSYNC *ctx);
/* Used for special modes or debugging */
int csync_set_status(CSYNC *ctx, int status);
int OCSYNC_EXPORT csync_set_status(CSYNC *ctx, int status);
typedef int csync_treewalk_visit_func(TREE_WALK_FILE* ,void*);
@@ -475,7 +470,7 @@ typedef int csync_treewalk_visit_func(TREE_WALK_FILE* ,void*);
*
* @return 0 on success, less than 0 if an error occurred.
*/
int csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter);
int OCSYNC_EXPORT csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter);
/**
* @brief Walk the remote file tree and call a visitor function for each file.
@@ -486,7 +481,7 @@ int csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int fi
*
* @return 0 on success, less than 0 if an error occurred.
*/
int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter);
int OCSYNC_EXPORT csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter);
/**
* @brief Get the csync status string.
@@ -495,7 +490,7 @@ int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int f
*
* @return A const pointer to a string with more precise status info.
*/
const char *csync_get_status_string(CSYNC *ctx);
const char OCSYNC_EXPORT *csync_get_status_string(CSYNC *ctx);
#ifdef WITH_ICONV
/**
@@ -505,7 +500,7 @@ const char *csync_get_status_string(CSYNC *ctx);
*
* @return 0 on success, or an iconv error number.
*/
int csync_set_iconv_codec(const char *from);
int OCSYNC_EXPORT csync_set_iconv_codec(const char *from);
#endif
/**
@@ -513,24 +508,24 @@ int csync_set_iconv_codec(const char *from);
*
* @param ctx The csync context.
*/
void csync_request_abort(CSYNC *ctx);
void OCSYNC_EXPORT csync_request_abort(CSYNC *ctx);
/**
* @brief Clears the abort flag. Can be called from another thread.
*
* @param ctx The csync context.
*/
void csync_resume(CSYNC *ctx);
void OCSYNC_EXPORT csync_resume(CSYNC *ctx);
/**
* @brief Checks for the abort flag, to be used from the modules.
*
* @param ctx The csync context.
*/
int csync_abort_requested(CSYNC *ctx);
int OCSYNC_EXPORT csync_abort_requested(CSYNC *ctx);
char *csync_normalize_etag(const char *);
time_t oc_httpdate_parse( const char *date );
char OCSYNC_EXPORT *csync_normalize_etag(const char *);
time_t OCSYNC_EXPORT oc_httpdate_parse( const char *date );
#ifdef __cplusplus
}
+11 -1
Ver Arquivo
@@ -28,7 +28,6 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "c_lib.h"
#include "c_private.h"
@@ -37,6 +36,12 @@
#include "csync_exclude.h"
#include "csync_misc.h"
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
#define CSYNC_LOG_CATEGORY_NAME "csync.exclude"
#include "csync_log.h"
@@ -225,6 +230,11 @@ static CSYNC_EXCLUDE_TYPE _csync_excluded_common(c_strlist_t *excludes, const ch
}
blen = strlen(bname);
rc = csync_fnmatch("._sync_*.db*", bname, 0);
if (rc == 0) {
match = CSYNC_FILE_SILENTLY_EXCLUDED;
goto out;
}
rc = csync_fnmatch(".csync_journal.db*", bname, 0);
if (rc == 0) {
match = CSYNC_FILE_SILENTLY_EXCLUDED;
+5 -3
Ver Arquivo
@@ -21,6 +21,8 @@
#ifndef _CSYNC_EXCLUDE_H
#define _CSYNC_EXCLUDE_H
#include "ocsynclib.h"
enum csync_exclude_type_e {
CSYNC_NOT_EXCLUDED = 0,
CSYNC_FILE_SILENTLY_EXCLUDED,
@@ -35,7 +37,7 @@ enum csync_exclude_type_e {
typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE;
#ifdef WITH_UNIT_TESTING
int _csync_exclude_add(c_strlist_t **inList, const char *string);
int OCSYNC_EXPORT _csync_exclude_add(c_strlist_t **inList, const char *string);
#endif
/**
@@ -46,7 +48,7 @@ int _csync_exclude_add(c_strlist_t **inList, const char *string);
*
* @return 0 on success, -1 if an error occurred with errno set.
*/
int csync_exclude_load(const char *fname, c_strlist_t **list);
int OCSYNC_EXPORT csync_exclude_load(const char *fname, c_strlist_t **list);
/**
* @brief Check if the given path should be excluded in a traversal situation.
@@ -72,7 +74,7 @@ CSYNC_EXCLUDE_TYPE csync_excluded_traversal(c_strlist_t *excludes, const char *p
* @param filetype
* @return
*/
CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype);
CSYNC_EXCLUDE_TYPE OCSYNC_EXPORT csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype);
#endif /* _CSYNC_EXCLUDE_H */
/**
+1 -42
Ver Arquivo
@@ -23,12 +23,6 @@
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#ifndef _WIN32
#include <sys/time.h>
#else
#include <sys/utime.h>
#endif
#include <time.h>
#include "csync_private.h"
#include "csync_log.h"
@@ -37,46 +31,11 @@ CSYNC_THREAD int csync_log_level;
CSYNC_THREAD csync_log_callback csync_log_cb;
CSYNC_THREAD void *csync_log_userdata;
static int current_timestring(int hires, char *buf, size_t len)
{
char tbuf[64];
struct timeval tv;
struct tm *tm;
time_t t;
gettimeofday(&tv, NULL);
t = (time_t) tv.tv_sec;
tm = localtime(&t);
if (tm == NULL) {
return -1;
}
if (hires) {
strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm);
snprintf(buf, len, "%s.%06ld", tbuf, (long) tv.tv_usec);
} else {
strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm);
snprintf(buf, len, "%s", tbuf);
}
return 0;
}
static void csync_log_stderr(int verbosity,
const char *function,
const char *buffer)
{
char date[64] = {0};
int rc;
rc = current_timestring(1, date, sizeof(date));
if (rc == 0) {
fprintf(stderr, "[%s, %d] %s:", date+5, verbosity, function);
} else {
fprintf(stderr, "[%d] %s", verbosity, function);
}
fprintf(stderr, "[%d] %s", verbosity, function);
fprintf(stderr, " %s\n", buffer);
}
static void csync_log_function(int verbosity,
-1
Ver Arquivo
@@ -39,7 +39,6 @@
# include <shlobj.h>
#else /* _WIN32 */
# include <pwd.h>
# include <unistd.h>
#endif /* _WIN32 */
#include "c_lib.h"
+1 -1
Ver Arquivo
@@ -36,7 +36,7 @@
#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
#endif
int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags);
int csync_fnmatch(const char *pattern, const char *name, int flags);
/**
* @brief csync_errno_to_status - errno to csync status code
+1 -8
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;
@@ -103,9 +103,6 @@ struct csync_s {
} callbacks;
c_strlist_t *excludes;
// needed for SSL client certificate support
struct csync_client_certs_s *clientCerts;
struct {
char *file;
@@ -126,7 +123,6 @@ struct csync_s {
} local;
struct {
char *uri;
c_rbtree_t *tree;
enum csync_replica_e type;
int read_from_db;
@@ -224,9 +220,6 @@ struct _csync_treewalk_context_s
};
typedef struct _csync_treewalk_context_s _csync_treewalk_context;
time_t oc_httpdate_parse( const char *date );
void set_errno_from_http_errcode( int err );
/**
+15 -1
Ver Arquivo
@@ -65,7 +65,21 @@ static c_rbnode_t *_csync_check_ignored(c_rbtree_t *tree, const char *path, int
}
}
/*
/**
* The main function in the reconcile pass.
*
* It's called for each entry in the local and remote rbtrees by
* csync_reconcile()
*
* Before the reconcile phase the trees already know about changes
* relative to the sync journal. This function's job is to spot conflicts
* between local and remote changes and adjust the nodes accordingly.
*
* See doc/dev/sync-algorithm.md for an overview.
*
*
* Older detail comment:
*
* We merge replicas at the file level. The merged replica contains the
* superset of files that are on the local machine and server copies of
* the replica. In the case where the same file is in both the local
+1 -1
Ver Arquivo
@@ -50,7 +50,7 @@
*
* @todo Add an argument to set the algorithm to use.
*/
int csync_reconcile_updates(CSYNC *ctx);
int OCSYNC_EXPORT csync_reconcile_updates(CSYNC *ctx);
/**
* }@
+5
Ver Arquivo
@@ -20,6 +20,7 @@
extern "C" {
#include "csync_private.h"
#include "csync_rename.h"
}
#include <map>
@@ -93,5 +94,9 @@ char* csync_rename_adjust_path_source(CSYNC* ctx, const char* path)
return c_strdup(path);
}
bool csync_rename_count(CSYNC *ctx) {
csync_rename_s* d = csync_rename_s::get(ctx);
return d->folder_renamed_from.size();
}
}
+6 -4
Ver Arquivo
@@ -27,11 +27,13 @@ extern "C" {
#endif
/* Return the final destination path of a given patch in case of renames */
char *csync_rename_adjust_path(CSYNC *ctx, const char *path);
char OCSYNC_EXPORT *csync_rename_adjust_path(CSYNC *ctx, const char *path);
/* Return the source of a given path in case of renames */
char *csync_rename_adjust_path_source(CSYNC *ctx, const char *path);
void csync_rename_destroy(CSYNC *ctx);
void csync_rename_record(CSYNC *ctx, const char *from, const char *to);
char OCSYNC_EXPORT *csync_rename_adjust_path_source(CSYNC *ctx, const char *path);
void OCSYNC_EXPORT csync_rename_destroy(CSYNC *ctx);
void OCSYNC_EXPORT csync_rename_record(CSYNC *ctx, const char *from, const char *to);
/* Return the amount of renamed item recorded */
bool OCSYNC_EXPORT csync_rename_count(CSYNC *ctx);
#ifdef __cplusplus
}
+4 -7
Ver Arquivo
@@ -27,7 +27,6 @@
#include <sqlite3.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -53,7 +52,7 @@
#define sqlite_open(A, B) sqlite3_open_v2(A,B, SQLITE_OPEN_READONLY+SQLITE_OPEN_NOMUTEX, NULL)
#define SQLTM_TIME 150000
#define SQLTM_TIME 150
#define SQLTM_COUNT 10
#define SQLITE_BUSY_HANDLED(F) if(1) { \
@@ -61,7 +60,7 @@
do { rc = F ; \
if( (rc == SQLITE_BUSY) || (rc == SQLITE_LOCKED) ) { \
n++; \
usleep(SQLTM_TIME); \
csync_sleep(SQLTM_TIME); \
} \
}while( (n < SQLTM_COUNT) && ((rc == SQLITE_BUSY) || (rc == SQLITE_LOCKED))); \
}
@@ -519,8 +518,7 @@ c_strlist_t *csync_statedb_query(sqlite3 *db,
/* compile SQL program into a virtual machine, reattempteing if busy */
do {
if (busy_count) {
/* sleep 100 msec */
usleep(100000);
csync_sleep(100);
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "sqlite3_prepare: BUSY counter: %zu", busy_count);
}
err = sqlite3_prepare(db, statement, -1, &stmt, &tail);
@@ -547,8 +545,7 @@ c_strlist_t *csync_statedb_query(sqlite3 *db,
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Busy counter has reached its maximum. Aborting this sql statement");
break;
}
/* sleep 100 msec */
usleep(100000);
csync_sleep(100);
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "sqlite3_step: BUSY counter: %zu", busy_count);
continue;
}
+20 -2
Ver Arquivo
@@ -31,6 +31,11 @@
#include "csync_time.h"
#include "vio/csync_vio.h"
#ifndef _WIN32
#include <unistd.h>
#include <sys/time.h>
#endif
#define CSYNC_LOG_CATEGORY_NAME "csync.time"
#include "csync_log.h"
@@ -45,7 +50,13 @@
int csync_gettime(struct timespec *tp)
{
#ifdef HAVE_CLOCK_GETTIME
#if defined(_WIN32)
__int64 wintime;
GetSystemTimeAsFileTime((FILETIME*)&wintime);
wintime -= 116444736000000000ll; //1jan1601 to 1jan1970
tp->tv_sec = wintime / 10000000ll; //seconds
tp->tv_nsec = wintime % 10000000ll * 100; //nano-seconds
#elif defined(HAVE_CLOCK_GETTIME)
return clock_gettime(CSYNC_CLOCK, tp);
#else
struct timeval tv;
@@ -62,4 +73,11 @@ int csync_gettime(struct timespec *tp)
#undef CSYNC_CLOCK
/* vim: set ts=8 sw=2 et cindent: */
void csync_sleep(unsigned int msecs)
{
#if defined(_WIN32)
Sleep(msecs);
#else
usleep(msecs * 1000);
#endif
}
+1
Ver Arquivo
@@ -26,5 +26,6 @@
#include "csync_private.h"
int csync_gettime(struct timespec *tp);
void csync_sleep(unsigned int msecs);
#endif /* _CSYNC_TIME_H */
+25 -96
Ver Arquivo
@@ -56,26 +56,13 @@ static uint64_t _hash_of_file(CSYNC *ctx, const char *file) {
if( ctx && file ) {
path = file;
switch (ctx->current) {
case LOCAL_REPLICA:
if (ctx->current == LOCAL_REPLICA) {
if (strlen(path) <= strlen(ctx->local.uri)) {
return 0;
}
path += strlen(ctx->local.uri) + 1;
break;
case REMOTE_REPLICA:
if (strlen(path) <= strlen(ctx->remote.uri)) {
return 0;
}
path += strlen(ctx->remote.uri) + 1;
break;
default:
path = NULL;
return 0;
break;
}
len = strlen(path);
h = c_jhash64((uint8_t *) path, len, 0);
}
return h;
@@ -158,7 +145,19 @@ static bool _csync_mtime_equal(time_t a, time_t b)
return false;
}
/**
* The main function of the discovery/update pass.
*
* It's called (indirectly) by csync_update(), once for each entity in the
* local filesystem and once for each entity in the server data.
*
* It has two main jobs:
* - figure out whether anything happened compared to the sync journal
* and set (primarily) the instruction flag accordingly
* - build the ctx->local.tree / ctx->remote.tree
*
* See doc/dev/sync-algorithm.md for an overview.
*/
static int _csync_detect_update(CSYNC *ctx, const char *file,
const csync_vio_file_stat_t *fs, const int type) {
uint64_t h = 0;
@@ -176,25 +175,12 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
}
path = file;
switch (ctx->current) {
case LOCAL_REPLICA:
if (ctx->current == LOCAL_REPLICA) {
if (strlen(path) <= strlen(ctx->local.uri)) {
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
return -1;
}
path += strlen(ctx->local.uri) + 1;
break;
case REMOTE_REPLICA:
if (strlen(path) <= strlen(ctx->remote.uri)) {
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
return -1;
}
path += strlen(ctx->remote.uri) + 1;
break;
default:
path = NULL;
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
return -1;
}
len = strlen(path);
@@ -450,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;
}
@@ -617,16 +603,7 @@ int csync_walker(CSYNC *ctx, const char *file, const csync_vio_file_stat_t *fs,
static bool fill_tree_from_db(CSYNC *ctx, const char *uri)
{
const char *path = NULL;
if( strlen(uri) < strlen(ctx->remote.uri)+1) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "name does not contain remote uri!");
return false;
}
path = uri + strlen(ctx->remote.uri)+1;
if( csync_statedb_get_below_path(ctx, path) < 0 ) {
if( csync_statedb_get_below_path(ctx, uri) < 0 ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "StateDB could not be read!");
return false;
}
@@ -668,12 +645,6 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
bool do_read_from_db = (ctx->current == REMOTE_REPLICA && ctx->remote.read_from_db);
if (uri[0] == '\0') {
errno = ENOENT;
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
goto error;
}
read_from_db = ctx->remote.read_from_db;
// if the etag of this dir is still the same, its content is restored from the
@@ -687,16 +658,7 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
goto done;
}
const char *uri_for_vio = uri;
if (ctx->current == REMOTE_REPLICA) {
uri_for_vio += strlen(ctx->remote.uri);
if (strlen(uri_for_vio) > 0 && uri_for_vio[0] == '/') {
uri_for_vio++; // cut leading slash
}
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "URI without fuzz for %s is \"%s\"", uri, uri_for_vio);
}
if ((dh = csync_vio_opendir(ctx, uri_for_vio)) == NULL) {
if ((dh = csync_vio_opendir(ctx, uri)) == NULL) {
if (ctx->abort) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Aborted!");
ctx->status_code = CSYNC_STATUS_ABORTED;
@@ -742,8 +704,6 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
}
while ((dirent = csync_vio_readdir(ctx, dh))) {
const char *path = NULL;
size_t ulen = 0;
int flen;
int flag;
@@ -769,50 +729,19 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
continue;
}
flen = asprintf(&filename, "%s/%s", uri, d_name);
if (flen < 0) {
if (uri[0] == '\0') {
filename = c_strdup(d_name);
flen = strlen(d_name);
} else {
flen = asprintf(&filename, "%s/%s", uri, d_name);
}
if (flen < 0 || !filename) {
csync_vio_file_stat_destroy(dirent);
dirent = NULL;
ctx->status_code = CSYNC_STATUS_MEMORY_ERROR;
goto error;
}
/* Create relative path */
switch (ctx->current) {
case LOCAL_REPLICA:
ulen = strlen(ctx->local.uri) + 1;
break;
case REMOTE_REPLICA:
ulen = strlen(ctx->remote.uri) + 1;
break;
default:
break;
}
if (((size_t)flen) < ulen) {
csync_vio_file_stat_destroy(dirent);
dirent = NULL;
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
goto error;
}
path = filename + ulen;
/* skip ".csync_journal.db" and ".csync_journal.db.ctmp" */
/* Isn't this done via csync_exclude already? */
if (c_streq(path, ".csync_journal.db")
|| c_streq(path, ".csync_journal.db.ctmp")
|| c_streq(path, ".csync_journal.db.ctmp-journal")
|| c_streq(path, ".csync-progressdatabase")
|| c_streq(path, ".csync_journal.db-shm")
|| c_streq(path, ".csync_journal.db-wal")
|| c_streq(path, ".csync_journal.db-journal")) {
csync_vio_file_stat_destroy(dirent);
dirent = NULL;
SAFE_FREE(filename);
continue;
}
/* Only for the local replica we have to stat(), for the remote one we have all data already */
if (ctx->replica == LOCAL_REPLICA) {
res = csync_vio_stat(ctx, filename, dirent);
+3 -3
Ver Arquivo
@@ -26,9 +26,9 @@
#include "csync_private.h"
const char *csync_instruction_str(enum csync_instructions_e instr);
const char OCSYNC_EXPORT *csync_instruction_str(enum csync_instructions_e instr);
void csync_memstat_check(void);
void OCSYNC_EXPORT csync_memstat_check(void);
bool csync_file_locked_or_open( const char *dir, const char *fname);
bool OCSYNC_EXPORT csync_file_locked_or_open( const char *dir, const char *fname);
#endif /* _CSYNC_UTIL_H */
+6
Ver Arquivo
@@ -26,6 +26,12 @@ set(cstdlib_SRCS
c_time.c
)
if(NOT HAVE_ASPRINTF AND NOT HAVE___MINGW_ASPRINTF)
list(APPEND cstdlib_SRCS
asprintf.c
)
endif()
include_directories(
${CSTDLIB_PUBLIC_INCLUDE_DIRS}
${CSTDLIB_PRIVATE_INCLUDE_DIRS}
+90
Ver Arquivo
@@ -0,0 +1,90 @@
/*
https://raw.githubusercontent.com/littlstar/asprintf.c/20ce5207a4ecb24017b5a17e6cd7d006e3047146/asprintf.c
The MIT License (MIT)
Copyright (c) 2014 Little Star Media, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/**
* `asprintf.c' - asprintf
*
* copyright (c) 2014 joseph werle <joseph.werle@gmail.com>
*/
#ifndef HAVE_ASPRINTF
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "asprintf.h"
int
asprintf (char **str, const char *fmt, ...) {
int size = 0;
va_list args;
// init variadic argumens
va_start(args, fmt);
// format and get size
size = vasprintf(str, fmt, args);
// toss args
va_end(args);
return size;
}
int
vasprintf (char **str, const char *fmt, va_list args) {
int size = 0;
va_list tmpa;
// copy
va_copy(tmpa, args);
// apply variadic arguments to
// sprintf with format to get size
size = vsnprintf(NULL, size, fmt, tmpa);
// toss args
va_end(tmpa);
// return -1 to be compliant if
// size is less than 0
if (size < 0) { return -1; }
// alloc with size plus 1 for `\0'
*str = (char *) malloc(size + 1);
// return -1 to be compliant
// if pointer is `NULL'
if (NULL == *str) { return -1; }
// format string with original
// variadic arguments and set new size
size = vsprintf(*str, fmt, args);
return size;
}
#endif
+60
Ver Arquivo
@@ -0,0 +1,60 @@
/*
https://raw.githubusercontent.com/littlstar/asprintf.c/20ce5207a4ecb24017b5a17e6cd7d006e3047146/asprintf.h
The MIT License (MIT)
Copyright (c) 2014 Little Star Media, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/**
* `asprintf.h' - asprintf.c
*
* copyright (c) 2014 joseph werle <joseph.werle@gmail.com>
*/
#ifndef HAVE_ASPRINTF
#ifndef ASPRINTF_H
#define ASPRINTF_H 1
#include <stdarg.h>
/**
* Sets `char **' pointer to be a buffer
* large enough to hold the formatted string
* accepting a `va_list' args of variadic
* arguments.
*/
int
vasprintf (char **, const char *, va_list);
/**
* Sets `char **' pointer to be a buffer
* large enough to hold the formatted
* string accepting `n' arguments of
* variadic arguments.
*/
int
asprintf (char **, const char *, ...);
#endif
#endif
+11 -2
Ver Arquivo
@@ -31,14 +31,17 @@
#include <sys/stat.h>
#ifdef _WIN32
#include <windows.h>
#include <windef.h>
#include <winbase.h>
#include <wchar.h>
#else
#include <unistd.h>
#endif
#include <errno.h>
#ifdef _WIN32
#ifdef __MINGW32__
#define EDQUOT 0
#define ENODATA 0
#ifndef S_IRGRP
@@ -65,6 +68,8 @@
#define nlink_t int
#define getuid() 0
#define geteuid() 0
#elif defined(_WIN32)
#define mode_t int
#else
#include <fcntl.h>
#endif
@@ -89,8 +94,12 @@ typedef struct stat csync_stat_t;
#define ENODATA EBADF
#endif
#if !defined(HAVE_ASPRINTF) && defined(HAVE___MINGW_ASPRINTF)
#if !defined(HAVE_ASPRINTF)
#if defined(HAVE___MINGW_ASPRINTF)
#define asprintf __mingw_asprintf
#else
#include "asprintf.h"
#endif
#endif
#ifndef HAVE_STRERROR_R
+4
Ver Arquivo
@@ -25,6 +25,10 @@
#include "c_path.h"
#include "c_time.h"
#ifndef _WIN32
#include <sys/time.h>
#endif
struct timespec c_tspecdiff(struct timespec time1, struct timespec time0) {
struct timespec ret;
int xsec = 0;
-1
Ver Arquivo
@@ -22,7 +22,6 @@
#define _C_TIME_H
#include <time.h>
#include <sys/time.h>
/**
* @brief Calculate time difference
+4 -6
Ver Arquivo
@@ -21,12 +21,10 @@
#ifndef _CSYNC_VIO_LOCAL_H
#define _CSYNC_VIO_LOCAL_H
#include <sys/time.h>
csync_vio_handle_t OCSYNC_EXPORT *csync_vio_local_opendir(const char *name);
int OCSYNC_EXPORT csync_vio_local_closedir(csync_vio_handle_t *dhandle);
csync_vio_file_stat_t OCSYNC_EXPORT *csync_vio_local_readdir(csync_vio_handle_t *dhandle);
csync_vio_handle_t *csync_vio_local_opendir(const char *name);
int csync_vio_local_closedir(csync_vio_handle_t *dhandle);
csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_handle_t *dhandle);
int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf);
int OCSYNC_EXPORT csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf);
#endif /* _CSYNC_VIO_LOCAL_H */
-1
Ver Arquivo
@@ -23,7 +23,6 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdio.h>
#include "windows.h"
+16 -19
Ver Arquivo
@@ -23,38 +23,36 @@
#include "csync_private.h"
static void setup(void **state) {
static int setup(void **state) {
CSYNC *csync;
int rc;
rc = system("mkdir -p /tmp/check_csync1");
assert_int_equal(rc, 0);
rc = system("mkdir -p /tmp/check_csync2");
assert_int_equal(rc, 0);
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
csync_create(&csync, "/tmp/check_csync1");
*state = csync;
return 0;
}
static void setup_module(void **state) {
static int setup_module(void **state) {
CSYNC *csync;
int rc;
rc = system("mkdir -p /tmp/check_csync1");
assert_int_equal(rc, 0);
rc = system("mkdir -p /tmp/check_csync2");
assert_int_equal(rc, 0);
csync_create(&csync, "/tmp/check_csync1");
csync_create(&csync, "/tmp/check_csync1", "dummy://foo/bar");
csync_init(csync);
csync_init(csync, "foo");
*state = csync;
return 0;
}
static void teardown(void **state) {
static int teardown(void **state) {
CSYNC *csync = *state;
int rc;
@@ -66,10 +64,9 @@ static void teardown(void **state) {
rc = system("rm -rf /tmp/check_csync1");
assert_int_equal(rc, 0);
rc = system("rm -rf /tmp/check_csync2");
assert_int_equal(rc, 0);
*state = NULL;
return 0;
}
static void check_csync_commit(void **state)
@@ -97,10 +94,10 @@ static void check_csync_commit_dummy(void **state)
int torture_run_tests(void)
{
const UnitTest tests[] = {
unit_test_setup_teardown(check_csync_commit, setup, teardown),
unit_test_setup_teardown(check_csync_commit_dummy, setup_module, teardown),
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(check_csync_commit, setup, teardown),
cmocka_unit_test_setup_teardown(check_csync_commit_dummy, setup_module, teardown),
};
return run_tests(tests);
return cmocka_run_group_tests(tests, NULL, NULL);
}
+5 -5
Ver Arquivo
@@ -42,7 +42,7 @@ static void check_csync_create(void **state)
(void) state; /* unused */
csync_create(&csync, "/tmp/csync1", "/tmp/csync2");
csync_create(&csync, "/tmp/csync1");
rc = csync_destroy(csync);
assert_int_equal(rc, 0);
@@ -50,11 +50,11 @@ static void check_csync_create(void **state)
int torture_run_tests(void)
{
const UnitTest tests[] = {
unit_test(check_csync_destroy_null),
unit_test(check_csync_create),
const struct CMUnitTest tests[] = {
cmocka_unit_test(check_csync_destroy_null),
cmocka_unit_test(check_csync_create),
};
return run_tests(tests);
return cmocka_run_group_tests(tests, NULL, NULL);
}
+31 -15
Ver Arquivo
@@ -20,6 +20,7 @@
#include "config_csync.h"
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include "torture.h"
@@ -28,19 +29,20 @@
#define EXCLUDE_LIST_FILE SOURCEDIR"/../sync-exclude.lst"
static void setup(void **state) {
static int setup(void **state) {
CSYNC *csync;
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
csync_create(&csync, "/tmp/check_csync1");
*state = csync;
return 0;
}
static void setup_init(void **state) {
static int setup_init(void **state) {
CSYNC *csync;
int rc;
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
csync_create(&csync, "/tmp/check_csync1");
rc = csync_exclude_load(EXCLUDE_LIST_FILE, &(csync->excludes));
assert_int_equal(rc, 0);
@@ -58,9 +60,10 @@ static void setup_init(void **state) {
assert_int_equal(rc, 0);
*state = csync;
return 0;
}
static void teardown(void **state) {
static int teardown(void **state) {
CSYNC *csync = *state;
int rc;
@@ -73,6 +76,8 @@ static void teardown(void **state) {
assert_int_equal(rc, 0);
*state = NULL;
return 0;
}
static void check_csync_exclude_add(void **state)
@@ -142,6 +147,17 @@ static void check_csync_excluded(void **state)
assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
rc = csync_excluded_no_ctx(csync->excludes, "subdir/.csync_journal.db", CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
/* also the new form of the database name */
rc = csync_excluded_no_ctx(csync->excludes, "._sync_5bdd60bdfcfa.db", CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
rc = csync_excluded_no_ctx(csync->excludes, "._sync_5bdd60bdfcfa.db.ctmp", CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
rc = csync_excluded_no_ctx(csync->excludes, "._sync_5bdd60bdfcfa.db-shm", CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
rc = csync_excluded_no_ctx(csync->excludes, "subdir/._sync_5bdd60bdfcfa.db", CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
/* pattern ]*.directory - ignore and remove */
rc = csync_excluded_no_ctx(csync->excludes, "my.~directory", CSYNC_FTW_TYPE_FILE);
@@ -379,16 +395,16 @@ static void check_csync_exclude_expand_escapes(void **state)
int torture_run_tests(void)
{
const UnitTest tests[] = {
unit_test_setup_teardown(check_csync_exclude_add, setup, teardown),
unit_test_setup_teardown(check_csync_exclude_load, setup, teardown),
unit_test_setup_teardown(check_csync_excluded, setup_init, teardown),
unit_test_setup_teardown(check_csync_excluded_traversal, setup_init, teardown),
unit_test_setup_teardown(check_csync_pathes, setup_init, teardown),
unit_test_setup_teardown(check_csync_is_windows_reserved_word, setup_init, teardown),
unit_test_setup_teardown(check_csync_excluded_performance, setup_init, teardown),
unit_test(check_csync_exclude_expand_escapes),
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(check_csync_exclude_add, setup, teardown),
cmocka_unit_test_setup_teardown(check_csync_exclude_load, setup, teardown),
cmocka_unit_test_setup_teardown(check_csync_excluded, setup_init, teardown),
cmocka_unit_test_setup_teardown(check_csync_excluded_traversal, setup_init, teardown),
cmocka_unit_test_setup_teardown(check_csync_pathes, setup_init, teardown),
cmocka_unit_test_setup_teardown(check_csync_is_windows_reserved_word, setup_init, teardown),
cmocka_unit_test_setup_teardown(check_csync_excluded_performance, setup_init, teardown),
cmocka_unit_test(check_csync_exclude_expand_escapes),
};
return run_tests(tests);
return cmocka_run_group_tests(tests, NULL, NULL);
}
+15 -19
Ver Arquivo
@@ -23,37 +23,33 @@
#include "csync_private.h"
static void setup(void **state) {
static int setup(void **state) {
CSYNC *csync;
int rc;
rc = system("mkdir -p /tmp/check_csync1");
assert_int_equal(rc, 0);
rc = system("mkdir -p /tmp/check_csync2");
assert_int_equal(rc, 0);
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
csync_create(&csync, "/tmp/check_csync1");
*state = csync;
return 0;
}
static void setup_module(void **state) {
static int setup_module(void **state) {
CSYNC *csync;
int rc;
rc = system("mkdir -p /tmp/check_csync1");
assert_int_equal(rc, 0);
rc = system("mkdir -p /tmp/check_csync2");
assert_int_equal(rc, 0);
csync_create(&csync, "/tmp/check_csync1", "dummy://foo/bar");
csync_create(&csync, "/tmp/check_csync1");
*state = csync;
return 0;
}
static void teardown(void **state) {
static int teardown(void **state) {
CSYNC *csync = *state;
int rc;
@@ -65,28 +61,28 @@ static void teardown(void **state) {
rc = system("rm -rf /tmp/check_csync1");
assert_int_equal(rc, 0);
rc = system("rm -rf /tmp/check_csync2");
assert_int_equal(rc, 0);
*state = NULL;
return 0;
}
static void check_csync_init(void **state)
{
CSYNC *csync = *state;
csync_init(csync);
csync_init(csync, "");
assert_int_equal(csync->status & CSYNC_STATUS_INIT, 1);
}
int torture_run_tests(void)
{
const UnitTest tests[] = {
unit_test_setup_teardown(check_csync_init, setup, teardown),
unit_test_setup_teardown(check_csync_init, setup_module, teardown),
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(check_csync_init, setup, teardown),
cmocka_unit_test_setup_teardown(check_csync_init, setup_module, teardown),
};
return run_tests(tests);
return cmocka_run_group_tests(tests, NULL, NULL);
}
+12 -15
Ver Arquivo
@@ -19,7 +19,6 @@
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "torture.h"
@@ -27,22 +26,21 @@
#include "csync_log.c"
#include "c_private.h"
static void setup(void **state) {
static int setup(void **state) {
CSYNC *csync;
int rc;
rc = system("mkdir -p /tmp/check_csync1");
assert_int_equal(rc, 0);
rc = system("mkdir -p /tmp/check_csync2");
assert_int_equal(rc, 0);
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
csync_create(&csync, "/tmp/check_csync1");
*state = csync;
return 0;
}
static void teardown(void **state) {
static int teardown(void **state) {
CSYNC *csync = *state;
int rc;
@@ -54,10 +52,9 @@ static void teardown(void **state) {
rc = system("rm -rf /tmp/check_csync1");
assert_int_equal(rc, 0);
rc = system("rm -rf /tmp/check_csync2");
assert_int_equal(rc, 0);
*state = NULL;
return 0;
}
static void check_log_callback(int verbosity,
@@ -141,11 +138,11 @@ static void check_logging(void **state)
int torture_run_tests(void)
{
const UnitTest tests[] = {
unit_test(check_set_log_level),
unit_test(check_set_auth_callback),
unit_test_setup_teardown(check_logging, setup, teardown),
const struct CMUnitTest tests[] = {
cmocka_unit_test(check_set_log_level),
cmocka_unit_test(check_set_auth_callback),
cmocka_unit_test_setup_teardown(check_logging, setup, teardown),
};
return run_tests(tests);
return cmocka_run_group_tests(tests, NULL, NULL);
}
+3 -3
Ver Arquivo
@@ -48,10 +48,10 @@ static void check_csync_normalize_etag(void **state)
int torture_run_tests(void)
{
const UnitTest tests[] = {
unit_test(check_csync_normalize_etag),
const struct CMUnitTest tests[] = {
cmocka_unit_test(check_csync_normalize_etag),
};
return run_tests(tests);
return cmocka_run_group_tests(tests, NULL, NULL);
}
@@ -18,7 +18,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <string.h>
#include <unistd.h>
#include "torture.h"
@@ -27,7 +26,7 @@
#define TESTDB "/tmp/check_csync1/test.db"
static void setup(void **state) {
static int setup(void **state) {
CSYNC *csync;
int rc;
@@ -37,7 +36,7 @@ static void setup(void **state) {
rc = system("mkdir -p /tmp/check_csync1");
assert_int_equal(rc, 0);
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
csync_create(&csync, "/tmp/check_csync1");
csync->statedb.file = c_strdup( TESTDB );
*state = csync;
@@ -48,9 +47,11 @@ static void setup(void **state) {
rc = sqlite3_close(db);
assert_int_equal(rc, SQLITE_OK);
return 0;
}
static void teardown(void **state) {
static int teardown(void **state) {
CSYNC *csync = *state;
int rc;
@@ -61,6 +62,8 @@ static void teardown(void **state) {
assert_int_equal(rc, 0);
*state = NULL;
return 0;
}
static void check_csync_statedb_load(void **state)
@@ -117,11 +120,11 @@ static void check_csync_statedb_close(void **state)
int torture_run_tests(void)
{
const UnitTest tests[] = {
unit_test_setup_teardown(check_csync_statedb_load, setup, teardown),
unit_test_setup_teardown(check_csync_statedb_close, setup, teardown),
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(check_csync_statedb_load, setup, teardown),
cmocka_unit_test_setup_teardown(check_csync_statedb_close, setup, teardown),
};
return run_tests(tests);
return cmocka_run_group_tests(tests, NULL, NULL);
}
@@ -27,23 +27,19 @@
static void setup(void **state)
static int setup(void **state)
{
CSYNC *csync;
int rc = 0;
rc = system("rm -rf /tmp/check_csync1");
assert_int_equal(rc, 0);
rc = system("rm -rf /tmp/check_csync2");
assert_int_equal(rc, 0);
rc = system("mkdir -p /tmp/check_csync1");
assert_int_equal(rc, 0);
rc = system("mkdir -p /tmp/check_csync2");
assert_int_equal(rc, 0);
rc = system("mkdir -p /tmp/check_csync");
assert_int_equal(rc, 0);
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
csync_init(csync);
csync_create(&csync, "/tmp/check_csync1");
csync_init(csync, TESTDB);
sqlite3 *db = NULL;
rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
@@ -55,9 +51,11 @@ static void setup(void **state)
assert_int_equal(rc, 0);
*state = csync;
return 0;
}
static void setup_db(void **state)
static int setup_db(void **state)
{
char *errmsg;
int rc = 0;
@@ -93,10 +91,12 @@ static void setup_db(void **state)
assert_int_equal(rc, SQLITE_OK);
sqlite3_close(db);
return 0;
}
static void teardown(void **state) {
static int teardown(void **state) {
CSYNC *csync = *state;
int rc = 0;
@@ -106,10 +106,10 @@ static void teardown(void **state) {
assert_int_equal(rc, 0);
rc = system("rm -rf /tmp/check_csync1");
assert_int_equal(rc, 0);
rc = system("rm -rf /tmp/check_csync2");
assert_int_equal(rc, 0);
*state = NULL;
return 0;
}
@@ -210,15 +210,15 @@ static void check_csync_statedb_get_stat_by_inode_not_found(void **state)
int torture_run_tests(void)
{
const UnitTest tests[] = {
unit_test_setup_teardown(check_csync_statedb_query_statement, setup, teardown),
unit_test_setup_teardown(check_csync_statedb_drop_tables, setup, teardown),
unit_test_setup_teardown(check_csync_statedb_insert_metadata, setup, teardown),
unit_test_setup_teardown(check_csync_statedb_write, setup, teardown),
unit_test_setup_teardown(check_csync_statedb_get_stat_by_hash_not_found, setup_db, teardown),
unit_test_setup_teardown(check_csync_statedb_get_stat_by_inode_not_found, setup_db, teardown),
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(check_csync_statedb_query_statement, setup, teardown),
cmocka_unit_test_setup_teardown(check_csync_statedb_drop_tables, setup, teardown),
cmocka_unit_test_setup_teardown(check_csync_statedb_insert_metadata, setup, teardown),
cmocka_unit_test_setup_teardown(check_csync_statedb_write, setup, teardown),
cmocka_unit_test_setup_teardown(check_csync_statedb_get_stat_by_hash_not_found, setup_db, teardown),
cmocka_unit_test_setup_teardown(check_csync_statedb_get_stat_by_inode_not_found, setup_db, teardown),
};
return run_tests(tests);
return cmocka_run_group_tests(tests, NULL, NULL);
}
+27 -25
Ver Arquivo
@@ -81,7 +81,7 @@ static void statedb_insert_metadata(sqlite3 *db)
}
}
static void setup(void **state)
static int setup(void **state)
{
CSYNC *csync;
int rc;
@@ -91,10 +91,8 @@ static void setup(void **state)
assert_int_equal(rc, 0);
rc = system("mkdir -p /tmp/check_csync1");
assert_int_equal(rc, 0);
rc = system("mkdir -p /tmp/check_csync2");
assert_int_equal(rc, 0);
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
csync_init(csync);
csync_create(&csync, "/tmp/check_csync1");
csync_init(csync, TESTDB);
/* Create a new db with metadata */
sqlite3 *db;
@@ -111,9 +109,11 @@ static void setup(void **state)
assert_int_equal(rc, 0);
*state = csync;
return 0;
}
static void setup_ftw(void **state)
static int setup_ftw(void **state)
{
CSYNC *csync;
int rc;
@@ -122,10 +122,8 @@ static void setup_ftw(void **state)
assert_int_equal(rc, 0);
rc = system("mkdir -p /tmp/check_csync1");
assert_int_equal(rc, 0);
rc = system("mkdir -p /tmp/check_csync2");
assert_int_equal(rc, 0);
csync_create(&csync, "/tmp", "/tmp");
csync_init(csync);
csync_create(&csync, "/tmp");
csync_init(csync, TESTDB);
sqlite3 *db = NULL;
rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
@@ -139,9 +137,11 @@ static void setup_ftw(void **state)
csync->statedb.file = c_strdup( TESTDB );
*state = csync;
return 0;
}
static void teardown(void **state)
static int teardown(void **state)
{
CSYNC *csync = *state;
int rc;
@@ -151,9 +151,11 @@ static void teardown(void **state)
assert_int_equal(rc, 0);
*state = NULL;
return 0;
}
static void teardown_rm(void **state) {
static int teardown_rm(void **state) {
int rc;
teardown(state);
@@ -162,8 +164,8 @@ static void teardown_rm(void **state) {
assert_int_equal(rc, 0);
rc = system("rm -rf /tmp/check_csync1");
assert_int_equal(rc, 0);
rc = system("rm -rf /tmp/check_csync2");
assert_int_equal(rc, 0);
return 0;
}
/* create a file stat, caller must free memory */
@@ -430,19 +432,19 @@ static void check_csync_ftw_failing_fn(void **state)
int torture_run_tests(void)
{
const UnitTest tests[] = {
unit_test_setup_teardown(check_csync_detect_update, setup, teardown_rm),
unit_test_setup_teardown(check_csync_detect_update_db_none, setup, teardown),
unit_test_setup_teardown(check_csync_detect_update_db_eval, setup, teardown),
unit_test_setup_teardown(check_csync_detect_update_db_rename, setup, teardown),
unit_test_setup_teardown(check_csync_detect_update_db_new, setup, teardown_rm),
unit_test_setup_teardown(check_csync_detect_update_null, setup, teardown_rm),
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(check_csync_detect_update, setup, teardown_rm),
cmocka_unit_test_setup_teardown(check_csync_detect_update_db_none, setup, teardown),
cmocka_unit_test_setup_teardown(check_csync_detect_update_db_eval, setup, teardown),
cmocka_unit_test_setup_teardown(check_csync_detect_update_db_rename, setup, teardown),
cmocka_unit_test_setup_teardown(check_csync_detect_update_db_new, setup, teardown_rm),
cmocka_unit_test_setup_teardown(check_csync_detect_update_null, setup, teardown_rm),
unit_test_setup_teardown(check_csync_ftw, setup_ftw, teardown_rm),
unit_test_setup_teardown(check_csync_ftw_empty_uri, setup_ftw, teardown_rm),
unit_test_setup_teardown(check_csync_ftw_failing_fn, setup_ftw, teardown_rm),
cmocka_unit_test_setup_teardown(check_csync_ftw, setup_ftw, teardown_rm),
cmocka_unit_test_setup_teardown(check_csync_ftw_empty_uri, setup_ftw, teardown_rm),
cmocka_unit_test_setup_teardown(check_csync_ftw_failing_fn, setup_ftw, teardown_rm),
};
return run_tests(tests);
return cmocka_run_group_tests(tests, NULL, NULL);
}
+4 -4
Ver Arquivo
@@ -43,11 +43,11 @@ static void check_csync_memstat(void **state)
int torture_run_tests(void)
{
const UnitTest tests[] = {
unit_test(check_csync_instruction_str),
unit_test(check_csync_memstat),
const struct CMUnitTest tests[] = {
cmocka_unit_test(check_csync_instruction_str),
cmocka_unit_test(check_csync_memstat),
};
return run_tests(tests);
return cmocka_run_group_tests(tests, NULL, NULL);
}
+1
Ver Arquivo
@@ -457,6 +457,7 @@ sub traverse( $$;$ )
$isHere = 1 if( $acceptConflicts && !$isHere && $f =~ /_conflict/ );
$isHere = 1 if( $f =~ /\.csync/ );
$isHere = 1 if( $f =~ /\._sync_/ );
assert( $isHere, "Filename local, but not remote: $f" );
}
+1 -1
Ver Arquivo
@@ -176,7 +176,7 @@ assertLocalAndRemoteDir( 'remoteToLocal1', 1);
printInfo("simulate a owncloud 5 update by removing all the fileid");
## simulate a owncloud 5 update by removing all the fileid
system( "sqlite3 " . localDir() . ".csync_journal.db \"UPDATE metadata SET fileid='';\"");
system( "sqlite3 " . localDir() . "._sync_*.db \"UPDATE metadata SET fileid='';\"");
#refresh the ids
csync();
assertLocalAndRemoteDir( 'remoteToLocal1', 1);
+1 -1
Ver Arquivo
@@ -61,7 +61,7 @@ sub getETagFromJournal($$)
{
my ($name,$num) = @_;
my $sql = "sqlite3 " . localDir() . ".csync_journal.db \"SELECT md5 FROM metadata WHERE path='$name';\"";
my $sql = "sqlite3 " . localDir() . "._sync_*.db \"SELECT md5 FROM metadata WHERE path='$name';\"";
open(my $fh, '-|', $sql) or die $!;
my $etag = <$fh>;
close $fh;
+36 -5
Ver Arquivo
@@ -37,8 +37,8 @@ sub assertCsyncJournalOk {
my $path = $_[0];
# FIXME: should test also remoteperm but it's not working with owncloud6
# my $cmd = 'sqlite3 ' . $path . '.csync_journal.db "SELECT count(*) from metadata where length(remotePerm) == 0 or length(fileId) == 0"';
my $cmd = 'sqlite3 ' . $path . '.csync_journal.db "SELECT count(*) from metadata where length(fileId) == 0"';
# my $cmd = 'sqlite3 ' . $path . '._sync_*.db "SELECT count(*) from metadata where length(remotePerm) == 0 or length(fileId) == 0"';
my $cmd = 'sqlite3 ' . $path . '._sync_*.db "SELECT count(*) from metadata where length(fileId) == 0"';
my $result = `$cmd`;
assert($result == "0");
}
@@ -170,14 +170,14 @@ assertLocalAndRemoteDir( '', 0);
#######################################################################
printInfo( "move a directory in a outside read only folder" );
system("sqlite3 " . localDir().'.csync_journal.db .dump');
system("sqlite3 " . localDir().'._sync_*.db .dump');
#Missing directory should be restored
#new directory should be uploaded
system("mv " . localDir().'readonlyDirectory_PERM_M_/subdir_PERM_CK_ ' . localDir().'normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_' );
csync();
system("sqlite3 " . localDir().'.csync_journal.db .dump');
system("sqlite3 " . localDir().'._sync_*.db .dump');
assertCsyncJournalOk(localDir());
# old name restored
@@ -229,7 +229,38 @@ system("rm -r " . localDir(). "readonlyDirectory_PERM_M_/moved_PERM_CK_");
assertLocalAndRemoteDir( '', 0);
system("sqlite3 " . localDir().'.csync_journal.db .dump');
system("sqlite3 " . localDir().'._sync_*.db .dump');
#######################################################################
printInfo( "multiple restores of a file create different conflict files" );
system("sleep 1"); #make sure changes have different mtime
system("echo 'modified_1' > ". localDir() . "readonlyDirectory_PERM_M_/canotBeModified_PERM_DVN_.data");
#do the sync
csync();
assertCsyncJournalOk(localDir());
system("sleep 1"); #make sure changes have different mtime
system("echo 'modified_2' > ". localDir() . "readonlyDirectory_PERM_M_/canotBeModified_PERM_DVN_.data");
#do the sync
csync();
assertCsyncJournalOk(localDir());
# there should be two conflict files
# TODO check that the conflict file has the right content
my @conflicts = glob(localDir().'readonlyDirectory_PERM_M_/canotBeModified_PERM_DVN__conflict-*.data' );
assert( scalar @conflicts == 2 );
# remove the conflicts for the next assertLocalAndRemoteDir
system("rm " . localDir().'readonlyDirectory_PERM_M_/canotBeModified_PERM_DVN__conflict-*.data' );
### Both side should still be the same
assertLocalAndRemoteDir( '', 0);
cleanup();
+6
Ver Arquivo
@@ -56,6 +56,8 @@ assertLocalAndRemoteDir( '', 0);
printInfo( "Testing with a .sys.admin#recall#" );
system("echo 'dir/file2.dat' > ". $tmpdir . ".sys.admin\#recall\#");
system("echo 'dir/file3.dat' >> ". $tmpdir . ".sys.admin\#recall\#");
system("echo 'nonexistant' >> ". $tmpdir . ".sys.admin\#recall\#");
system("echo '/tmp/t_recall/file4.dat' >> ". $tmpdir . ".sys.admin\#recall\#");
glob_put( "$tmpdir/.sys.admin\#recall\#", "" );
csync();
@@ -68,6 +70,10 @@ assert( -e glob(localDir().'dir/file3_.sys.admin#recall#-*.dat' ) );
assert( -e glob(localDir().'dir/file2.dat' ) );
assert( -e glob(localDir().'dir/file3.dat' ) );
assert( !-e glob(localDir().'nonexistant*' ) );
assert( !-e glob('/tmp/t_recall/file4_.sys.admin#recall#-*.dat' ) );
assert( -e glob('/tmp/t_recall/file4.dat' ) );
#Remove the recall file
unlink(localDir() . ".sys.admin#recall#");
-1
Ver Arquivo
@@ -18,7 +18,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <string.h>
#include <unistd.h>
#include "torture.h"
+1 -2
Ver Arquivo
@@ -22,7 +22,6 @@
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "torture.h"
@@ -49,7 +48,7 @@ static void setup(void **state)
rc = system("rm -rf /tmp/csync_test");
assert_int_equal(rc, 0);
csync_create(&csync, "/tmp/csync1", "/tmp/csync2");
csync_create(&csync, "/tmp/csync1");
csync->replica = LOCAL_REPLICA;
+1 -2
Ver Arquivo
@@ -22,7 +22,6 @@
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include "torture.h"
@@ -97,7 +96,7 @@ static void setup_testenv(void **state) {
statevar *mystate = malloc( sizeof(statevar) );
mystate->result = NULL;
csync_create(&(mystate->csync), "/tmp/csync1", "/tmp/csync2");
csync_create(&(mystate->csync), "/tmp/csync1");
mystate->csync->replica = LOCAL_REPLICA;
+3 -8
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
@@ -153,7 +153,8 @@ By default, the ownCloud Client ignores the following files:
* Files matched by one of the patterns defined in the Ignored Files Editor
* Files containing characters that do not work on certain file systems ``(`\, /, :, ?, *, ", >, <, |`)``.
* Files starting with ``.csync_journal.db``, as these files are reserved for journalling.
* Files starting with ``._sync_xxxxxxx.db`` and the old format ``.csync_journal.db``,
as these files are reserved for journalling.
If a pattern selected using a checkbox in the `ignoredFilesEditor-label` (or if
a line in the exclude file starts with the character ``]`` directly followed by
@@ -199,12 +200,6 @@ the database by comparing the files and their modification times. This process
ensures that both server and client are synchronized using the appropriate NTP
time before restarting the client following a database removal.
Pressing ``F5`` while in the Account Settings Dialog enables you to "reset" the
journal. This function can be used to recreate the journal database.
.. note:: We recommend that you use this function only when advised to do so by
ownCloud support staff.
Custom WebDAV Properties
------------------------
+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``.
+34 -11
Ver Arquivo
@@ -42,7 +42,8 @@ repositories`_ to see all the Linux client repos.
echo 'deb-src
http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/Debian_8.0/ /' >> /etc/apt/sources.list.d/owncloud-client.list
2. Install the dependencies using the following commands for your specific Linux distribution:
2. Install the dependencies using the following commands for your specific Linux
distribution. Make sure the repositories for source packages are enabled.
* Debian/Ubuntu: ``apt-get update; apt-get build-dep owncloud-client``
* openSUSE/SLES: ``zypper ref; zypper si -d owncloud-client``
@@ -53,7 +54,7 @@ repositories`_ to see all the Linux client repos.
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
@@ -65,31 +66,45 @@ recipes.
To set up your build environment for development using HomeBrew_:
1. Add the ownCloud repository using the following command::
1. Install Xcode
2. Install Xcode command line tools::
xcode-select --install
3. Install homebrew::
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
4. Add the ownCloud repository using the following command::
brew tap owncloud/owncloud
2. 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/qmake
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.
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.
.. note:: Contrary to earlier versions, ownCloud 1.7 and later are packaged
.. note:: Contrary to earlier versions, ownCloud 1.7 and later are packaged
as a ``pkg`` installer. Do not call "make package" at any time when
compiling for OS X, as this will build a disk image, and will not
work correctly.
@@ -233,6 +248,14 @@ To build the most up-to-date version of the client:
.. note:: On Mac OS X, you need to specify ``-DCMAKE_INSTALL_PREFIX=target``,
where ``target`` is a private location, i.e. in parallel to your build
dir by specifying ``../install``.
..note:: qtkeychain must be compiled with the same prefix e.g CMAKE_INSTALL_PREFIX=/Users/path/to/client/install/
.. note:: Example:: cmake -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5 -DCMAKE_INSTALL_PREFIX=/Users/path/to/client/install/ -D_OPENSSL_LIBDIR=/usr/local/opt/openssl/lib/ -D_OPENSSL_INCLUDEDIR=/usr/local/opt/openssl/include/ -DOPENSSL_INCLUDE_DIR=/usr/local/opt/openssl/include/ -DNO_SHIBBOLETH=1
.. note:: Example:: cmake -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5 -DCMAKE_INSTALL_PREFIX=/Users/path/to/client/install/ -D_OPENSSL_LIBDIR=/usr/local/opt/openssl/lib/ -D_OPENSSL_INCLUDEDIR=/usr/local/opt/openssl/include/ -D_OPENSSL_VERSION=1.0.2a -DOPENSSL_INCLUDE_DIR=/usr/local/opt/openssl/include/ -DNO_SHIBBOLETH=1
qtkeychain must be compiled with the same prefix e.g CMAKE_INSTALL_PREFIX=/Users/path/to/client/install/ .
4. Call ``make``.
+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.
+84
Ver Arquivo
@@ -0,0 +1,84 @@
Sync Algorithm
==============
Overview
--------
This is a technical description of the synchronization (sync) algorithm used by the ownCloud client.
The sync algorithm is the thing that looks at the local and remote file system trees and the sync journal and decides which steps need to be taken to bring the two trees into synchronization. It's different from the propagator, whose job it is to actually execute these steps.
Definitions
-----------
- local tree: The files and directories on the local file system that shall be kept in sync with the remote tree.
- remote tree: The files and directories on the ownCloud server that shall be kept in sync with the local tree.
- sync journal (journal): A snapshot of file and directory metadata that the sync algorithm uses as a baseline to detect local or remote changes. Typically stored in a database.
- file and directory metadata:
- mtimes
- sizes
- inodes (journal and local only): Representation of filesystem object. Useful for rename detection.
- etags (journal and remote only): The server assigns a new etag when a file or directory changes.
- checksums (journal and remote only): Checksum algorithm applied to a file's contents.
- permissions (journal and remote only)
Phases
------
### Discovery (aka Update)
The discovery phase collects file and directory metadata from the local and remote trees, detecting differences between each tree and the journal.
Afterwards, we have two trees that tell us what happened relative to the journal. But there may still be conflicts if something happened to an entity both locally and on the remote.
- Input: file system, server data, journal
- Output: two c_rbtree_t*, representing the local and remote trees
- Note on remote discovery: Since a change to a file on the server causes the etags of all parent folders to change, folders with an unchanged etag can be read from the journal directly and don't need to be walked into.
- Details
- csync_update() uses csync_ftw() on the local and remote trees, one after the other.
- csync_ftw() iterates through the entities in a tree and calls csync_walker() for each.
- csync_walker() calls _csync_detect_update() on each.
- _csync_detect_update() compares the item to its journal entry (if any) to detect new, changed or renamed files. This is the main function of this pass.
### Reconcile
The reconcile phase compares and adjusts the local and remote trees (in both directions), detecting conflicts.
Afterwards, there are still two trees, but conflicts are marked in them.
- Input: c_rbtree_t* for the local and remote trees, journal (for some rename-related queries)
- Output: changes c_rbtree_t* in-place
- Details
- csync_reconcile() runs csync_reconcile_updates() for the local and remote trees, one after the other.
- csync_reconcile_updates() uses c_rbtree_walk() to iterate through the entries, calling _csync_merge_algorithm_visitor() for each.
- _csync_merge_algorithm_visitor() checks whether the other tree also has an entry for that node and merges the actions, detecting conflicts. This is the main function of this pass.
### Post-Reconcile
The post-reconcile phase merges the two trees into one set of SyncFileItems.
Afterwards, there is a list of items that can tell the propagator what needs to be done.
- Input: c_rbtree_t* for the local and remote trees
- Output: QMap<QString, SyncFileItemPtr>
- Note that some "propagations", specifically cheap metadata-only updates, are already done at this stage.
- Details
- csync_walk_local_tree() and csync_walk_remote_tree() are called.
- They use _csync_walk_tree() to run SyncEngine::treewalkFile() on each entry.
- treewalkFile() creates and fills SyncFileItems for each entry, ensuring that each file only has a single instance. This is the main function of this pass.
See Also
--------
An overview of the propagation steps is still missing. The sync protocol is documented at https://github.com/cernbox/smashbox/blob/master/protocol/protocol.md.
+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.
+1 -1
Ver Arquivo
@@ -12,7 +12,7 @@ Desktop Sync client enables you to:
Your files are always automatically synchronized between your ownCloud server
and local PC.
Because of various technical issues, desktop sync clients older than 1.7 will
Because of various technical issues, desktop sync clients older than 2.2.1 will
not allowed to connect and sync with the ownCloud 8.1+ server. It is highly
recommended to keep your client updated.
+1 -1
Ver Arquivo
@@ -65,7 +65,7 @@ If no client is configured, or if you choose to use a different user to synchron
you can specify the user
password setting with the usual URL pattern. For example::
$ owncloudcmd / https://carla:secret@server/owncloud/remote.php/webdav/
$ owncloudcmd /home/user/my_sync_folder https://carla:secret@server/owncloud/remote.php/webdav/
To synchronize the ownCloud directory ``Music`` to the local directory
``media/music``, through a proxy listening on port ``8080``, and on a gateway
+2 -1
Ver Arquivo
@@ -4,7 +4,8 @@
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+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
+362 -4
Ver Arquivo
@@ -292,6 +292,360 @@ 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
# 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
# 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
# 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
@@ -382,10 +736,10 @@ Comment[cs_CZ]=@APPLICATION_NAME@ počítačový synchronizační klient
GenericName[cs_CZ]=Synchronizace adresáře
Name[cs_CZ]=@APPLICATION_NAME@ počítačový synchronizační klient
Icon[cs_CZ]=@APPLICATION_EXECUTABLE@
Comment[ru]=Настольный клиент синхронизации @НАЗВАНИЕ_ПРИЛОЖЕНИЯ@
GenericName[ru]=Синхронизация папки
Name[ru]=Настольный клиент синхронизации @НАЗВАНИЕ_ПРИЛОЖЕНИЯ@
Icon[ru]=@ВЫПОЛНЯЕМОЕ_ПРИЛОЖЕНИЕ@
Comment[ru]=Настольный клиент синхронизации @APPLICATION_NAME@
GenericName[ru]=Синхронизация каталогов
Name[ru]=Настольный клиент синхронизации @APPLICATION_NAME@
Icon[ru]=@APPLICATION_EXECUTABLE@
Comment[sl]=@APPLICATION_NAME@ Program za usklajevanje datotek z namizjem
GenericName[sl]=Usklajevanje map
Name[sl]=@APPLICATION_NAME@ Program za usklajevanje datotek z namizjem
@@ -427,6 +781,10 @@ Comment[th_TH]=@APPLICATION_NAME@ ไคลเอนต์ประสานข
GenericName[th_TH]=ประสานข้อมูลโฟลเดอร์
Name[th_TH]= @APPLICATION_NAME@ ไคลเอนต์ประสานข้อมูลเดสก์ท็อป
Icon[th_TH]=@APPLICATION_EXECUTABLE@
Comment[es_MX]=Cliente de escritorio para sincronziación de @APPLICATION_NAME@
GenericName[es_MX]=Sincronización de Carpetas
Name[es_MX]=Cliente de escritorio para sincronziación de @APPLICATION_NAME@
Icon[es_MX]=@APPLICATION_EXECUTABLE@
Comment[nb_NO]=@APPLICATION_NAME@ skrivebordssynkroniseringsklient
GenericName[nb_NO]=Mappesynkronisering
Name[nb_NO]=@APPLICATION_NAME@ skrivebordssynkroniseringsklient
+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;
}
+2 -1
Ver Arquivo
@@ -49,5 +49,6 @@ target_link_libraries(${OWNCLOUDDOLPHINOVERLAYPLUGIN} KF5::CoreAddons KF5::KIOCo
set(OWNCLOUDDOLPHINACTIONPLUGIN ${APPLICATION_EXECUTABLE}dolphinactionplugin)
add_library(${OWNCLOUDDOLPHINACTIONPLUGIN} MODULE ownclouddolphinactionplugin.cpp)
target_link_libraries(${OWNCLOUDDOLPHINACTIONPLUGIN} KF5::CoreAddons KF5::KIOCore KF5::KIOWidgets ${OWNCLOUDDOLPHINHELPER})
install(FILES ownclouddolphinactionplugin.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} RENAME ${OWNCLOUDDOLPHINACTIONPLUGIN}.desktop)
configure_file(ownclouddolphinactionplugin.desktop.in ${OWNCLOUDDOLPHINACTIONPLUGIN}.desktop ESCAPE_QUOTES @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${OWNCLOUDDOLPHINACTIONPLUGIN}.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR})
install(TARGETS ${OWNCLOUDDOLPHINACTIONPLUGIN} DESTINATION ${KDE_INSTALL_PLUGINDIR})
@@ -24,6 +24,7 @@
#include <KIOCore/kfileitem.h>
#include <KIOCore/KFileItemListProperties>
#include <QtWidgets/QAction>
#include <QtCore/QDir>
#include <QtCore/QTimer>
#include "ownclouddolphinpluginhelper.h"
@@ -43,7 +44,8 @@ public:
auto url = urls.first();
if (!url.isLocalFile())
return {};
auto localFile = url.toLocalFile();
QDir localPath(url.toLocalFile());
auto localFile = localPath.canonicalPath();
const auto paths = helper->paths();
if (!std::any_of(paths.begin(), paths.end(), [&](const QString &s) {
@@ -1,6 +1,6 @@
[Desktop Entry]
Type=Service
Name=OwncloudAction
Name=@APPLICATION_NAME@Action
ServiceTypes=KFileItemAction/Plugin
MimeType=application/octet-stream;inode/directory;
X-KDE-Library=ownclouddolphinactionplugin
X-KDE-Library=@APPLICATION_EXECUTABLE@dolphinactionplugin
@@ -21,6 +21,7 @@
#include <KPluginFactory>
#include <QtNetwork/QLocalSocket>
#include <KIOCore/kfileitem.h>
#include <QDir>
#include <QTimer>
#include "ownclouddolphinpluginhelper.h"
@@ -46,7 +47,8 @@ public:
return QStringList();
if (!url.isLocalFile())
return QStringList();
const QByteArray localFile = url.toLocalFile().toUtf8();
QDir localPath(url.toLocalFile());
const QByteArray localFile = localPath.canonicalPath().toUtf8();
helper->sendCommand(QByteArray("RETRIEVE_FILE_STATUS:" + localFile + "\n"));
+11 -2
Ver Arquivo
@@ -4,6 +4,7 @@ if( UNIX AND NOT APPLE )
configure_file(syncstate.py syncstate.py COPYONLY)
configure_file(syncstate.py syncstate_nemo.py COPYONLY)
configure_file(syncstate.py syncstate_caja.py COPYONLY)
# Call the setupappname.sh script to set the custom app name.
set (cmd "${CMAKE_CURRENT_SOURCE_DIR}/setappname.sh")
@@ -18,9 +19,17 @@ if( UNIX AND NOT APPLE )
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
ERROR_VARIABLE errors OUTPUT_VARIABLE out)
# Create a caja plugin script from the nautilus one.
# cajacmd copies the syncstate.py and performs string replacement.
set (cajacmd "${CMAKE_CURRENT_SOURCE_DIR}/createcajaplugin.sh")
execute_process(COMMAND ${cajacmd}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
ERROR_VARIABLE errors OUTPUT_VARIABLE out)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate.py DESTINATION ${DATADIR}/nautilus-python/extensions)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate_nemo.py DESTINATION ${DATADIR}/nemo-python/extensions RENAME syncstate.py)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate.py DESTINATION ${DATADIR}/nautilus-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate_nemo.py DESTINATION ${DATADIR}/nemo-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate_caja.py DESTINATION ${DATADIR}/caja-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
+7
Ver Arquivo
@@ -0,0 +1,7 @@
#!/bin/sh
# this script creates a plugin for caja, just by replacing
# all occurences of Nautilus with Caja (case sensitive).
sed -i.org -e 's/Nautilus/Caja/g' syncstate_caja.py
sed -i.org -e 's/nautilus/caja/g' syncstate_caja.py
+66 -37
Ver Arquivo
@@ -18,6 +18,7 @@
import os
import urllib
import socket
import tempfile
from gi.repository import GObject, Nautilus
@@ -43,7 +44,7 @@ def get_runtime_dir():
try:
return os.environ['XDG_RUNTIME_DIR']
except KeyError:
fallback = '/tmp/runtime-' + os.environ['USER']
fallback = os.path.join(tempfile.gettempdir(), 'runtime-' + os.environ['USER'])
return fallback
@@ -86,22 +87,17 @@ class SocketConnect(GObject.GObject):
def _connectToSocketServer(self):
try:
self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
postfix = "/" + appname + "/socket" # Should use os.path.join instead
sock_file = get_runtime_dir() + postfix
print ("Socket: " + sock_file + " <=> " + postfix)
if sock_file != postfix:
try:
print("Socket File: " + sock_file)
self._sock.connect(sock_file)
self.connected = True
print("Setting connected to %r." % self.connected )
self._watch_id = GObject.io_add_watch(self._sock, GObject.IO_IN, self._handle_notify)
print("Socket watch id: " + str(self._watch_id))
return False # Don't run again
except Exception as e:
print("Could not connect to unix socket. " + str(e))
else:
print("Sock-File not valid: " + sock_file)
sock_file = os.path.join(get_runtime_dir(), appname, "socket")
try:
print("Socket File: " + sock_file)
self._sock.connect(sock_file) # fails if sock_file doesn't exist
self.connected = True
print("Setting connected to %r." % self.connected )
self._watch_id = GObject.io_add_watch(self._sock, GObject.IO_IN, self._handle_notify)
print("Socket watch id: " + str(self._watch_id))
return False # Don't run again
except Exception as e:
print("Could not connect to unix socket. " + str(e))
except Exception as e: # Bad habbit
print("Connect could not be established, try again later.")
self._sock.close()
@@ -157,32 +153,65 @@ class MenuExtension(GObject.GObject, Nautilus.MenuProvider):
def __init__(self):
GObject.GObject.__init__(self)
def check_registered_paths(self, filename):
topLevelFolder = False
internalFile = False
for reg_path in socketConnect.registered_paths:
if filename == reg_path:
topLevelFolder = True
break
if filename.startswith(reg_path):
internalFile = True
# you can't have a registered path below another so it is save to break here
break
return (topLevelFolder, internalFile)
def get_file_items(self, window, files):
# Show the menu extension to share a file or folder
#
# Show if file is OK.
# Ignore top level folders.
# Also show extension for folders
# if there is a OK or SYNC underneath.
# This is only
if len(files) != 1:
return
file = files[0]
items = []
# Internal or external file?!
syncedFile = False
for reg_path in socketConnect.registered_paths:
topLevelFolder = False
filename = get_local_path(file.get_uri())
# Check if its a folder (ends with an /), if yes add a "/"
# otherwise it will not find the entry in the table
if os.path.isdir(filename + "/"):
filename += "/"
# Check if toplevel folder, we need to ignore those as they cannot be shared
if filename == reg_path:
topLevelFolder=True
# Only show the menu extension if the file is synced and the sync
# status is ok. Not for ignored files etc.
# ignore top level folders
if filename.startswith(reg_path) and topLevelFolder == False and socketConnect.nautilusVFSFile_table[filename]['state'].startswith('OK'):
syncedFile = True
filename = get_local_path(file.get_uri())
# Check if its a folder (ends with an /), if yes add a "/"
# otherwise it will not find the entry in the table
isDir = os.path.isdir(filename + os.sep)
if isDir:
filename += os.sep
# If it is neither in a synced folder or is a directory
if not syncedFile:
# Check if toplevel folder, we need to ignore those as they cannot be shared
topLevelFolder, internalFile = self.check_registered_paths(filename)
if topLevelFolder or not internalFile:
return items
entry = socketConnect.nautilusVFSFile_table.get(filename)
if not entry:
return items
shareable = False
state = entry['state']
state_ok = state.startswith('OK')
state_sync = state.startswith('SYNC')
if state_ok:
shareable = True
elif state_sync and isDir:
# some file below is OK or SYNC
for key, value in socketConnect.nautilusVFSFile_table.items():
if key != filename and key.startswith(filename):
state = value['state']
if state.startswith('OK') or state.startswith('SYNC'):
shareable = True
break
if not shareable:
return items
# Create a menu item
@@ -303,7 +332,7 @@ class SyncStateExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.Info
filename = get_local_path(item.get_uri())
if item.is_directory():
filename += '/'
filename += os.sep
inScope = False
for reg_path in socketConnect.registered_paths:
@@ -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

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