1
0
mirror of https://github.com/chylex/Nextcloud-Desktop.git synced 2026-04-03 18:11:32 +02:00

Compare commits

...

367 Commits

Author SHA1 Message Date
Markus Goetz
95297e23bf VERSION.cmake: 2.5.0 alpha 2018-05-25 15:56:36 +02:00
Dominik Schmidt
13d0595296 Update libcrashreporter-qt to build it with msvc
(cherry picked from commit b9323bd191)
2018-05-25 15:36:54 +02:00
Markus Goetz
88abf43bda ChangeLog: More entries 2018-05-25 15:32:16 +02:00
Christian Kamm
de77514671 AccountWizard: Reserve space for error label #6546 2018-05-25 08:44:03 +02:00
Jenkins for ownCloud
5c69130300 [tx-robot] updated from transifex 2018-05-25 02:18:51 +02:00
Markus Goetz
74e412c789 owncloudsynclog: 1 MB -> 10 MB #6420 2018-05-24 16:02:52 +02:00
Christian Kamm
5811c74f9c Settings migration: Preserve future settings where possible
See discussion in #6506
2018-05-24 12:18:44 +02:00
Christian Kamm
57a2881906 Config: Add version flags to accounts and folders
Also, if there is too-new configuration, backup the file, show a
warning message asking the user whether it's ok to discard the
configuration from the future.

See #6504
2018-05-24 12:18:44 +02:00
Olivier Goffart
c625d8e3b7 Credentials: Retry fetching from the keychain in case the keychain is still starting
When owncloud is restored, at boot time, it might be started before the
crendential manager. So if we detect an error, wait 10 seconds and hopefully
it'd be loaded by then.

Issues: #4274, #6522
2018-05-24 12:10:55 +02:00
Christian Kamm
53f52b4cf5 Settings: Add warning when switching update channel 2018-05-24 12:09:40 +02:00
Christian Kamm
293c2b4f79 Updater: Make sparkle updater respect release channel 2018-05-24 12:09:40 +02:00
Markus Goetz
29349d4b3a Auto Updater: Show UI element also on macOS
(cherry picked from commit dfdc2e1e87f99d387a042f4983c999fbb7fcf3d9)
2018-05-24 12:09:40 +02:00
Christian Kamm
7790953a2c Settings: Add update channel combobox #6259 2018-05-24 12:09:40 +02:00
Jenkins for ownCloud
e3083d6791 [tx-robot] updated from transifex 2018-05-24 02:18:53 +02:00
Christian Kamm
8f9f2b5462 Rename Placeholders to Virtual Files in code #6531 2018-05-23 09:57:00 +02:00
Jenkins for ownCloud
70b1deb226 [tx-robot] updated from transifex 2018-05-23 02:18:39 +02:00
Jenkins for ownCloud
2b112b8dcf [tx-robot] updated from transifex 2018-05-22 02:18:40 +02:00
Jenkins for ownCloud
9350b4458c [tx-robot] updated from transifex 2018-05-21 02:18:39 +02:00
Jenkins for ownCloud
2870715fff [tx-robot] updated from transifex 2018-05-20 02:18:40 +02:00
Jenkins for ownCloud
b0aa3a1da0 [tx-robot] updated from transifex 2018-05-19 02:18:42 +02:00
Christian Kamm
0cd2540a69 Add to and rearrange the Changelog for 2.5 2018-05-18 07:43:43 +02:00
Jenkins for ownCloud
e680b3f3c8 [tx-robot] updated from transifex 2018-05-18 02:19:19 +02:00
Christian Kamm
2493cbe491 SyncJournal: Explain added file-exists check 2018-05-17 15:02:52 +02:00
Christian Kamm
394ef439e0 Merge branch 'master' into 2.5 2018-05-17 13:23:20 +02:00
Markus Goetz
309c53ca8f macOS: Don't use WAL for sqlite3 in /Volumes
For #6049
2018-05-17 13:19:30 +02:00
Christian Kamm
2638332dc6 Upload: Adjust timeout for final job based on size #6527
Some servers have virus scanners and the like that can delay the
response of the final chunked upload assembly significantly, often
breaking the current 5min (!) timeout. See owncloud/enterprise#2480
for details.
2018-05-17 13:14:37 +02:00
Christian Kamm
5308fc4148 Propagation: Connection closed is a normal error #6516
Because it sometimes appears in conjunction with server bugs and we
don't want to halt all syncing for other files in these cases.
2018-05-17 13:14:20 +02:00
Christian Kamm
ad5fbfe05b Wizard: Add a "(recommended)" to the main option #6470 2018-05-17 13:14:03 +02:00
Christian Kamm
b1224cff0c SyncJournal: Check file existence even for open dbs #6049
With WAL mode sqlite seems to occasionally crash when the
underlying filesystem goes away.
2018-05-17 13:08:42 +02:00
Jenkins for ownCloud
ce06c96135 [tx-robot] updated from transifex 2018-05-17 02:19:19 +02:00
Christian Kamm
1c4592339a Rename "placeholder" feature 2018-05-16 12:52:32 +02:00
Markus Goetz
0365653055 Sparkle: Delegate calls work now with 1.18.1 (maybe even before)
We can extend on this to give UI feedback.
2018-05-16 11:29:27 +02:00
Jenkins for ownCloud
d8078d43fb [tx-robot] updated from transifex 2018-05-16 02:19:12 +02:00
Olivier Goffart
fabc706e43 SyncRunFileLog: Add the requestid
https://github.com/owncloud/client/pull/6427#issuecomment-383879509
2018-05-15 18:11:01 +02:00
Olivier Goffart
e7e8a62bb7 Blacklist: remember the X-Request-ID
Issue #6420
Store the X-Request-ID in the SyncFileItem and also in the blacklist.
Note that for consistency reason, the X-Request-ID is also in the
SyncFileItem if the request succeeds.

Currently there is no UI to access it, but it can be queried with sql
commands
2018-05-15 18:11:01 +02:00
Christian Kamm
f396f2f41d IgnoreEditor: Preserve comments, add #!readonly
Useful in case we ever want to make use of directives inside the ignore
list.
2018-05-15 14:26:35 +02:00
Christian Kamm
8d14f4357a Placeholder: Stop adding ignore pattern
Because we can't make older clients preserve the version directive that
was attached to it.

See #6504 and #6498
2018-05-15 14:26:35 +02:00
Christian Kamm
34d40e6c67 Placeholder: Don't contain "stub" 2018-05-15 14:26:35 +02:00
Christian Kamm
c80ee0ea48 Placeholders: Save to key that's invisible to <2.5 clients #6504 2018-05-15 14:26:35 +02:00
Olivier Goffart
fb71a90756 FolderWizard: fix crash when experimental feature are disabled
The _placeholderCheckBox only exists if the experimental features are enabled

Found via the crash reporter
https://sentry.io/owncloud/desktop-win-and-mac/issues/556407777/
2018-05-15 12:33:09 +02:00
Olivier Goffart
41dc87c748 Update binary submodule 2018-05-15 12:18:54 +02:00
Christian Kamm
8b952d3741 TestChunkingNG: Remove unneeded test code 2018-05-15 09:42:54 +02:00
Christian Kamm
33b0726390 PropagateUpload: Fix miscount in abort() #6516
Previously it tried to abort even jobs that had already finished, which
was not going to work as they wouldn't emit finished() again.

Also, in some cases the abortCount would never go to zero and that case
wasn't well documented.
2018-05-15 09:42:54 +02:00
Christian Kamm
40e23d3da7 PropagateUpload: Remove unused PropagateUploadFileCommon::abort 2018-05-15 09:42:54 +02:00
Jenkins for ownCloud
97ff3dccb8 [tx-robot] updated from transifex 2018-05-15 02:18:53 +02:00
Dominik Schmidt
fd18ece619 Use newer craft cache 2018-05-14 13:40:12 +02:00
Dominik Schmidt
fe5e5fcb32 Fix for png2ico 2018-05-14 13:40:12 +02:00
Dominik Schmidt
0f57326057 Fix create_windows_icon_and_rc invocation for png2ico 2018-05-14 13:40:12 +02:00
Dominik Schmidt
886f31456a Add FindIcoTool.cmake 2018-05-14 13:40:12 +02:00
Dominik Schmidt
2d7841204c Support icotool in ECMAddAppIcon macro 2018-05-14 13:40:12 +02:00
Olivier Goffart
5f6f5f5789 Merge remote-tracking branch 'origin/2.5' 2018-05-14 09:46:15 +02:00
Olivier Goffart
64e351c6d3 Merge remote-tracking branch 'origin/2.5' 2018-05-14 09:44:42 +02:00
Christian Kamm
5e4aca8988 ShareLink: Preserve password when unrelated ui changes #6512 2018-05-14 09:44:21 +02:00
Christian Kamm
d917f52779 Remove debug code 2018-05-14 09:37:28 +02:00
Jenkins for ownCloud
cca7914204 [tx-robot] updated from transifex 2018-05-14 02:18:41 +02:00
Jenkins for ownCloud
974b6a8845 [tx-robot] updated from transifex 2018-05-13 02:18:40 +02:00
Jenkins for ownCloud
52aa5754c3 [tx-robot] updated from transifex 2018-05-12 02:18:39 +02:00
Jenkins for ownCloud
2bfcd60d18 [tx-robot] updated from transifex 2018-05-11 02:18:42 +02:00
Jenkins for ownCloud
2e64b291da [tx-robot] updated from transifex 2018-05-10 02:18:42 +02:00
Jenkins for ownCloud
ce42080cc7 [tx-robot] updated from transifex 2018-05-09 02:18:31 +02:00
Matthew Setter
600a98e2e9 Merge pull request #6502 from owncloud/correct-osx-ui-nomenclature
Correct incorrect reference to OSX Menu bar
2018-05-08 14:17:37 +02:00
Matthew Setter
a547e228d3 Correct incorrect reference to OSX Menu bar
This fixes https://github.com/owncloud/documentation/issues/4109.
2018-05-08 14:17:12 +02:00
Jenkins for ownCloud
369d833610 [tx-robot] updated from transifex 2018-05-08 02:18:32 +02:00
Jenkins for ownCloud
80e0f03f1b [tx-robot] updated from transifex 2018-05-07 02:18:30 +02:00
Jenkins for ownCloud
63935f086d [tx-robot] updated from transifex 2018-05-06 02:18:33 +02:00
Jenkins for ownCloud
905877ecc0 [tx-robot] updated from transifex 2018-05-05 02:18:31 +02:00
Jenkins for ownCloud
af4e40c3fc [tx-robot] updated from transifex 2018-05-04 02:18:32 +02:00
Christian Kamm
e9ac35b2e5 Doc: Adjust step-by-step guide for creating log files #6442 2018-05-03 11:13:03 +02:00
Matthew Setter
ce260909a8 Merge pull request #6505 from owncloud/integrate-external-themes-repo
Integrate external themes repository
2018-05-03 10:18:12 +02:00
Samuel Alfageme
d1304b2c05 Set copyright's upper bound dynamically based on the compilation date
Ref. https://github.com/owncloud/client/pull/6505\#discussion_r185712624
2018-05-03 09:39:56 +02:00
Samuel Alfageme
6b3f9ee4c9 Remove the outdated submodule reference from the git tree
This completes the rename started in 0ce287d96d
	- As suggested in https://github.com/owncloud/client/pull/6505\#discussion_r185496084

Also, fixes its reference on CMakeLists.txt so the whole thing builds again
2018-05-03 09:20:45 +02:00
Jenkins for ownCloud
b7eb9b2040 [tx-robot] updated from transifex 2018-05-03 02:18:34 +02:00
Matthew Setter
0ce287d96d Use external theme in documentation 2018-05-02 21:40:49 +02:00
Samuel Alfageme
5e13d519d9 Use HTTPS rather than SSH schema for the _shared_assets submodule 2018-05-02 16:56:44 +02:00
Samuel Alfageme
2c53025b0a Removed CMake-generated files and referenced the right themes path
- i.e. Makefile and conf.py (generated via pyconfigure's conf.py.in) - included both into local .gitignore
- Fixed the reference to _shared_assets in the CMake script and the copyright used in the metadata.
2018-05-02 13:49:49 +02:00
Samuel Alfageme
0d51b32722 Fix broken LTS link to point to Ubuntu's release policy
- To fix make's client/doc/installing.rst:39: ERROR: Unknown target name: 'lts' on build.
- Also removed references to wizard's last page after https://github.com/owncloud/client/pull/5729
2018-05-02 13:12:04 +02:00
Matthew Setter
489342018f Use external theme in documentation 2018-05-02 12:06:32 +02:00
Matthew Setter
e5dd54d4f4 Add the docs-themes repository as a submodule
This provides a simpler way of integrating the external theme.
Relates to:

- owncloud/client#6163
- owncloud/client#6169
- #3240
- owncloud/client#6497
2018-05-02 12:04:14 +02:00
Jenkins for ownCloud
f470b045d7 [tx-robot] updated from transifex 2018-05-02 02:18:34 +02:00
Jenkins for ownCloud
2b7a726acf [tx-robot] updated from transifex 2018-05-01 02:18:33 +02:00
Jenkins for ownCloud
7cac493a6e [tx-robot] updated from transifex 2018-04-30 02:18:31 +02:00
Jenkins for ownCloud
ad917d038f [tx-robot] updated from transifex 2018-04-29 02:18:35 +02:00
Jenkins for ownCloud
7710b66498 [tx-robot] updated from transifex 2018-04-28 02:18:31 +02:00
Jenkins for ownCloud
0a14fce639 [tx-robot] updated from transifex 2018-04-27 02:18:33 +02:00
Christian Kamm
642ed1bb70 Merge remote-tracking branch 'origin/master' into 2.5 2018-04-26 10:16:45 +02:00
Christian Kamm
3f9c10e641 Proxy settings: Fix bad behavior with empty host
Fixes f6a075ef54 for #5885

When no host is given it shouldn't just *appear* that there is no
proxy, there actually shouldn't be a proxy set then.
2018-04-26 10:07:05 +02:00
Jenkins for ownCloud
4327fede32 [tx-robot] updated from transifex 2018-04-26 02:18:37 +02:00
Markus Goetz
8b45fbfdab Share Dialog: Disable workaround for macOS too #6185 2018-04-25 19:32:01 +02:00
Olivier Goffart
2696c520bd Wizard: fix a layout glitch 2018-04-25 14:47:56 +02:00
Olivier Goffart
1ab3a9fc13 Nautilus: Fix Python3 and remove many debug
Use b'\n' in the call to rfind, as the _remainder is bytes, not a string.

Remove most of the debug message which happens during normal operation.
They are mostly spamming the nautilus console, and can also cause bug
as they may throw exception in case of wrong encoding.

Relates to issue: #6406
2018-04-25 13:58:45 +02:00
Markus Goetz
9d4ece4b3a ShareDialog: macOS grey odditiy #5774 2018-04-25 13:56:19 +02:00
Christian Kamm
e9db52a378 Issues: Show link to conflicts doc if there are some #6396
The link url is themed.
2018-04-25 13:31:49 +02:00
Christian Kamm
fc73cde10c Merge branch 'master' into 2.5 2018-04-25 12:30:31 +02:00
Christian Kamm
44071f0892 Nautilus shell integration: Print python version on startup #6406 2018-04-25 12:26:18 +02:00
Jenkins for ownCloud
529649254b [tx-robot] updated from transifex 2018-04-25 02:18:37 +02:00
Samuel Alfageme
1ec5d5b0cf Fix 'client/doc/conffile.rst:36: ERROR: Malformed table' 2018-04-24 16:13:45 +02:00
Olivier Goffart
7053a9c3d9 Update installing.rst 2018-04-24 13:33:56 +02:00
Jürgen Weigert
5ccf5fd9a1 update supported linux platforms 2018-04-24 13:33:56 +02:00
Adrien
6520263244 Fix #6394 2018-04-24 13:27:33 +02:00
Christian Kamm
9555f8d75c Show a tray message when a folder watcher becomes unreliable #6119 2018-04-24 13:06:50 +02:00
Olivier Goffart
073de7a8e0 Merge remote-tracking branch 'origin/2.5' 2018-04-24 13:02:37 +02:00
Thomas Boerger
397206134f Dropped .travis.yml from repo 2018-04-24 12:54:22 +02:00
Thomas Boerger
a12986a952 Build clang and gcc on drone 2018-04-24 12:54:22 +02:00
Thomas Boerger
5270b76520 Dropped .travis.yml from repo 2018-04-24 12:52:27 +02:00
Thomas Boerger
f0dae03d06 Build clang and gcc on drone 2018-04-24 12:52:27 +02:00
Christian Kamm
4268f793fb Share dialog: Don't hide account settings before showing #6185
At least on windows and linux. OSX would need tests first since
the addition was originally supposed to help with OSX problems,
see #3783.
2018-04-24 10:09:23 +02:00
Olivier Goffart
1ef7ca1b09 sqlite: Update bundled version to 3.23.1
For OS X and Windows.
2018-04-24 09:16:06 +02:00
Jenkins for ownCloud
dd5265a5f8 [tx-robot] updated from transifex 2018-04-24 02:18:31 +02:00
Jenkins for ownCloud
84a692435e [tx-robot] updated from transifex 2018-04-23 15:28:10 +02:00
Olivier Goffart
c1fb5e6b20 Wizard: Move the 'Skip folder configuration' in a radio button
Issue #3664
2018-04-23 13:29:01 +02:00
Olivier Goffart
e0b554ada9 Fix a bunch of warning with clang
The option -Wno-discarded-qualifiers only exists with GCC, clang warns that
it has no effects.

Also it warns when some virtual fuction are marked with override but not
all of them.
2018-04-23 13:22:01 +02:00
Christian Kamm
1508b562ad SocketAPI: Allow opening share dialog if contents still syncing #4608
With the previous changes the "Share..." action was shown but it didn't
work yet.
2018-04-23 12:24:32 +02:00
Christian Kamm
4390bbf838 SocketAPI: Remove SHARE_STATUS
It was never used by a shell integration.
2018-04-23 12:24:32 +02:00
Jenkins for ownCloud
a4d049464b [tx-robot] updated from transifex 2018-04-23 02:18:31 +02:00
Jenkins for ownCloud
0073b7581f [tx-robot] updated from transifex 2018-04-22 02:18:33 +02:00
Jenkins for ownCloud
1ce3e4c27a [tx-robot] updated from transifex 2018-04-21 02:18:32 +02:00
Markus Goetz
69e5d55956 Logging: Avoid the word "Error"
The old code printed "QNetworkReply::NoError"
2018-04-20 15:26:34 +02:00
Christian Kamm
7cce30942e CMake: Add a default placeholder_suffix
To make themes work that don't define it explicitly.
2018-04-20 15:08:08 +02:00
Jenkins for ownCloud
71db7fef77 [tx-robot] updated from transifex 2018-04-20 02:18:32 +02:00
Markus Goetz
b6f1ba38a6 Placeholders: Support for macOS #6290 2018-04-19 19:24:29 +02:00
Christian Kamm
f6a075ef54 Network settings: If no proxy host given, show "no proxy" #5885
What happens internally is that a proxy without a hostname gets treated
as no proxy.
2018-04-19 17:04:56 +02:00
Olivier Goffart
c5701f635a Fix test: QTemporaryDir::filePath was added in Qt 5.9 2018-04-19 17:01:31 +02:00
Olivier Goffart
2bf1f27c80 More Button: Use SVG and fix size so it renders good in highdpi
When the more button was changed from using a text to an icon,
the size computation was not adjusted proerly to that of a button
with an icon.

And using svg allows it to be rendered correctly with high-dpi

It looks much much nicer now
2018-04-19 16:44:11 +02:00
Christian Kamm
a5271b529b LocalDiscoveryTracker: Add unit test #6120 2018-04-19 10:58:46 +02:00
Christian Kamm
7c558394c1 LocalDiscoveryTracker: Separate from Folder and move to libsync
To allow relevant code to be closer together and for testing in
unittests without having to get a gui Folder.

See #6120
2018-04-19 10:58:46 +02:00
Jenkins for ownCloud
d2d5439c5c [tx-robot] updated from transifex 2018-04-19 02:18:39 +02:00
Olivier Goffart
c82aa10a66 ChangeLog: update for 2.5 2018-04-18 15:04:56 +02:00
Olivier Goffart
38f1c5b7d2 Logger: Guard zlib usage by ZLIB_FOUND
Similar to the use for the checksum.
I know that zlib is required in principle, but i don't have it
in one of my test building environment, and it is easier to just
disable it.
2018-04-18 15:01:30 +02:00
Christian Kamm
985a657f48 Merge remote-tracking branch 'origin/master' 2018-04-18 11:14:08 +02:00
Christian Kamm
9e8464e114 Merge branch 'placeholder-prototype' 2018-04-18 11:02:53 +02:00
Olivier Goffart
02b818af04 Download: Use the <s:message> from the reply in the error message if any
Issue: #6459
2018-04-18 10:57:16 +02:00
Olivier Goffart
0fdfb2cba3 Add a test for resuming downloads 2018-04-18 10:57:16 +02:00
Christian Kamm
a9561f494b Doc: Add showExperimentalOptions to conffile.rst 2018-04-18 10:27:51 +02:00
Christian Kamm
b7412a4f09 Wizards: Show placeholder option only if showExperimentalOptions is set
This config file option will also control other features in the future.
2018-04-18 10:27:51 +02:00
Christian Kamm
ba1309b3a4 Wizards: Add placeholder option and warning to account wizard
Also add the warning dialog to the option in the folder wizard.
2018-04-18 10:27:51 +02:00
Christian Kamm
70b4dc99dc NSIS: Register placeholder extension
Also change the placeholder suffix config option to not include the dot,
the dotless form is needed in the nsis script.
2018-04-18 10:27:51 +02:00
Christian Kamm
65a2b1aa8a Placeholders: Fix migration issues
Some edgecases weren't covered and didn't have tests yet.
2018-04-18 10:27:51 +02:00
Christian Kamm
fb3e3edcbd SyncOptions: Add default placeholder suffix
Otherwise each test has to set this up anew.
2018-04-18 10:27:51 +02:00
Christian Kamm
c2f84d7c3e Placeholders: Ignore placeholder files in older clients
To do this, we add the placeholder extension to the user exclude file
automatically. However, newer clients shouldn't use that exclude
pattern: so we also add version directives that allow making exclude
patterns dependent on the client version.
2018-04-18 10:27:51 +02:00
Christian Kamm
8358dabbfd Folder: Simplify relative path computation
It was done manually in several places after folderForPath() calls.
2018-04-18 10:27:51 +02:00
Christian Kamm
8b6ae04155 Placeholders: Download from shell integration 2018-04-18 10:27:51 +02:00
Olivier Goffart
87433bfe87 Placeholder: The extension is now a branding option 2018-04-18 10:27:51 +02:00
Olivier Goffart
9bd583b0e5 Placeholders: Fixup clicking on placeholder after previous change
Now that the name in the db is the name of the placeholder file,
we need to adjust the call to downloadPlaceholder
2018-04-18 10:27:51 +02:00
Christian Kamm
01bb241e48 Placeholders: Safe migration to older client versions
Now the db entries for placeholders will have the full placeholder
paths. That way older clients will, on remote discovery, delete the
placeholders and download the real files.
2018-04-18 10:27:51 +02:00
Christian Kamm
e2f2c9a153 Placeholders: Deal with conflicts when a placeholder exists
So "foo.owncloud" exists but the user adds a new "foo".
2018-04-18 10:27:51 +02:00
Olivier Goffart
a41d385607 Placeholders: install mimetype on linux 2018-04-18 10:27:51 +02:00
Olivier Goffart
a8b4526d65 Placeholders: Add an checkbox in the FolderWizard to enable the placeholder feature 2018-04-18 10:27:51 +02:00
Olivier Goffart
a2191474eb Placeholders: Move the placeholder option from the account to the folder 2018-04-18 10:27:51 +02:00
Olivier Goffart
cc8497916d PlaceHolders: Trigger a download of the placeholder and open it 2018-04-18 10:27:51 +02:00
Christian Kamm
798e60c9f6 On-demand downloading: Placeholder-file based prototype
- Controled by an option.
- New remote files start out as ItemTypePlaceholder, are created with a
  .owncloud extension.
- When their db entry is set to ItemTypePlaceholderDownload the next
  sync run will download them.
- Files that aren't in the placeholder state sync as usual.
- See test cases in testsyncplaceholders.

Missing:
- User ui for triggering placeholder file download
- Maybe: Going back from file to placeholder?
2018-04-18 10:27:51 +02:00
Christian Kamm
57044c1e02 Silence warning by removing unnecessary this capture 2018-04-18 10:26:22 +02:00
Jenkins for ownCloud
daa26d0c81 [tx-robot] updated from transifex 2018-04-18 02:18:35 +02:00
Markus Goetz
9ed937a6d3 Documentation: Update building.rst #6154 #5594 2018-04-17 19:03:08 +02:00
Markus Goetz
5509cd2504 Notifications: Also have clickable link #6236 2018-04-17 16:57:38 +02:00
Christian Kamm
fa6ac9da23 Upload: Add more chunk resuming unit tests #6405 2018-04-17 13:48:13 +02:00
Jenkins for ownCloud
78e80e5d46 [tx-robot] updated from transifex 2018-04-17 02:18:37 +02:00
Olivier Goffart
2c18ea0a89 Uploads: Don't delete unexisting chunks
Since commit 4dc49ff3, we store an entry in the upload info table even
for non chunked uploads. However, if this fails we don't want to remove
non-existant stale chunks if the upload fails.

Without this commit, we would send a DELETE command to clean non-existant
chunks in the dav/uploads/ namespace.
2018-04-16 12:00:12 +02:00
Christian Kamm
93d8810414 SocketApi/Sharing: Add "copy public link" to menu #6356
* The new menu option will fetch shares and create a new link share if
  no "context menu share" currently exists.
* Various cleanup of common operations in socketapi happened as well,
  in particular there's now FileData::get() that calculates all the
  relevant paths that are useful for most socketapi actions.
2018-04-16 08:37:44 +02:00
Markus Goetz
aaa00c1f30 Q_UNUSED: Sprinkle around 2018-04-13 17:15:37 +02:00
Markus Goetz
2728c49649 Notifications: Lower hiding timeout
With the 4.5sec timeout, it was very easy to accidently hit the wrong notification
when the previous one dissapeared so late.
2018-04-13 16:55:55 +02:00
Jenkins for ownCloud
1449426aee [tx-robot] updated from transifex 2018-04-13 02:18:37 +02:00
Markus Goetz
aceff1f863 macOS: Implement new dynamic Finder menu items #6328 2018-04-12 13:12:42 +02:00
Christian Kamm
113f56fdc5 Logging: Add persistent auto-logdir option #6442 2018-04-12 12:38:17 +02:00
Christian Kamm
bd9ec3dbee LogDir: Compress log when switching files #6442 2018-04-12 12:38:17 +02:00
Christian Kamm
6fcff62e95 LogDir: Go to new file on Problem/Abort too #6442 2018-04-12 12:38:17 +02:00
Jenkins for ownCloud
abc3667048 [tx-robot] updated from transifex 2018-04-12 02:18:34 +02:00
Markus Goetz
894686e66a macOS: Unload the Finder extension on exit #5382 #3819 2018-04-11 13:37:34 +02:00
Christian Kamm
db64b217b8 Doc: Explaining conflict files and resolving them #6396 2018-04-11 09:02:15 +02:00
Jenkins for ownCloud
7e5edac9ce [tx-robot] updated from transifex 2018-04-11 02:18:33 +02:00
Christian Kamm
ca36da6037 Doc: Remove out of date changelog copy 2018-04-10 09:20:22 +02:00
Christian Kamm
73777beb00 Doc: fix for new conflict tag 2018-04-10 09:17:05 +02:00
Christian Kamm
eef275a1e4 Folders: Use "Problem" icon for unresolved conflicts #6277 2018-04-10 08:38:59 +02:00
Jenkins for ownCloud
1114b8ce0a [tx-robot] updated from transifex 2018-04-10 02:18:37 +02:00
Olivier Goffart
716be66234 SyncJournalDb::setSelectiveSyncList: Always use a transaction
Issue #6431
2018-04-09 12:22:52 +02:00
Christian Kamm
2298ecca7c Share link: Update permission wording #6192 2018-04-09 12:16:40 +02:00
Jenkins for ownCloud
0f5a43797a [tx-robot] updated from transifex 2018-04-09 02:18:33 +02:00
Jenkins for ownCloud
268eae1da6 [tx-robot] updated from transifex 2018-04-08 02:18:31 +02:00
Jenkins for ownCloud
d128608f21 [tx-robot] updated from transifex 2018-04-07 02:18:31 +02:00
Jenkins for ownCloud
cbcd3a05e7 [tx-robot] updated from transifex 2018-04-06 02:18:37 +02:00
Olivier Goffart
42b254785e Theme: unify ownCloudTheme and Theme classes
The goal is to avoid confusion described in issue #6422 by removing
duplicates between the Theme and owncloudTheme.

 - Use the about from ownCloudTheme everywhere
 - Create default applicationIcons() and condifFileName() that should work
   everywhere
 - trayFolderIcon was removed as it is not used
 - the helpUrl from the default Theme now points to the owncloud client
   documentation. Before there was no help entry by default for branded
   client if the function was not overriden.
 - Do not merge functions that would otherwise break compatibility with
   theme that did not override them. For example colors or customMedia.
2018-04-05 18:37:29 +02:00
Jenkins for ownCloud
d6b16c3c06 [tx-robot] updated from transifex 2018-04-05 02:18:31 +02:00
Markus Goetz
55414d4c1d macOS: Don't hardcode path in Installer source 2018-04-04 16:45:42 +02:00
Markus Goetz
3bafa1ec89 macOS: Offer only standard installation in installer 2018-04-04 16:23:18 +02:00
Markus Goetz
dfc0545994 create_mac.sh: Also name properly in source dir 2018-04-04 15:46:16 +02:00
Markus Goetz
71de396a5d macosx.pkgproj; This is a .cmake preprocessed file 2018-04-04 15:42:31 +02:00
Jenkins for ownCloud
f9299826b1 [tx-robot] updated from transifex 2018-04-04 02:18:36 +02:00
Markus Goetz
e9646364a0 macdeployqt: Adjust minimum version based on our Qt #5932 2018-04-03 21:31:02 +02:00
Markus Goetz
75241c6cd6 Remove admin/osx/sign_dmg.sh
We don't do dmh anymore.
2018-04-03 19:27:20 +02:00
Joss Brown
fc4582ddf6 postinstall macOS: check if Finder is running
Some users have disabled Finder, and the postinstall will always reenable Finder, unless it checks Finder status first.
2018-04-03 16:00:08 +02:00
Christian Kamm
02a2056543 Notify if an explicitly excluded folder is created #6222 2018-04-03 14:03:46 +02:00
Christian Kamm
afec3ccf6e Conflicts: Change tags to be more user friendly #6365
From "_conflict-user-yyyymmdd-hhmmss"
to   " (conflicted copy user yyyy-mm-dd hhmmss)"
2018-04-03 14:03:03 +02:00
Jenkins for ownCloud
49b1a32251 [tx-robot] updated from transifex 2018-04-03 02:18:32 +02:00
Jenkins for ownCloud
a450859789 [tx-robot] updated from transifex 2018-04-02 02:18:31 +02:00
Jenkins for ownCloud
8b1b572935 [tx-robot] updated from transifex 2018-04-01 02:18:34 +02:00
Jenkins for ownCloud
cc4149c125 [tx-robot] updated from transifex 2018-03-31 02:18:33 +02:00
Jenkins for ownCloud
073fda3d03 [tx-robot] updated from transifex 2018-03-30 02:18:32 +02:00
Jenkins for ownCloud
6f44cc3d98 [tx-robot] updated from transifex 2018-03-29 02:18:50 +02:00
Christian Kamm
9f346037ee Nautilus integration: Not a ColumnProvider
The nautilus plugin doesn't actually define get_columns(), so pretending
to be a ColumnProvider lead to a critical warning on startup.
2018-03-28 15:30:05 +02:00
Olivier Goffart
39d909b05a csync_update: add the checksum in the discovery log
Issue #6414
2018-03-28 13:42:54 +02:00
Christian Kamm
28f68369be Blacklist: Add unittest #6411 2018-03-28 11:25:32 +02:00
Christian Kamm
2641a6af21 Rename local discovery option for clarity
It's using full relative filepaths, not just dir paths.
2018-03-28 11:25:32 +02:00
Olivier Goffart
d69936e065 FolderStatusModel: fix potential assert
OCC::FolderStatusModel::slotUpdateDirectories: ASSERT: "parentInfo->_fetching" in file /home/olivier/kdegit/owncloud/mirall/src/gui/folderstatusmodel.cpp, line 599

This can happen if the structure of a folder is change while the user
expands the root folder. In this case, resetSubs() is called which
resets _fetching to false.
Instead, we need to keep a pointer to the job so we can abort it by
deleting it.
2018-03-28 10:19:05 +02:00
Christian Kamm
1ac45be94e Readme: Update list of maintainers 2018-03-28 10:11:40 +02:00
Christian Kamm
3d002468ae Readme: Fix link to binary downloads 2018-03-28 10:11:40 +02:00
Christian Kamm
5e75d224ee Blacklisting must prevent parent etag updates #6411 2018-03-28 10:01:33 +02:00
Jenkins for ownCloud
8e7f7cfec8 [tx-robot] updated from transifex 2018-03-28 02:18:35 +02:00
Markus Goetz
31f13c8846 SslButton: Improve speed (especially on macOS) #6031
From 1+n*450msec to 1*450msec
2018-03-27 17:43:57 +02:00
Christian Kamm
25deaed9e5 Excludes: Expand doc, Desktop.ini only in root folder
The Desktop.ini exclude was added for 2.4 because we add such a file to
the synced folder on Windows. It doesn't need to cover subdirectories.
2018-03-27 12:43:53 +02:00
Christian Kamm
17342031d7 Upload: Simplify 'finished' flag
* Sometimes there was 'finished' and '_finished'
* Make each done() call automatically set _finished to true
2018-03-27 12:42:48 +02:00
Olivier Goffart
26b991c0c0 Folder: normalize the local path.
We otherwise normalize all path in the C form, so we must have
the Folder's path normalized the same. Or all comparizon will fail
(such as knowing if a file from the SocketAPI or the FilesystemWatcher
are part of the folder)

Issue #4424
2018-03-27 10:54:10 +02:00
Olivier Goffart
3f4d504c34 propagateuploadv1: don't finalize after a done()
Should fix an assert when "Server does not support X-OC-MTime"
(Which only happens with owncloud 5)

Issue #6403
2018-03-27 10:50:40 +02:00
Olivier Goffart
6a4486df3b Merge pull request #6402 from whitequark/patch-1
Dolphin plugin: fall back if $XDG_RUNTIME_DIR is empty
2018-03-27 10:32:12 +02:00
Jenkins for ownCloud
9516519165 [tx-robot] updated from transifex 2018-03-27 02:18:34 +02:00
Markus Goetz
7739157bfc SslButton: Add HTTP/2 info #3146 2018-03-26 22:49:54 +02:00
Markus Goetz
b34878c16d macOS: Put Qt version in .pkg name 2018-03-26 19:21:27 +02:00
Jenkins for ownCloud
962c38583f [tx-robot] updated from transifex 2018-03-26 02:18:32 +02:00
whitequark
9bd30cf003 Dolphin plugin: fall back if $XDG_RUNTIME_DIR is empty
As per XDG Base Directories specification:
> If $XDG_RUNTIME_DIR is not set applications should fall back
> to a replacement directory [...]

In practice, the ownCloud client has the fallback, but the plugin
helper does not, and if $XDG_RUNTIME_DIR is not set, the plugin
mysteriously does not work.
2018-03-24 08:12:25 +00:00
Jenkins for ownCloud
20881cd004 [tx-robot] updated from transifex 2018-03-24 02:18:32 +01:00
Jenkins for ownCloud
e5b93c7584 [tx-robot] updated from transifex 2018-03-23 02:18:33 +01:00
Markus Goetz
24e2c809e4 macOS: Fix .app icon 2018-03-22 16:30:22 +01:00
Markus Goetz
75a269acb6 About section: Try to lower height #6075 #6215 2018-03-22 15:37:04 +01:00
Jenkins for ownCloud
8357f1ea9a [tx-robot] updated from transifex 2018-03-22 02:18:32 +01:00
Markus Goetz
20bd943a87 macdeployqt: Qt 5.10.1 #5932 2018-03-21 19:20:50 +01:00
Olivier Goffart
424898603a mirall.desktop.in: Remove all the Translations comments
Relates to #5767
2018-03-21 15:03:45 +01:00
Jenkins for ownCloud
c1592e34c7 [tx-robot] updated from transifex 2018-03-21 11:56:01 +01:00
Christian Kamm
edacaae15f Merge remote-tracking branch 'origin/2.4' 2018-03-21 11:47:29 +01:00
Christian Kamm
29557ea550 Fix nautilus/nemo shell integration encoding issues #6393
The problem was that plain encode()/decode() in python2 use ascii
encoding, not utf8.
2018-03-21 11:25:37 +01:00
Jenkins for ownCloud
37a93dca63 [tx-robot] updated from transifex 2018-03-21 02:18:33 +01:00
Jenkins for ownCloud
b632b7e0fa [tx-robot] updated from transifex 2018-03-20 02:18:30 +01:00
Jenkins for ownCloud
fc8e3b0914 [tx-robot] updated from transifex 2018-03-19 02:18:32 +01:00
Jenkins for ownCloud
861d777899 [tx-robot] updated from transifex 2018-03-18 02:18:31 +01:00
Jenkins for ownCloud
ff3e3ce886 [tx-robot] updated from transifex 2018-03-17 02:18:31 +01:00
Dominik Schmidt
d69e9ebf46 Apply branding to crashreporter resources file 2018-03-16 16:59:01 +01:00
Dominik Schmidt
24bf1b3629 Define APPLICATION_ICON_NAME fallback only in one place 2018-03-16 16:59:01 +01:00
Dominik Schmidt
94b0c9f78e Fix crash reporter icon 2018-03-16 16:59:01 +01:00
Dominik Schmidt
567f7eb205 Apply branding to crashreporter resources file 2018-03-16 16:35:49 +01:00
Christian Kamm
a89508ba26 Minor header fixup
To make the IDE happy.
2018-03-16 13:41:57 +01:00
Jenkins for ownCloud
c3c8ab85ec [tx-robot] updated from transifex 2018-03-16 02:18:30 +01:00
Olivier Goffart
0bf0f92949 OwnSql: Fixup after feedback for #6388 2018-03-15 19:30:21 +01:00
Olivier Goffart
04f8d0f2bc OwnSql: Put the SQL queries next to their use.
This avoid haivng to modify 4 places when we want to add a query
2018-03-15 19:30:21 +01:00
Olivier Goffart
4584e5d3c5 OwnSql: Some refactoring
Use QByteArray for the query so we don't have to convert twice.
Automatically finish the query when the DB close, so we don't
have to call reset
2018-03-15 19:30:21 +01:00
Jenkins for ownCloud
d1c887d754 [tx-robot] updated from transifex 2018-03-15 02:18:32 +01:00
Olivier Goffart
bbf1843865 SyncEngine: remove the "CSync" wording from the error messages
They are confusing for the user.
Example in issue #6274
2018-03-14 10:25:45 +01:00
Olivier Goffart
b6aaa6fd2b CSync: Remove unused error codes
None of the removed ERRNO code were ever set.
So none of the removed error hapenned anymore
2018-03-14 10:25:45 +01:00
Olivier Goffart
0031e09410 CSync: reconcile never returns an error 2018-03-14 10:25:45 +01:00
Olivier Goffart
0071011ebf csync: remove CSYNC_PARAM_ERROR
It does not make sense to report such error to the user.
Its goal was to show invalid use of the csync API, but this is now done
with asserts.
2018-03-14 10:25:45 +01:00
Olivier Goffart
978a129eed csync: Simplify csync_walk_local_tree/csync_walk_remote_tree
Small refactoring
2018-03-14 10:25:45 +01:00
Jenkins for ownCloud
991f4faafb [tx-robot] updated from transifex 2018-03-14 02:18:31 +01:00
Jenkins for ownCloud
371acb296d [tx-robot] updated from transifex 2018-03-13 02:18:36 +01:00
Christian Kamm
86b30e36c2 Merge remote-tracking branch 'origin/2.4' 2018-03-12 10:24:25 +01:00
Jürgen Weigert
7132e88f8e removed germano0 as co-maintainer. 2018-03-11 12:53:39 +01:00
Jenkins for ownCloud
1119bcf539 [tx-robot] updated from transifex 2018-03-11 02:18:36 +01:00
Jenkins for ownCloud
d67018311f [tx-robot] updated from transifex 2018-03-10 02:18:34 +01:00
Dominik Schmidt
50c8ec8fd9 Bump Qt to 5.10.1 and openssl to 1.1.0g on AppVeyor 2018-03-09 12:19:44 +01:00
Jenkins for ownCloud
eaecec418e [tx-robot] updated from transifex 2018-03-09 02:18:35 +01:00
Michael Stingl
2e2ffca9e2 fixed 2.4.1 release date in ChangeLog 2018-03-08 16:16:40 +01:00
Jenkins for ownCloud
ab27bcacdf [tx-robot] updated from transifex 2018-03-08 02:18:36 +01:00
Jenkins for ownCloud
536a051460 [tx-robot] updated from transifex 2018-03-07 02:18:36 +01:00
Christian Kamm
427bb83f0d IssuesWidget: addItem performance improvement
Ensure adding a new item isn't usually O(n) by keeping track of which
items have associated issues.
2018-03-06 13:02:54 +01:00
Christian Kamm
faec059a9b IssuesWidget: Don't allow two issues for the same file/folder
This is intended to safeguard against invalidation bugs that cause the
same error to be added again for every sync run.
2018-03-06 13:02:54 +01:00
Christian Kamm
641eddfbdf INSTRUCTION_IGNORE now carries a direction
This allows IssuesWidget to selectively wipe only the 'Up' ignores
during selective local discovery.
2018-03-06 13:02:54 +01:00
Christian Kamm
61869bb65e ProtocolItem: Adjust the way data is stored again
The struct makes it easy to pack data and should consume less memory
overall.
2018-03-06 13:02:54 +01:00
Christian Kamm
797473ba1f SyncResult: Make sure the number of conflicts is correct #6226
If the SyncResult incorrectly believes that there are no conflicts, the
tray icon won't be correct and there will be no warning about unresolved
conflicts on the account.

Nevertheless, it's pretty awkward that the IssuesWidget is better
informed about pending conflicts than the Folder itself. This kind of
backwards data flow is very confusing.

Unfortunately the only alternative I see is to either keep track of
this information in two places (also in Folder), or create a common
data-holding class that can serve as a model instance for the issues
view as well as provide data directly to the Folder - which would
have been a much larger change.
2018-03-06 13:02:54 +01:00
Christian Kamm
f82d61ea19 SyncEngine: Make "local discovery?" question available
Also fix the minor bug that was mentioned and add tests.
2018-03-06 13:02:54 +01:00
Christian Kamm
ec281654ae Issues tab: Invalidate issues selectively #6226
Everything is invalidated later: after discovery, not before. In
addition entries that should only be invalidated when new local
discovery is done have that behavior now.
2018-03-06 13:02:54 +01:00
Christian Kamm
52dfe589ba ProgressInfo: Add information for local vs remote discovery 2018-03-06 13:02:54 +01:00
Christian Kamm
a5aebac6a7 slotFolderDiscovered: Fix 'local' always being false
It was unused, so no harm done.
2018-03-06 13:02:54 +01:00
Christian Kamm
13eb64584f Discovery: Error if properties are missing #6317 2018-03-06 13:01:53 +01:00
Jenkins for ownCloud
259a117db5 [tx-robot] updated from transifex 2018-03-06 02:18:36 +01:00
Jürgen Weigert
2041f1ace8 Update release_template.md 2018-03-05 15:58:56 +01:00
Jürgen Weigert
08f402d264 Update release_template.md 2018-03-05 15:36:33 +01:00
Jürgen Weigert
d8084e2b18 Update release_template.md 2018-03-05 15:29:09 +01:00
Jürgen Weigert
7d03e47fea Update release_template.md 2018-03-05 14:52:43 +01:00
Markus Goetz
f5f68c0bc0 ChangeLog: 2.4.1 had been released (..in branch) 2018-03-05 14:28:18 +01:00
Jenkins for ownCloud
167939a8c9 [tx-robot] updated from transifex 2018-03-05 02:18:37 +01:00
Jenkins for ownCloud
41ebfb635e [tx-robot] updated from transifex 2018-03-04 02:18:36 +01:00
Jenkins for ownCloud
017b8e9de3 [tx-robot] updated from transifex 2018-03-03 02:18:35 +01:00
Jenkins for ownCloud
6453c57979 [tx-robot] updated from transifex 2018-03-02 02:18:36 +01:00
Markus Goetz
7606184b31 Update release_template.md 2018-03-01 17:22:21 +01:00
Markus Goetz
5ff2b5b0a3 Update release_template.md 2018-03-01 17:13:39 +01:00
Olivier Goffart
7397565274 Propagator: remove a bunch of code related to the 'Shared' directory
This no longer exists since the owncloud server 7.0 which we no longer
allow to connect to
2018-03-01 14:48:00 +01:00
Olivier Goffart
4a19a8d644 ConnectionValidator: change the minimum server version
Forbit connection with server older than 7.0. These server did not have
permission.

Also warn for anything older than 9.1. 9.0 is end of life according to
https://github.com/owncloud/core/wiki/Maintenance-and-Release-Schedule
2018-03-01 14:48:00 +01:00
Jenkins for ownCloud
a01c73be19 [tx-robot] updated from transifex 2018-03-01 02:18:37 +01:00
Jenkins for ownCloud
f63737ecb0 [tx-robot] updated from transifex 2018-02-28 02:18:35 +01:00
Jenkins for ownCloud
dd87799a82 [tx-robot] updated from transifex 2018-02-27 02:19:02 +01:00
Olivier Goffart
302c60fe15 ConnectionValidator::Status use Q_ENUM
So no need to have a manual conversion to QString
This is only used in debug message anyway.
2018-02-26 16:11:46 +01:00
Olivier Goffart
22c7002d59 Move ClientProxy and ConnecitonValidator to gui
They are using the ConfigFile and are used to control
when to sync rather than for the sync itself
2018-02-26 16:11:46 +01:00
Olivier Goffart
9968142976 owncloudcmd: Do not overwrite the http timeout for json jobs
The AbstractNetworkJob already has a sensible timeout that depends
on an environment variable.
No need to overwrite that with some arbitrary value. (The connection
validator does that because it could cause problems if two connection
validator were to run at the same time. Not a problem here)
2018-02-26 16:11:46 +01:00
Olivier Goffart
75a6783a79 owncloudcmd: Do not read the proxy settings from the gui's config file
The proxy settings for the owncloudcmd client can be set via the
--httpproxy command line argument. owncloudcmd should not depends
on the gui's config
2018-02-26 16:11:46 +01:00
Olivier Goffart
18afe6a395 Folder: remove unused member 2018-02-26 16:11:46 +01:00
Jenkins for ownCloud
da6b515bfc [tx-robot] updated from transifex 2018-02-26 02:19:12 +01:00
Jenkins for ownCloud
f9a03fa288 [tx-robot] updated from transifex 2018-02-25 02:19:29 +01:00
Jenkins for ownCloud
a5c66cf289 [tx-robot] updated from transifex 2018-02-24 02:18:36 +01:00
Jenkins for ownCloud
41b908e293 [tx-robot] updated from transifex 2018-02-23 02:18:35 +01:00
Jenkins for ownCloud
6ffed87b08 [tx-robot] updated from transifex 2018-02-22 02:18:34 +01:00
Olivier Goffart
f6331951eb cmake: Remove references of now unused WITH_TESTING
Issue #6318
2018-02-21 11:28:31 +01:00
Olivier Goffart
7897b386b6 Utility::fsCasePreserving: remove UNIT_TESTING ifdef
Since the release package will be build with unit test, we don't
want to query the env variable at every call to fsCasePreserving.
So only test the env variable at startup.
And the testutility can still change the value.

(The env variable is still used from t8.pl and maybe smashbox)

Issue #6318
2018-02-21 11:28:31 +01:00
Jenkins for ownCloud
bd5ea43547 [tx-robot] updated from transifex 2018-02-21 02:18:51 +01:00
Markus Goetz
159899d3ba Update release_template.md 2018-02-20 20:30:32 +01:00
Christian Kamm
48dd8ed6c2 Partial local discovery: Fix scheduling logic
A recent patch that touched the condition for deciding whether a
periodic full local discovery is necessary accidentally inverted the
condition.
2018-02-20 18:07:28 +01:00
Markus Goetz
8ba27cb0f1 VERSION.cmake: This is 2.4.2 now 2018-02-20 12:13:58 +01:00
Markus Goetz
1ab8bb62ae ChangeLog: 2.4.1 2018-02-20 12:11:11 +01:00
Markus Goetz
6f8248ebfd test/testsyncengine: testNoLocalEncoding is for Linux 2018-02-20 11:26:11 +01:00
Christian Kamm
33306dcc38 Set launch-on-startup when the first account is set up
The previous code would disable it when the second account was
configured.

See #6347
2018-02-20 11:20:52 +01:00
Christian Kamm
ed2dfcf399 Conflicts with user name: Fix tests 2018-02-20 10:36:07 +01:00
Christian Kamm
6fc3bfc265 Conflicts: Add user name to conflict file name #6325
For the case of uploading conflict files only.
2018-02-20 10:10:34 +01:00
Christian Kamm
129b814931 SyncEngine: Use separate state for two unicode conversions
It's unlikely that there were interaction effects but still seems safer
to use different conversion state for the path and rename_path.
2018-02-20 10:01:47 +01:00
Jenkins for ownCloud
888818a9f7 [tx-robot] updated from transifex 2018-02-20 02:18:34 +01:00
Dominik Schmidt
aee72ae098 Merge pull request #6362 from dschmidt/fix-appveyor
Fix appveyor
2018-02-19 18:02:08 +01:00
Dominik Schmidt
766f8c2006 Pin craftmaster cache to qt version 2018-02-19 13:45:45 +01:00
Dominik Schmidt
d43439ebd9 Explicitly add owncloud blueprint repository 2018-02-19 10:58:42 +01:00
Dominik Schmidt
f7caf13873 Do not store artifacts on appveyor for now 2018-02-19 10:58:42 +01:00
Jenkins for ownCloud
d90229242e [tx-robot] updated from transifex 2018-02-19 02:18:34 +01:00
Jenkins for ownCloud
b14ba325d5 [tx-robot] updated from transifex 2018-02-18 02:18:35 +01:00
Jenkins for ownCloud
628e310501 [tx-robot] updated from transifex 2018-02-17 02:18:34 +01:00
Christian Kamm
6c1a73b67a SyncJournal: Clear etag filter before sync
Before, we only cleared the _avoidReadFromDbOnNextSyncFilter *after* a
sync which meant that we had to sync twice after selective sync setup.

Now, we clear the filter *before* a sync as well which allows the actual
next sync to write the correct etags to the db again - instead of only
the sync after that one.

Also expand on comments and rename _avoidReadFromDbOnNextSyncFilter to
_etagStorageFilter.
2018-02-16 11:39:19 +01:00
Christian Kamm
4a47f7e438 Merge remote-tracking branch 'origin/2.4' 2018-02-16 10:17:19 +01:00
Jenkins for ownCloud
131647442f [tx-robot] updated from transifex 2018-02-16 02:18:34 +01:00
ChrisEdS
01b79f2ff1 Fix ownCloud icon in unbranded installer
Fix ownCloud icon in unbranded installer
2018-02-15 12:07:24 +01:00
Christian Kamm
73062e21a3 SyncJournal: Don't use LIKE with paths
Paths can contain the wildcards % and _ and that would lead to odd
behavior.

This patch also clarifies the behavior of avoidReadFromDbOnNextSync()
which previously dependend on whether "foo/bar" or "foo/bar/" was
passed as input.

Possibly affects #6322
2018-02-15 09:56:43 +01:00
Christian Kamm
e7e6584cab Sharing: Use maximum allowed permissions for new share #6346
The client already computed the valid permissions, there was just a typo
that meant we didn't end up using them.
2018-02-15 09:10:47 +01:00
Jenkins for ownCloud
7373c68aeb [tx-robot] updated from transifex 2018-02-15 02:18:35 +01:00
Markus Goetz
13f1122c50 HTTP2: Only from Qt 5.9.4 #6285 2018-02-14 12:11:27 +01:00
Jenkins for ownCloud
ba5fb5aca7 [tx-robot] updated from transifex 2018-02-14 02:18:33 +01:00
Markus Goetz
c4543c58ea Release template: Add @Germano0 2018-02-13 15:09:52 +01:00
Jenkins for ownCloud
55a91926c1 [tx-robot] updated from transifex 2018-02-13 02:18:34 +01:00
Markus Goetz
b5e129aa6b Theme: Icon cache explanation 2018-02-12 17:11:58 +01:00
Markus Goetz
9fc175231d Notifications: Immediately request when getting account online 2018-02-12 09:01:00 +01:00
Markus Goetz
4dd0a75cce SettingsDialogMac: Also start timer for notifications 2018-02-12 09:01:00 +01:00
Jenkins for ownCloud
3cfd502f7e [tx-robot] updated from transifex 2018-02-12 02:18:34 +01:00
Jenkins for ownCloud
452a99f7d3 [tx-robot] updated from transifex 2018-02-11 02:18:34 +01:00
Jenkins for ownCloud
a9d37a0784 [tx-robot] updated from transifex 2018-02-10 02:18:51 +01:00
Christian Kamm
22b19636e9 Don't delete contents behind directory junctions #6322
QFileInfo::isSymLink() does detect reparse points that are symlinks but
returns false for junctions. The new function FileSystem::isJunction()
can detect those and is used to not recursively delete files inside
directories that are junctions.

See also https://bugreports.qt.io/browse/QTBUG-45344 and the
discussion in the PR https://codereview.qt-project.org/#/c/113019/.
2018-02-09 09:15:29 +01:00
Jenkins for ownCloud
6ee3310e2b [tx-robot] updated from transifex 2018-02-09 02:18:54 +01:00
Jenkins for ownCloud
065b1eed11 [tx-robot] updated from transifex 2018-02-08 02:18:53 +01:00
Markus Goetz
7860876b54 libcrashreporter-qt: Update submodule 2018-02-07 15:31:42 +01:00
Jenkins for ownCloud
dbc2d4a8b6 [tx-robot] updated from transifex 2018-02-07 02:18:35 +01:00
Markus Goetz
7eb2dc21af ServerNotificationHandler: Properly create "Dismiss" URL
Qt's JSON API is confusing, it doesn't convert to a string as one expects.
2018-02-06 20:28:00 +01:00
Markus Goetz
3aeeb11135 Fix submodule URL 2018-02-06 15:51:11 +01:00
Markus Goetz
e338739d83 Fix compile for libcrashreporter-qt on macOS 2018-02-06 15:22:19 +01:00
Jenkins for ownCloud
8fb9700869 [tx-robot] updated from transifex 2018-02-06 02:18:36 +01:00
Jenkins for ownCloud
f95e044206 [tx-robot] updated from transifex 2018-02-05 02:18:34 +01:00
Jenkins for ownCloud
795ab29514 [tx-robot] updated from transifex 2018-02-04 02:18:38 +01:00
Jenkins for ownCloud
72262b565e [tx-robot] updated from transifex 2018-02-03 02:18:36 +01:00
Markus Goetz
cedf72825b NO_SHIBBOLETH: Fix warning 2018-02-02 19:47:26 +01:00
Markus Goetz
06a86033c1 ChangeLog: Entries for 2.4.1 2018-02-02 16:30:49 +01:00
Jenkins for ownCloud
e17d5defe3 [tx-robot] updated from transifex 2018-02-02 02:18:34 +01:00
Jenkins for ownCloud
959d60e957 [tx-robot] updated from transifex 2018-02-01 02:18:34 +01:00
Samuel Alfageme
31f516f390 Fix 2.4.0 release date that somehow got lost 2018-01-31 13:43:13 +01:00
Jenkins for ownCloud
b6835186a3 [tx-robot] updated from transifex 2018-01-31 02:18:36 +01:00
Jenkins for ownCloud
c32ba4aee3 [tx-robot] updated from transifex 2018-01-30 02:18:36 +01:00
Olivier Goffart
e720f84005 owncloudcmd: Do not do the capability call when --nonshib is passed
https://github.com/owncloud/enterprise/issues/2391
2018-01-29 09:57:18 +01:00
Oleg Solovyov
ec26388826 - doc: linux-only setting 2018-01-29 09:41:42 +01:00
Oleg Solovyov
f0822d648d - add description for moveToTrash variable 2018-01-29 09:41:42 +01:00
Christian Kamm
14f60a4238 FolderStatusModel: Refresh folders on Problem sync #6337
We don't want to refresh too frequently. But Problem is very close to
Success and very common.
2018-01-29 09:36:35 +01:00
Christian Kamm
f8022bb248 Fix compiler warning
Stray semicolon
2018-01-29 09:31:31 +01:00
Jenkins for ownCloud
48ef2e4563 [tx-robot] updated from transifex 2018-01-29 02:18:36 +01:00
Jenkins for ownCloud
a0d9fc4354 [tx-robot] updated from transifex 2018-01-28 02:18:53 +01:00
Jenkins for ownCloud
e4b2d27c65 [tx-robot] updated from transifex 2018-01-27 02:18:50 +01:00
Christian Kamm
d1aacac294 Tray: Change icon for unresolved conflicts #6277 2018-01-26 13:33:33 +01:00
Olivier Goffart
e322bd706f SocketAPI: "Open in browser" and disable Share entries when sharing is disabled.
This adds "Open in browser" entry in the menu (Issue #5903)

Also mark the entries as disabled when the file is not yet on the server.
If re-sharing is not allowed for that file, a disabled explaination
entry is added to the menu.
If sharing is disabled globaly in the branding or in the server,
the share entry will not be present.
(Issues #4205 and #4608)

Meta issue #6292
2018-01-26 09:19:26 +01:00
Jenkins for ownCloud
c846a329a8 [tx-robot] updated from transifex 2018-01-26 02:18:34 +01:00
Olivier Goffart
de929eb566 Adjust the Move To Trash patch
(PR #6265)

 - Remove the UI completely
 - Move the #ifdef inside the FileSystem::moveToTrash function, so it is easier to
   implement on other platforms
 - Q_OS_UNIX includes mac, so we need to disable it. (not using Q_OS_LINUX because of
   other BSD that uses XDG spec as well
 - Translate the error messages
 - Add a couple of doc comments
2018-01-25 14:42:11 +01:00
Oleg Solovyov
c5d37dfedc Move remote-deleted files to trash
Squashed from https://github.com/owncloud/client/pull/6265

Linux only, Hidden option, disabled by default
2018-01-25 14:40:16 +01:00
Olivier Goffart
eae00f9969 Use std::chrono::milliseconds to represent milliseconds 2018-01-25 14:07:08 +01:00
Jenkins for ownCloud
c1bf90ddad [tx-robot] updated from transifex 2018-01-25 02:18:51 +01:00
Jenkins for ownCloud
b418bf6db4 [tx-robot] updated from transifex 2018-01-24 02:18:35 +01:00
252 changed files with 41064 additions and 27078 deletions

92
.drone.yml Normal file
View File

@@ -0,0 +1,92 @@
#
# We are building GCC with make and Clang with ninja, the combinations are more
# or less arbitrarily chosen. We just want to check that both compilers and both
# CMake generators work. It's unlikely that a specific generator only breaks
# with a specific compiler.
#
workspace:
base: /drone
path: src/github.com/owncloud/client
branches:
- master
- 2.5
- 2.4
clone:
git:
image: plugins/git
pull: true
tags: false
pipeline:
prepare-clang:
image: owncloudci/client:latest
pull: true
environment:
- LC_ALL=C.UTF-8
commands:
- mkdir clang-build
- cd clang-build
- cmake -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE="Debug" -DUNIT_TESTING=1 ..
building-clang:
image: owncloudci/client:latest
pull: true
environment:
- LC_ALL=C.UTF-8
commands:
- cd clang-build
- ninja -j4
testing-clang:
image: owncloudci/client:latest
pull: true
environment:
- LC_ALL=C.UTF-8
commands:
- cd clang-build
- useradd -m -s /bin/bash tester
- chown -R tester:tester .
- su-exec tester ctest --output-on-failure
prepare-gcc:
image: owncloudci/client:latest
pull: true
environment:
- LC_ALL=C.UTF-8
commands:
- mkdir gcc-build
- cd gcc-build
- cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE="Debug" -DUNIT_TESTING=1 ..
building-gcc:
image: owncloudci/client:latest
pull: true
environment:
- LC_ALL=C.UTF-8
commands:
- cd gcc-build
- make -j4
testing-gcc:
image: owncloudci/client:latest
pull: true
environment:
- LC_ALL=C.UTF-8
commands:
- cd gcc-build
- useradd -m -s /bin/bash tester
- chown -R tester:tester .
- su-exec tester ctest --output-on-failure
notify-slack:
image: plugins/slack
pull: true
secrets: [ slack_webhook ]
channel: desktop
when:
local: false
status: [ changed, failure ]
event: [ push ]

View File

@@ -16,6 +16,7 @@ Some weeks before the release:
* [ ] Ensure Windows Overlay DLLs are rebuilt
* [ ] Check nightly builds are up and running, that is Jenkins jobs ownCloud-client-linux, ownCloud-client-osx and ownCloud-client-win32 all green.
* [ ] Ensure Linux nightlies are built too for all distros https://build.opensuse.org/package/show/isv:ownCloud:community:nightly/owncloud-client
* Check if patches still apply in the linux packages
* [ ] Build branded clients through the scripting machine and smoke test one or two branded clients (especially with predefined url)
* [ ] Upload a nightly build of the windows version to virustotal.com
* Contact AV vendors whom's engine reports a virus
@@ -35,6 +36,7 @@ For all alphas, betas and RCs (Copy this section for each alpha/beta/rc):
* [ ] Add last updates to Changelog in the client source repository.
* [ ] Branch off a release branch called VERSION-rcX or VERSION-betaX (without v, v is for tags)
* [ ] Edit ```VERSION.cmake``` to set the suffix to beta1, beta2 etc. Commit the result to the release branch only
* [ ] Make sure to increase the version number of the branched of release, e.g. if you release 2.3.2 then you should change VERSION.cmake in 2.3 to 2.3.3 since that branch now will be 2.3.3
* [ ] Create build for using owncloud-client-trigger (uncheck the "nightly build" checkbox, use the proper dropdown for version suffix) for theme 'ownCloud'
* [ ] Create build for using owncloud-client-trigger (uncheck the "nightly build" checkbox, use the proper dropdown for version suffix) for theme 'testpilotcloud'
* [ ] Only now download the last created source .tar.xz and sign it with gpg. Copy the signature into a new .asc file. (timing issue because currently 'testpilotcloud' re-creates the source .tar.xz)
@@ -42,11 +44,12 @@ For all alphas, betas and RCs (Copy this section for each alpha/beta/rc):
* [ ] Mac: Perform smoke test (Install, make sure it does not explode, and check if all version indicators are correct)
* [ ] Win: Perform smoke test (Install, make sure it does not explode, and check if all version indicators are correct)
* [ ] Linux: Smoke test of one distro package (Install, make sure it does not explode, and check if all version indicators are correct)
* [ ] Linux: Run @SamuAlfageme 's magic Linux-test-all-packages-script
* [ ] Create a signed tag using ```git tag -u E94E7B37 tagname``` (https://github.com/owncloud/enterprise/wiki/Desktop-Signing-Knowledge)
* [ ] Create a pull request to the owncloud.org repository to update the install page (strings.php, page-desktop.php) and the changelog on owncloud.org. From now on download packages from the staging webserver.
* [ ] Inform community mailinglists devel@owncloud.org and testpilots@owncloud.org
* [ ] Inform packagers @dragotin (openSUSE) @hefee (Debian)
* [ ] Inform packagers @dragotin (openSUSE), @hefee (Debian), ??? (Fedora)
* [ ] Announce on https://central.owncloud.org
* [ ] Inform community mailinglists devel@owncloud.org and testpilots@owncloud.org (make sure to mention it is an rc). Link to the central post so discussion happens there.
* [ ] Check crash reporter
One week before the final release:
@@ -63,52 +66,53 @@ Day before final Release:
On Release Day (for final release):
* [ ] Add last updates to Changelog in the client source repository.
* [ ] Branch off a release branch called VERSION-rcX or VERSION-betaX (without v, v is for tags)
* [ ] Edit ```VERSION.cmake``` to set the suffix to beta1, beta2 etc. Commit the result to the release branch only
* [ ] Make sure to increase the version number of the branched of release, e.g. if you release 2.3.2 then you should change VERSION.cmake in 2.3 to 2.3.3 since that branch now will be 2.3.3
* [ ] Branch off a release branch called VERSION (without v, v is for tags)
* [ ] Edit ```VERSION.cmake``` to set the suffix to "" etc. Commit the result to the release branch only
* [ ] Create build for using owncloud-client-trigger (uncheck the "nightly build" checkbox, use the proper dropdown for version suffix) for theme 'ownCloud'
* [ ] Create build for using owncloud-client-trigger (uncheck the "nightly build" checkbox, use the proper dropdown for version suffix) for theme 'testpilotcloud'
* [ ] Only now download the last created source .tar.xz and sign it with gpg. Copy the signature into a new .asc file. (timing issue because currently 'testpilotcloud' re-creates the source .tar.xz) (https://github.com/owncloud/enterprise/wiki/Desktop-Signing-Knowledge)
* [ ] Branch isv:ownCloud:desktop to isv:ownCloud:desktop:client-X.Y.Z before overwriting https://github.com/owncloud/administration/blob/master/jenkins/obs_integration/obs-backup-prj.sh
* Check if patches still apply in the linux packages
* Update [OBS repository](https://build.opensuse.org/project/show?project=isv%3AownCloud%3Adesktop) `isv:ownCloud:desktop`
* [ ] Branch isv:ownCloud:desktop to isv:ownCloud:desktop:client-X.Y.Z before overwriting https://github.com/owncloud/administration/blob/master/jenkins/obs_integration/obs-backup-prj.sh (the linux packages will land in the :testing repository still)
```obs-backup-prj.sh isv:ownCloud:desktop isv:ownCloud:desktop:client-2.4.1 owncloud-client 2.4.1 # (if not already done)```
* [ ] Re-download Mac builds and check signature. Interactive in installer window
* [ ] Re-download Win build check signature. From Mac or Linux: ```osslsigncode verify ownCloud-version-setup.exe```
* [ ] Mac: Perform smoke test (Install, make sure it does not explode, and check if all version indicators are correct)
* [ ] Win: Perform smoke test (Install, make sure it does not explode, and check if all version indicators are correct)
* [ ] Linux: Smoke test of one distro package (Install, make sure it does not explode, and check if all version indicators are correct)
* [ ] Linux: Run @SamuAlfageme 's magic Linux-test-all-packages-script
* [ ] Linux: Re-enable OBS publishing on the project (check for accidentially disabled packages too)
* Let obs build and publish exactly once. then
* [ ] disable publishing (on the obs project!) and rebuild the owncloud-client package and all its dependencies.
* [ ] double-check that there are no _aggregatepac from other projects
* [ ] Create a signed tag using ```git tag -u E94E7B37 tagname``` (https://github.com/owncloud/enterprise/wiki/Desktop-Signing-Knowledge)
* [ ] Copy builds from ```testing``` to ```stable``` on download.owncloud.com, double check the download links. (make sure the .asc is there too)
* [ ] Create a pull request to the owncloud.org repository to update the install page (strings.php, page-desktop.php). From now on download packages from the staging webserver.
* [ ] Linux: Run @SamuAlfageme 's client-linux-tests Jenkins job (this tests only package installations!) Adjust REPO_URL in https://jenkins.int.owncloud.com/job/client-linux-tests/build (Better: gitlab?)
* [ ] Win/Mac Copy builds from ```testing``` to ```stable``` on download.owncloud.com, double check the download links. (make sure the .asc is there too)
* [ ] Linux: disable publishing on project isv:ownCloud:desktop
* [ ] Linux: Use https://github.com/owncloud/administration/blob/master/jenkins/obs_integration/obs-deepcopy-prj.sh to copy from isv:ownCloud:community:testing to isv:ownCloud:desktop
 ```obs-deepcopy-prj.sh isv:ownCloud:desktop:testing isv:ownCloud:desktop```
 ```obs-deepcopy-prj.sh isv:ownCloud:testpilot:testing isv:ownCloud:testpilot```
* [ ] Linux: Re-enable OBS publishing on the project after official release date and if all distros build (check for accidentially disabled packages too)
* [ ] Linux: Wait until everything is built and published, then disable publishing on project isv:ownCloud:desktop
* [ ] Create git signed tag in client repository using ```git tag -u E94E7B37 tagname``` (https://github.com/owncloud/enterprise/wiki/Desktop-Signing-Knowledge)
* [ ] Create a (draft) release on https://github.com/owncloud/client/releases
* [ ] Update https://owncloud.org/changelog/desktop-client/
* [ ] Update https://owncloud.org/download/#owncloud-desktop-client -> Download ownCloud -> click open 'Desktop Client', edit win/mac/lin, each all three tabs "Production", "Technical Preview" [disabled], "Test pilot"
* [ ] Announce on https://central.owncloud.org
* [ ] Announce on announcements@owncloud.org
* [ ] Inform packagers @dragotin (openSUSE) @hefee (Debian)
* [ ] Create git signed tag in client repository using ```git tag -u E94E7B37 tagname```
* [ ] Announce on announcements@owncloud.org Link to the central post so discussion happens there.
* [ ] Inform packagers @dragotin (openSUSE) @hefee (Debian) @Germano0 (Fedora)
* [ ] Send out Social (tweet, blog, other)
* [ ] Send out customer communication (if any)
* [ ] Inform GCX that the new version is released (gcx@owncloud.com)
* [ ] Inform release-coordination@owncloud.com
* [ ] Ensure marketing is aware (marketing@owncloud.com)
* [ ] Take pride and celebrate!
* [ ] Also update the testpilotcloud builds for that release version and make sure they show up on the download page
* [ ] Tell GCX to increment the minimum supported version for enterprise customers
* [ ] Check if minimum.supported.desktop.version (https://github.com/owncloud/core/blob/master/config/config.sample.php#L1152) needs to be updated in server
* [ ] Linux OBS: Update the testing repository to the latest stable version.
15 minutes after after release:
* [ ] Test all advertised download links to have the expected version
* [ ] Check for build errors in OBS
* [ ] Check for build errors in OBS, do
```obs-deepcopy-prj.sh isv:ownCloud:desktop isv:ownCloud:desktop:client-2.X.X```
* [ ] disable publishing in OBS to prevent that accidential rebuilds hit the end users.
A few days after the release (for final release)
* [ ] Review changes in the release branch, merge back into master
* [ ] check the crash reporter if auto update is a good idea or we need a new release
* [ ] Update the updater script ```clientupdater.php```
* [ ] Update the updater script ```clientupdater.php``` https://github.com/owncloud/enterprise/wiki/How-to-use-the-Client-Updater#updating-the-owncloud-hosted-updater
* [ ] Execute announced deprecations. Disable builds for deprecated platforms. Update accordingly: https://doc.owncloud.org/server/latest/admin_manual/installation/system_requirements.html#desktop
* [ ] Increment version number in nightly builds. Special case: after the last release in a branch, jump forward to the 'next release branch'... That may mean, this is nightly is the same as edge then.

3
.gitmodules vendored
View File

@@ -7,3 +7,6 @@
[submodule "src/3rdparty/libcrashreporter-qt"]
path = src/3rdparty/libcrashreporter-qt
url = git://github.com/dschmidt/libcrashreporter-qt.git
[submodule "doc/docs-themes"]
path = doc/docs-themes
url = https://github.com/owncloud/docs-themes.git

View File

@@ -1,37 +0,0 @@
sudo: required
language: cpp
services:
- docker
branches:
only:
- coverity_scan
before_install:
- sudo sh -c "echo 'deb http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/Ubuntu_14.04/ /' >> /etc/apt/sources.list.d/owncloud-client.list"
- sudo sh -c "echo 'deb-src http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/Ubuntu_14.04/ /' >> /etc/apt/sources.list.d/owncloud-client.list"
- wget http://download.opensuse.org/repositories/isv:ownCloud:desktop/Ubuntu_14.04/Release.key
- sudo apt-key add - < Release.key
- sudo apt-get update
- sudo apt-get -y build-dep owncloud-client
- checkout=$(git show-ref --head --hash head)
- cd ../
- wget https://scan.coverity.com/download/linux-64 --post-data "token=$token&project=owncloud%2Fmirall" -O coverity_tool.tgz
- mkdir coverity
- tar -xvf coverity_tool.tgz -C coverity --strip-components=1
- export PATH=$PATH:$PWD/coverity/bin/
- cd $TRAVIS_BUILD_DIR
install:
- cd ../
- mkdir client-build
- cd client-build
- cmake -DCMAKE_BUILD_TYPE="Debug" $TRAVIS_BUILD_DIR
- cov-build --dir cov-int make
- tar czvf client.tgz cov-int
- curl --form token=$token --form email=lukas@statuscode.ch --form file=@$PWD/client.tgz --form version="$checkout" --form description="$checkout" https://scan.coverity.com/builds?project=owncloud%2Fmirall
# Hack to stop processing
script: true

View File

@@ -5,12 +5,19 @@ project(client)
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(OEM_THEME_DIR "" CACHE STRING "Define directory containing a custom theme")
if ( EXISTS ${OEM_THEME_DIR}/OEM.cmake )
include ( ${OEM_THEME_DIR}/OEM.cmake )
else ()
include ( ${CMAKE_SOURCE_DIR}/OWNCLOUD.cmake )
endif()
# Default suffix if the theme doesn't define one
if(NOT DEFINED APPLICATION_VIRTUALFILE_SUFFIX)
set(APPLICATION_VIRTUALFILE_SUFFIX "${APPLICATION_SHORTNAME}_virtual" CACHE STRING "Virtual file suffix (not including the .)")
endif()
# need this logic to not mess with re/uninstallations via macosx.pkgproj
if(${APPLICATION_REV_DOMAIN} STREQUAL "com.owncloud.desktopclient")
set(APPLICATION_REV_DOMAIN_INSTALLER "com.ownCloud.client")
@@ -188,7 +195,7 @@ if(BUILD_CLIENT)
endif()
if (NOT DEFINED APPLICATION_ICON_NAME)
set(APPLICATION_ICON_NAME ${APPLICATION_SHORTNAME})
set(APPLICATION_ICON_NAME "${APPLICATION_SHORTNAME}")
endif()
include(OwnCloudCPack.cmake)
@@ -211,9 +218,6 @@ endif()
file( GLOB TRANS_FILES ${CMAKE_SOURCE_DIR}/translations/client_*.ts)
set(TRANSLATIONS ${TRANS_FILES})
# Make sure we set this before recursing into child folders.
set(WITH_TESTING ${UNIT_TESTING})
if(BUILD_CLIENT)
add_subdirectory(src)
if(NOT BUILD_LIBRARIES_ONLY)

106
ChangeLog
View File

@@ -1,7 +1,111 @@
ChangeLog
=========
version 2.4.0 (2017-12-XX)
version 2.5.0 (2018-06-xx)
* Local discovery: Speed up by skipping directories without changes reported by the file system watcher.
* Windows: Add sync folders to Explorer's navigation pane (#5295)
* Conflicts: Change conflict file naming scheme
* Conflicts: Add user name to conflict file name (#6325)
* ConnectionValidator: change the minimum server version to 7.0
* ConnectionValidator: Warn when the server version is less than 9.1
* Experimental option to create virtual files and download contents on demand ("placeholders")
* Experimental option to upload conflict files (#4557)
* Wizard: Remove the "Skip folder config" button and instead add a radio button (#3664)
* Sharing: Add "copy public link" to menu (#6356)
* Protocol: Introduce context menu with "open in browser" (#6121)
* Shell integration: Add "Open in browser" entry in the explorer menu (#5903)
* Sync journal: Fix crash when unmounting a drive while a sync is running (#6049)
* Client certs: Improve error message (#6128)
* User shares: Show avatars
* Settings: Hide selective sync buttons while disconnected (#5809)
* Excludes: Optimize further the matching of exclude files using regular expression
* Don't use Qt deprecated API now that we required Qt 5.6
* Windows: Update Overlay Icon naming
* SyncEngine: Recover when the PUT reply (or chunkin's MOVE) is lost (#5106)
* Config: Look for exclude file in a relative path.
* Config: Versionize settings
* Credentials: Re-try on Linux if daemon not running (#4274, #6522)
* Windows: Fixed MSVC build and compiler bugs
* Proxy: Hostname validation and reconnection on setting change (#6140)
* owncloudcmd: Set proxy earlier (#6281)
* Exclude regex: Restore old matching on Windows (#6245)
* Build system: Modernize the CMakeLists.txt files
* Use standard png2ico
* Sync: Deal with file/folder conflicts (#6312)
* Protocol: Correct sorting by size (#6326)
* SocketAPI: dynamic action menu
* Hidden option to move remote-deleted files to trash (#6265)
* Tray: Change icon for unresolved conflicts (#6277)
* FolderStatusModel: Refresh folders on Problem sync (#6337)
* SyncJournal: Clear etag filter before sync
* SyncEngine: Use separate state for two unicode conversions
* Conflicts: Add documentation link to conflicts listing (#6396)
* owncloudcmd: Do not read the proxy settings from the gui's config file
* Discovery: Error if properties are missing (#6317)
* ProgressInfo: Add information for local vs remote discovery
* Issues tab: Invalidate issues selectively (#6226)
* SyncResult: Make sure the number of conflicts is correct (#6226)
* IssuesWidget: Don't allow two issues for the same file/folder
* IssuesWidget: addItem performance improvement
* Remove the "CSync" wording from the error messages
* Apply branding to crashreporter resources file
* Dolphin plugin: fall back if $XDG_RUNTIME_DIR is empty
* SslButton: Add HTTP/2 info (#3146)
* propagateuploadv1: Fixed an assert with ownCloud 5
* Folder: normalize the local path. (#4424)
* SslButton: Improve speed (especially on macOS) (#6031)
* Blacklisting must prevent parent etag updates (#6411)
* FolderStatusModel: fix potential assert
* Nautilus integration: Not a ColumnProvider
* Nautilus integration: Fix python3 compatibility (#6406)
* Conflicts: Change tags to be more user friendly (#6365)
* Notify if an explicitly excluded folder is created (#6222)
* Theme: unify ownCloudTheme and Theme classes
* Share link: Update permission wording (#6192)
* SyncJournalDb::setSelectiveSyncList: Always use a transaction (#6431)
* Folders: Use "Problem" icon for unresolved conflicts (#6277)
* macOS: Unload the Finder extension on exit (#5382, #3819)
* LogDir: Go to new file on Problem/Abort too (#6442)
* LogDir: Compress log when switching files (#6442)
* Logging: Add persistent auto-logdir option (#6442)
* .owncloudsynclog: Allow 10 MB of size (#6420)
* .owncloudsynclog: Persist X-Request-ID for correlation with server (#6420)
* Notifications: Lower hiding timeout
* Download: Use the <s:message> from the reply in the error message (#6459)
* Notifications: Also have clickable link (#6236)
* UI: High-DPI layout fixes
* Network settings: Better warnings about bad configuration (#5885)
* Share dialog: Allow opening it if the file's contents are still syncing (#4608)
* Share dialog: Don't hide account settings when opening it (#6185)
* Share dialog: Remove odd grey square on OSX (#5774)
* Share dialog: Preserve the entered password when unrelated changes are done (#6512)
* Folder watcher: Show a notification if it becomes unreliable (#6119)
* Ignore editor: Preserve comments in the exclude list file
* Propagation: Do not abort a sync if the server closes the connection (#6516)
* Propagation: Increase the timeout for the last MOVE/PUT for huge files (#6527)
* Update bundled sqlite version to 3.23.1
* Auto Updater: Drop down menu to switch update channels
version 2.4.1 (2018-03-05)
* Ignore files with file names that can't be encoded for the filesystem (#6287, #5676, #5719)
* Issues: Speed up insertion and add hard upper limit (#6272)
* Notifications: Fix "Dismiss" action
* Notifications: Fix timer invocation on macOS
* Notifications: Immediately poll when account online
* Protocol: Remove entries for auto resolved conflicts (#6316)
* owncloudcmd: Set proxy before capabilities call (#6281)
* owncloudcmd: Do not do the capability call when --nonshib is passed
* Avatars: Use old location for servers <10 (#6279)
* Link shares: Change default share name (#6298)
* Sharing: Use maximum allowed permissions for new share (#6346)
* Nautilus integration: Work with python2 and python3
* Windows: Don't delete contents behind directory junctions (#6322)
* SyncJournal: Don't use LIKE with paths (#6322)
* Fix setting launch-on-startup when the first account is set up (#6347)
* HTTP2: Only allow with Qt 5.9.4 (#6285)
* Crash fixes
version 2.4.0 (2017-12-21)
* If you're using 2.4.0 alpha1, please upgrade as previous alphas/rcs had an issue with hidden files and renames!
* OAuth2 authentication support by opening external browser (#5668)
* Shibboleth: Change to use OAuth2 if supported (#6198)

View File

@@ -5,6 +5,7 @@ set( APPLICATION_DOMAIN "owncloud.com" )
set( APPLICATION_VENDOR "ownCloud" )
set( APPLICATION_UPDATE_URL "https://updates.owncloud.com/client/" CACHE string "URL for updater" )
set( APPLICATION_ICON_NAME "owncloud" )
set( APPLICATION_VIRTUALFILE_SUFFIX "owncloud" CACHE STRING "Virtual file suffix (not including the .)")
set( LINUX_PACKAGE_SHORTNAME "owncloud" )
@@ -19,4 +20,4 @@ set( MAC_INSTALLER_BACKGROUND_FILE "${CMAKE_SOURCE_DIR}/admin/osx/installer-back
option( WITH_CRASHREPORTER "Build crashreporter" OFF )
set( CRASHREPORTER_SUBMIT_URL "https://crash-reports.owncloud.com/submit" CACHE string "URL for crash reporter" )
set( CRASHREPORTER_ICON ":/owncloud-icon.png" )

View File

@@ -12,7 +12,7 @@ with your computer.
### Binary packages
* Refer to the download page https://owncloud.org/install/#install-clients
* Refer to the download page https://owncloud.org/download/#owncloud-desktop-client
### Source code
@@ -27,18 +27,6 @@ https://github.com/owncloud/client.
[Building the Client](http://doc.owncloud.org/desktop/2.3/building.html)
in the ownCloud Desktop Client manual.
## Maintainers and Contributors
The maintainers of this repository are:
* Klaas Freitag <freitag@owncloud.com>
* Daniel Molkentin <danimo@owncloud.com>
* Markus Goetz <guruz@owncloud.com>
* Olivier Goffart <ogoffart@owncloud.com>
ownCloud Desktop Client is developed by the ownCloud community and receives
patches from a variety of authors.
## Reporting issues and contributing
If you find any bugs or have any suggestion for improvement, please
@@ -56,6 +44,23 @@ If you want to contact us, e.g. before starting a more complex feature,
you can join us at
[#owncloud-client-dev](irc://irc.freenode.net/#owncloud-client-dev).
## Maintainers and Contributors
The current maintainers of this repository are:
* Markus Goetz <guruz@owncloud.com>
* Olivier Goffart <ogoffart@owncloud.com>
* Christian Kamm <mail@ckamm.de>
ownCloud Desktop Client is developed by the ownCloud community and [receives
patches from a variety of authors](https://github.com/owncloud/client/graphs/contributors).
Past maintainers:
* Klaas Freitag <freitag@owncloud.com>
* Daniel Molkentin <daniel@molkentin.de>
* Andreas Schneider <asn@cryptomilk.org>
## License
This program is free software; you can redistribute it and/or modify

View File

@@ -1,11 +1,11 @@
set( MIRALL_VERSION_MAJOR 2 )
set( MIRALL_VERSION_MINOR 5 )
set( MIRALL_VERSION_PATCH 0 )
set( MIRALL_VERSION_YEAR 2017 )
set( MIRALL_VERSION_YEAR 2018 )
set( MIRALL_SOVERSION 0 )
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
set( MIRALL_VERSION_SUFFIX "git") #e.g. beta1, beta2, rc1
set( MIRALL_VERSION_SUFFIX "alpha") #e.g. beta1, beta2, rc1
endif( NOT DEFINED MIRALL_VERSION_SUFFIX )
if( NOT DEFINED MIRALL_VERSION_BUILD )

View File

@@ -11,7 +11,8 @@ else()
set(MAC_INSTALLER_DO_CUSTOM_BACKGROUND "0")
endif()
configure_file(create_mac_pkg.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/create_mac.sh)
configure_file(macosx.pkgproj ${CMAKE_CURRENT_BINARY_DIR}/macosx.pkgproj)
find_package(Qt5 5.6 COMPONENTS Core REQUIRED)
configure_file(create_mac.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/create_mac.sh)
configure_file(macosx.pkgproj.cmake ${CMAKE_CURRENT_BINARY_DIR}/macosx.pkgproj)
configure_file(pre_install.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/pre_install.sh)
configure_file(post_install.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/post_install.sh)

View File

@@ -23,7 +23,7 @@ identity="$3"
prjfile=$build_path/admin/osx/macosx.pkgproj
# The name of the installer package
installer="@APPLICATION_SHORTNAME@-@MIRALL_VERSION_FULL@@MIRALL_VERSION_SUFFIX@"
installer="@APPLICATION_SHORTNAME@-qt@Qt5Core_VERSION@-@MIRALL_VERSION_FULL@@MIRALL_VERSION_SUFFIX@"
installer_file="$installer.pkg"
installer_file_tar="$installer.pkg.tar"
installer_file_tar_bz2="$installer.pkg.tar.bz2"

View File

@@ -22,6 +22,7 @@ import subprocess
import commands
import sys
from glob import glob
from distutils.version import LooseVersion
def QueryQMake(attrib):
return subprocess.check_output([qmake_path, '-query', attrib]).rstrip('\n')
@@ -92,6 +93,8 @@ commands.append(['mkdir', '-p', resources_dir])
plugins_dir = os.path.join(bundle_dir, 'Contents', 'PlugIns')
binaries = [i for i in glob(os.path.join(bundle_dir, 'Contents', 'MacOS', "*")) if is_exe(i)];
qt_version = QueryQMake('QT_VERSION')
print "Using Qt", qt_version
fixed_libraries = []
fixed_frameworks = []
@@ -334,9 +337,19 @@ def FindQtPlugin(name):
for binary in binaries:
FixBinary(binary)
if LooseVersion(qt_version) >= LooseVersion("5.10.0"):
QT_PLUGINS.append('styles/libqmacstyle.dylib')
for plugin in QT_PLUGINS:
FixPlugin(FindQtPlugin(plugin), os.path.dirname(plugin))
if LooseVersion(qt_version) >= LooseVersion("5.10.0"):
args = ['plutil', '-insert', 'LSMinimumSystemVersion', '-string', '10.10.0', os.path.join(bundle_dir, 'Contents', 'Info.plist')]
commands.append(args)
else:
args = ['plutil', '-insert', 'LSMinimumSystemVersion', '-string', '10.7.0', os.path.join(bundle_dir, 'Contents', 'Info.plist')]
commands.append(args)
if len(sys.argv) <= 2:
print 'Will run %d commands:' % len(commands)
for command in commands:

View File

@@ -579,7 +579,9 @@
</dict>
</dict>
<key>INSTALLATION TYPE</key>
<integer>0</integer>
<integer>1</integer>
<key>MODE</key>
<integer>1</integer>
</dict>
<key>INSTALLATION_STEPS</key>
<array>
@@ -699,7 +701,7 @@
<key>BUILD_PATH</key>
<dict>
<key>PATH</key>
<string>../install/.</string>
<string>@CMAKE_INSTALL_PREFIX@/.</string>
<key>PATH_TYPE</key>
<integer>3</integer>
</dict>

View File

@@ -1,12 +1,16 @@
#!/bin/sh
osascript << EOF
# Check if Finder is running (for systems with Finder disabled)
finder_status=`ps aux | grep "/System/Library/CoreServices/Finder.app/Contents/MacOS/Finder" | grep -v "grep"`
if ! [ "$finder_status" == "" ] ; then # Finder is running
osascript << EOF
tell application "Finder"
activate
select the last Finder window
reveal POSIX file "/Applications/@APPLICATION_EXECUTABLE@.app"
end tell
EOF
fi
# Always enable the new 10.10 finder plugin if available
if [ -x "$(command -v pluginkit)" ]; then

View File

@@ -1,40 +0,0 @@
#!/bin/sh -x
[ "$#" -lt 2 ] && echo "Usage: sign_dmg.sh <dmg> <identity>" && exit
src_dmg="$1"
tmp_dmg="writable_$1"
signed_dmg="signed_$1"
identity="$2"
QT_FMWKS=`basename ${TMP_APP}/Contents/Frameworks`/Qt*
QT_FMWK_VERSION="5"
fix_frameworks() {
TMP_APP=$1
QT_FMWK_PATH=$2
QT_FMWKS=$3/Qt*.framework
echo "Patching Qt frameworks..."
for FMWK in $QT_FMWKS; do
FMWK_NAME=`basename -s .framework $FMWK`
FMWK=`basename $FMWK`
FMWK_PATH="${TMP_APP}/Contents/Frameworks/${FMWK}"
mkdir -p "${FMWK_PATH}/Versions/${QT_FMWK_VERSION}/Resources/"
cp -avf "${QT_FMWK_PATH}/${FMWK}/Contents/Info.plist" "${FMWK_PATH}/Versions/${QT_FMWK_VERSION}/Resources"
(cd "${FMWK_PATH}" && ln -sf "Versions/${QT_FMWK_VERSION}/Resources" "Resources")
perl -pi -e "s/${FMWK_NAME}_debug/${FMWK_NAME}/" "${FMWK_PATH}/Resources/Info.plist"
done
}
mount="/Volumes/$(basename "$src_dmg"|sed 's,-\([0-9]\)\(.*\),,')"
test -e "$tmp_dmg" && rm -rf "$tmp_dmg"
hdiutil convert "$src_dmg" -format UDRW -o "$tmp_dmg"
hdiutil attach "$tmp_dmg"
pushd "$mount"
fix_frameworks "$mount"/*.app `qmake -query QT_INSTALL_LIBS` "$mount"/*.app/Contents/Frameworks
codesign -s "$identity" --deep "$mount"/*.app
popd
diskutil eject "$mount"
test -e "$signed_dmg" && rm -rf "$signed_dmg"
hdiutil convert "$tmp_dmg" -format UDBZ -o "$signed_dmg"

View File

@@ -0,0 +1,120 @@
; fileassoc.nsh
; File association helper macros
; Written by Saivert
; See http://nsis.sourceforge.net/FileAssoc
;
; Features automatic backup system and UPDATEFILEASSOC macro for
; shell change notification.
;
; |> How to use <|
; To associate a file with an application so you can double-click it in explorer, use
; the APP_ASSOCIATE macro like this:
;
; Example:
; !insertmacro APP_ASSOCIATE "txt" "myapp.textfile" "Description of txt files" \
; "$INSTDIR\myapp.exe,0" "Open with myapp" "$INSTDIR\myapp.exe $\"%1$\""
;
; Never insert the APP_ASSOCIATE macro multiple times, it is only ment
; to associate an application with a single file and using the
; the "open" verb as default. To add more verbs (actions) to a file
; use the APP_ASSOCIATE_ADDVERB macro.
;
; Example:
; !insertmacro APP_ASSOCIATE_ADDVERB "myapp.textfile" "edit" "Edit with myapp" \
; "$INSTDIR\myapp.exe /edit $\"%1$\""
;
; To have access to more options when registering the file association use the
; APP_ASSOCIATE_EX macro. Here you can specify the verb and what verb is to be the
; standard action (default verb).
;
; And finally: To remove the association from the registry use the APP_UNASSOCIATE
; macro. Here is another example just to wrap it up:
; !insertmacro APP_UNASSOCIATE "txt" "myapp.textfile"
;
; |> Note <|
; When defining your file class string always use the short form of your application title
; then a period (dot) and the type of file. This keeps the file class sort of unique.
; Examples:
; Winamp.Playlist
; NSIS.Script
; Photoshop.JPEGFile
;
; |> Tech info <|
; The registry key layout for a file association is:
; HKEY_CLASSES_ROOT
; <applicationID> = <"description">
; shell
; <verb> = <"menu-item text">
; command = <"command string">
;
!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND
; Backup the previously associated file class
ReadRegStr $R0 HKCR ".${EXT}" ""
WriteRegStr HKCR ".${EXT}" "${FILECLASS}_backup" "$R0"
WriteRegStr HKCR ".${EXT}" "" "${FILECLASS}"
WriteRegStr HKCR "${FILECLASS}" "" `${DESCRIPTION}`
WriteRegStr HKCR "${FILECLASS}\DefaultIcon" "" `${ICON}`
WriteRegStr HKCR "${FILECLASS}\shell" "" "open"
WriteRegStr HKCR "${FILECLASS}\shell\open" "" `${COMMANDTEXT}`
WriteRegStr HKCR "${FILECLASS}\shell\open\command" "" `${COMMAND}`
!macroend
!macro APP_ASSOCIATE_EX EXT FILECLASS DESCRIPTION ICON VERB DEFAULTVERB SHELLNEW COMMANDTEXT COMMAND
; Backup the previously associated file class
ReadRegStr $R0 HKCR ".${EXT}" ""
WriteRegStr HKCR ".${EXT}" "${FILECLASS}_backup" "$R0"
WriteRegStr HKCR ".${EXT}" "" "${FILECLASS}"
StrCmp "${SHELLNEW}" "0" +2
WriteRegStr HKCR ".${EXT}\ShellNew" "NullFile" ""
WriteRegStr HKCR "${FILECLASS}" "" `${DESCRIPTION}`
WriteRegStr HKCR "${FILECLASS}\DefaultIcon" "" `${ICON}`
WriteRegStr HKCR "${FILECLASS}\shell" "" `${DEFAULTVERB}`
WriteRegStr HKCR "${FILECLASS}\shell\${VERB}" "" `${COMMANDTEXT}`
WriteRegStr HKCR "${FILECLASS}\shell\${VERB}\command" "" `${COMMAND}`
!macroend
!macro APP_ASSOCIATE_ADDVERB FILECLASS VERB COMMANDTEXT COMMAND
WriteRegStr HKCR "${FILECLASS}\shell\${VERB}" "" `${COMMANDTEXT}`
WriteRegStr HKCR "${FILECLASS}\shell\${VERB}\command" "" `${COMMAND}`
!macroend
!macro APP_ASSOCIATE_REMOVEVERB FILECLASS VERB
DeleteRegKey HKCR `${FILECLASS}\shell\${VERB}`
!macroend
!macro APP_UNASSOCIATE EXT FILECLASS
; Backup the previously associated file class
ReadRegStr $R0 HKCR ".${EXT}" `${FILECLASS}_backup`
WriteRegStr HKCR ".${EXT}" "" "$R0"
DeleteRegKey HKCR `${FILECLASS}`
!macroend
!macro APP_ASSOCIATE_GETFILECLASS OUTPUT EXT
ReadRegStr ${OUTPUT} HKCR ".${EXT}" ""
!macroend
; !defines for use with SHChangeNotify
!ifdef SHCNE_ASSOCCHANGED
!undef SHCNE_ASSOCCHANGED
!endif
!define SHCNE_ASSOCCHANGED 0x08000000
!ifdef SHCNF_FLUSH
!undef SHCNF_FLUSH
!endif
!define SHCNF_FLUSH 0x1000
!macro UPDATEFILEASSOC
; Using the system.dll plugin to call the SHChangeNotify Win32 API function so we
; can update the shell.
System::Call "shell32::SHChangeNotify(i,i,i,i) (${SHCNE_ASSOCCHANGED}, ${SHCNF_FLUSH}, 0, 0)"
!macroend
;EOF

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -9,6 +9,9 @@ Command=craft
#Values need to be overwritten to create a chache
UseCache = True
CreateCache = False
QtVersion = 5.10.1
OpenSslVersion = 1.1.0h
CacheVersion = Qt_${Variables:QtVersion}-1
# Settings applicable for all Crafts matrices
# Settings are Category/key=value
@@ -25,6 +28,7 @@ ShortPath/JunctionDir = C:\CM-SP\
Packager/CacheDir = ${Variables:Root}\cache
Packager/UseCache = ${Variables:UseCache}
Packager/CreateCache = ${Variables:CreateCache}
Packager/CacheVersion = ${Variables:CacheVersion}
; Packager/RepositoryUrl = https://files.kde.org/craft/
Packager/PackageType = PortablePackager
Packager/RepositoryUrl = http://ftp.acc.umu.se/mirror/kde.org/files/craft/master/
@@ -35,7 +39,8 @@ ContinuousIntegration/Enabled = True
# don't try to pip install on the ci
python-modules.ignored = True
libs/qt5.version = 5.9.3
libs/qt5.version = ${Variables:QtVersion}
win32libs/openssl.version = ${Variables:OpenSslVersion}
craft/craft-core.version = master
[windows-msvc2017_64-cl]

View File

@@ -20,6 +20,7 @@ install:
& cmd /C "git clone -q --depth=1 git://anongit.kde.org/craftmaster.git C:\CraftMaster\CraftMaster 2>&1"
craft $env:TARGET -i craft
craft $env:TARGET --add-blueprint-repository [git]https://github.com/owncloud/craft-blueprints-owncloud.git
craft $env:TARGET --install-deps owncloud-client
build_script:
@@ -30,11 +31,6 @@ after_build:
- ps: |
craft $env:TARGET --src-dir $env:APPVEYOR_BUILD_FOLDER --package owncloud-client
on_finish:
- ps: |
Get-ChildItem $env:USERPROFILE\.craft\* | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
test_script:
- ps: |
craft $env:TARGET --src-dir $env:APPVEYOR_BUILD_FOLDER --test owncloud-client
@@ -45,6 +41,3 @@ environment:
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
- TARGET: windows-msvc2017_64-cl
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
artifacts:
- path: binaries/*

2
binary

Submodule binary updated: 3425fab2c6...39bfc426e5

View File

@@ -20,7 +20,7 @@
<file>resources/lock-https.png</file>
<file>resources/lock-https@2x.png</file>
<file>resources/account.png</file>
<file>resources/more.png</file>
<file>resources/more.svg</file>
<file>resources/delete.png</file>
<file>resources/bell.png</file>
</qresource>

View File

@@ -164,12 +164,18 @@ function(ecm_add_app_icon appsources)
endif()
set(windows_icons ${icons_at_16px}
${icons_at_32px}
${icons_at_48px}
${icons_at_64px}
${icons_at_128px})
if (NOT windows_icons)
set(windows_icons_classic ${icons_at_16px}
${icons_at_24px}
${icons_at_32px}
${icons_at_48px}
${icons_at_64px}
${icons_at_128px})
set(windows_icons_modern ${windows_icons_classic}
${icons_at_256px}
${icons_at_512px}
${icons_at_1024px})
if (NOT (windows_icons_modern OR windows_icons_classic))
message(AUTHOR_WARNING "No icons suitable for use on Windows provided")
endif()
@@ -180,30 +186,19 @@ function(ecm_add_app_icon appsources)
endif()
set (_outfilename "${CMAKE_CURRENT_BINARY_DIR}/${_outfilebasename}")
if (WIN32 AND windows_icons)
if (WIN32 AND (windows_icons_modern OR windows_icons_classic))
set(saved_CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_FIND_MODULE_DIR})
find_package(Png2Ico)
find_package(IcoTool)
set(CMAKE_MODULE_PATH "${saved_CMAKE_MODULE_PATH}")
if (Png2Ico_FOUND)
if (Png2Ico_HAS_RCFILE_ARGUMENT)
add_custom_command(
OUTPUT "${_outfilename}.rc" "${_outfilename}.ico"
COMMAND Png2Ico::Png2Ico
ARGS
--rcfile "${_outfilename}.rc"
"${_outfilename}.ico"
${windows_icons}
DEPENDS ${windows_icons}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)
else()
function(create_windows_icon_and_rc command args deps)
add_custom_command(
OUTPUT "${_outfilename}.ico"
COMMAND Png2Ico::Png2Ico
ARGS "${_outfilename}.ico" ${windows_icons}
DEPENDS ${windows_icons}
COMMAND ${command}
ARGS ${args}
DEPENDS ${deps}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)
# this bit's a little hacky to make the dependency stuff work
@@ -215,10 +210,65 @@ function(ecm_add_app_icon appsources)
DEPENDS "${_outfilename}.ico"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
)
endif()
endfunction()
if (IcoTool_FOUND)
set(icotool_args "-c -o \"${_outfilename}.ico\"")
# According to https://stackoverflow.com/a/40851713/2886832
# Windows always chooses the first icon above 255px, all other ones will be ignored
set(maxSize 0)
foreach(size 256 512 1024)
if(icons_at_${size}px)
set(maxSize "${size}")
endif()
endforeach()
foreach(size 16 32 48 64 128 ${maxSize})
if(NOT icons_at_${size}px)
continue()
endif()
set(icotool_icon_arg "")
if(size STREQUAL "${maxSize}")
# maxSize icon needs to be included as raw png
list(APPEND icotool_args "-r")
endif()
foreach(icon ${icons_at_${size}px})
list(APPEND icotool_args "${icons_at_${size}px}")
endforeach()
endforeach()
create_windows_icon_and_rc(IcoTool::IcoTool "${icotool_args}" "${windows_icons_modern}")
set(${appsources} "${${appsources}};${_outfilename}.rc" PARENT_SCOPE)
# standard png2ico has no rcfile argument
elseif(Png2Ico_FOUND AND NOT Png2Ico_HAS_RCFILE_ARGUMENT AND windows_icons_classic)
set(png2ico_args)
list(APPEND png2ico_args "${_outfilename}.ico")
list(APPEND png2ico_args "${windows_icons_classic}")
create_windows_icon_and_rc(Png2Ico::Png2Ico "${png2ico_args}" "${windows_icons_classic}")
set(${appsources} "${${appsources}};${_outfilename}.rc" PARENT_SCOPE)
# png2ico from kdewin provides rcfile argument
elseif(Png2Ico_FOUND AND windows_icons_classic)
add_custom_command(
OUTPUT "${_outfilename}.rc" "${_outfilename}.ico"
COMMAND Png2Ico::Png2Ico
ARGS
--rcfile "${_outfilename}.rc"
"${_outfilename}.ico"
${windows_icons_classic}
DEPENDS ${windows_icons_classic}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)
set(${appsources} "${${appsources}};${_outfilename}.rc" PARENT_SCOPE)
# else none of the supported tools was found
else()
message(WARNING "Unable to find the png2ico utility - application will not have an application icon!")
message(WARNING "Unable to find the png2ico or icotool utilities or icons in matching sizes - application will not have an application icon!")
endif()
elseif (APPLE AND mac_icons)
# first generate .iconset directory structure, then convert to .icns format using the Mac OS X "iconutil" utility,

View File

@@ -0,0 +1,27 @@
# Copyright 2017 Vincent Pinon <vpinon@kde.org>
include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake)
ecm_find_package_version_check(IcoTool)
find_program(IcoTool_EXECUTABLE NAMES icotool)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(IcoTool
FOUND_VAR
IcoTool_FOUND
REQUIRED_VARS
IcoTool_EXECUTABLE
)
mark_as_advanced(IcoTool_EXECUTABLE)
if (IcoTool_FOUND)
if (NOT TARGET IcoTool::IcoTool)
add_executable(IcoTool::IcoTool IMPORTED)
set_target_properties(IcoTool::IcoTool PROPERTIES
IMPORTED_LOCATION "${IcoTool_EXECUTABLE}"
)
endif()
endif()
include(FeatureSummary)
set_package_properties(IcoTool PROPERTIES
URL "http://www.nongnu.org/icoutils/"
DESCRIPTION "Executable that converts a collection of PNG files into a Windows icon file"
)

View File

@@ -11,7 +11,7 @@
<key>CFBundleExecutable</key>
<string>@APPLICATION_EXECUTABLE@</string>
<key>CFBundleIconFile</key>
<string>ownCloud.icns</string>
<string>@APPLICATION_EXECUTABLE@.icns</string>
<key>CFBundleIdentifier</key>
<string>@APPLICATION_REV_DOMAIN@</string>
<key>CFBundleInfoDictionaryVersion</key>
@@ -27,12 +27,47 @@
<key>CFBundleShortVersionString</key>
<string>@MIRALL_VERSION_STRING@</string>
<key>NSHumanReadableCopyright</key>
<string>(C) 2014-2016 @APPLICATION_VENDOR@</string>
<string>(C) 2014-2018 @APPLICATION_VENDOR@</string>
<key>SUShowReleaseNotes</key>
<false/>
<key>LSMinimumBundleVersion</key>
<string>10.7.0</string>
<key>SUPublicDSAKeyFile</key>
<string>dsa_pub.pem</string>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeIdentifier</key>
<string>@APPLICATION_REV_DOMAIN@.VIRTUALFILE</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<string>@APPLICATION_VIRTUALFILE_SUFFIX@</string>
<key>public.mime-type</key>
<string>application/octet-stream</string>
</dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
</dict>
</array>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>@APPLICATION_EXECUTABLE@ Download Virtual File</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>@APPLICATION_REV_DOMAIN@.VIRTUALFILE</string>
</array>
</dict>
</array>
</dict>
</plist>

View File

@@ -7,6 +7,8 @@
!define APPLICATION_CMD_EXECUTABLE "@APPLICATION_EXECUTABLE@cmd.exe"
!define APPLICATION_DOMAIN "@APPLICATION_DOMAIN@"
!define APPLICATION_LICENSE "@APPLICATION_LICENSE@"
!define APPLICATION_VIRTUALFILE_SUFFIX "@APPLICATION_VIRTUALFILE_SUFFIX@"
!define APPLICATION_VIRTUALFILE_FILECLASS "@APPLICATION_EXECUTABLE@.@APPLICATION_VIRTUALFILE_SUFFIX@"
!define WIN_SETUP_BITMAP_PATH "@WIN_SETUP_BITMAP_PATH@"
!define CRASHREPORTER_EXECUTABLE "@CRASHREPORTER_EXECUTABLE@"
@@ -100,6 +102,8 @@ ReserveFile "${NSISDIR}\Plugins\InstallOptions.dll"
!include Library.nsh ;Used by the COM registration for shell extensions
!include x64.nsh ;Used to determine the right arch for the shell extensions
!include ${source_path}/admin/win/nsi/lib/fileassoc.nsh
;-----------------------------------------------------------------------------
; Memento selections stored in registry.
;-----------------------------------------------------------------------------
@@ -466,6 +470,9 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
;CSync configs
File "${SOURCE_PATH}/sync-exclude.lst"
;Add file association
!insertmacro APP_ASSOCIATE "${APPLICATION_VIRTUALFILE_SUFFIX}" "${APPLICATION_VIRTUALFILE_FILECLASS}" "Virtual File for Remote File" "$INSTDIR\${APPLICATION_EXECUTABLE},0" "Download" "$INSTDIR\${APPLICATION_EXECUTABLE} $\"%1$\""
SectionEnd
!ifdef OPTION_SECTION_SC_SHELL_EXT
@@ -643,6 +650,9 @@ Section Uninstall
DeleteRegKey HKCR "${APPLICATION_NAME}"
;Remove file association
!insertmacro APP_UNASSOCIATE "${APPLICATION_VIRTUALFILE_SUFFIX}" "${APPLICATION_VIRTUALFILE_FILECLASS}"
;Shell extension
!ifdef OPTION_SECTION_SC_SHELL_EXT
!define LIBRARY_COM

View File

@@ -7,10 +7,11 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
# Fix sqlite compilation on macOS
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-incompatible-pointer-types-discards-qualifiers")
# Fix sqlite compilation on MinGW
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-discarded-qualifiers")
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
# Fix sqlite compilation on MinGW
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-discarded-qualifiers")
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)

View File

@@ -18,12 +18,12 @@
#cmakedefine APPLICATION_EXECUTABLE "@APPLICATION_EXECUTABLE@"
#cmakedefine APPLICATION_UPDATE_URL "@APPLICATION_UPDATE_URL@"
#cmakedefine APPLICATION_ICON_NAME "@APPLICATION_ICON_NAME@"
#cmakedefine APPLICATION_VIRTUALFILE_SUFFIX "@APPLICATION_VIRTUALFILE_SUFFIX@"
#define APPLICATION_DOTVIRTUALFILE_SUFFIX "." APPLICATION_VIRTUALFILE_SUFFIX
#cmakedefine ZLIB_FOUND @ZLIB_FOUND@
#cmakedefine SYSCONFDIR "@SYSCONFDIR@"
#cmakedefine SHAREDIR "@SHAREDIR@"
#cmakedefine WITH_TESTING 1
#endif

2
doc/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
conf.py
Makefile

View File

@@ -24,7 +24,7 @@ if(SPHINX_FOUND)
add_custom_target(doc DEPENDS doc-html COMMENT "Building documentation...")
endif(WITH_DOC)
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ocdoc/_shared_assets")
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/docs-themes")
add_dependencies(doc doc-html-org)
add_dependencies(doc doc-html-com)
endif()
@@ -90,4 +90,4 @@ if(SPHINX_FOUND)
${SPHINX_HTMLHELP_DIR} )
add_custom_target( doc-chm pushd ${SPHINX_HTMLHELP_DIR}; ${MSHTML_COMPILER} *.hhp; popd
DEPENDS doc-chm-sphinx )
endif(SPHINX_FOUND)
endif(SPHINX_FOUND)

View File

@@ -1,174 +0,0 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " pdf to make PDF files"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html: html-org
html-all: html-release html-org html-com
html-release:
$(SPHINXBUILD) -b html -D html_theme='owncloud_release' $(ALLSPHINXOPTS) $(BUILDDIR)/html/release
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html/release."
html-org:
$(SPHINXBUILD) -b html -D html_theme='owncloud_org' $(ALLSPHINXOPTS) $(BUILDDIR)/html/org
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html/org."
html-com:
$(SPHINXBUILD) -b html -D html_theme='owncloud_com' $(ALLSPHINXOPTS) $(BUILDDIR)/html/com
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html/com."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/OwncloudDocumentation.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/OwncloudDocumentation.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/OwncloudDocumentation"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/OwncloudDocumentation"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
pdf:
$(SPHINXBUILD) -b pdf $(ALLSPHINXOPTS) $(BUILDDIR)/pdf
@echo
@echo "build finished. the text files are in $(BUILDDIR)/pdf."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "build finished. the text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."

View File

@@ -138,8 +138,8 @@ under the original file name.
Example: Assume there is a conflict in message.txt because its contents have
changed both locally and remotely since the last sync run. The local file with
the local changes will be renamed to message_conflict-20160101-153110.txt and
the remote file will be downloaded and saved as message.txt.
the local changes will be renamed to "message (conflicted copy 2016-01-01 153110).txt"
and the remote file will be downloaded and saved as message.txt.
Conflict files are always created on the client and never on the server.
@@ -276,9 +276,15 @@ Some system wide file patterns that are used to exclude or ignore files are incl
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 ``._sync_xxxxxxx.db`` and the old format ``.csync_journal.db``, as these files are reserved for journalling.
* Files matched by one of the patterns defined in the Ignored Files Editor.
* Files starting with ``._sync_*.db*``, ``.sync_*.db*``, ``.csync_journal.db*``, ``.owncloudsync.log*``, as these files are reserved for journalling.
* Files with a name longer than 254 characters.
* The file ``Desktop.ini`` in the root of a synced folder.
* Files matching the pattern ``*_conflict-*`` unless conflict file uploading is enabled.
* Files matching the pattern ``*(conflicted copy*`` unless conflict file uploading is enabled.
* Windows only: Files containing characters that do not work on typical Windows filesystems ``(`\, /, :, ?, *, ", >, <, |`)``.
* Windows only: Files with a trailing space or dot.
* Windows only: Filenames that are reserved on Windows.
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

View File

@@ -13,6 +13,14 @@ desktop client.
These instructions are updated to work with version |version| of the ownCloud Client.
Compiling via ownBrander
------------------------
If you don't want to go through the trouble of doing all the compile work manually,
you can use `ownBrander`_ to create installer images for all platforms.
Getting Source Code
-------------------
@@ -51,8 +59,8 @@ distribution. Make sure the repositories for source packages are enabled.
3. Follow the :ref:`generic-build-instructions`, starting with step 2.
Mac OS X
--------
macOS
-----
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
@@ -77,29 +85,23 @@ To set up your build environment for development using HomeBrew_:
brew tap owncloud/owncloud
5. Install a Qt5 version with qtwebkit support::
5. Install a Qt5 version, ideally from from 5.10.1::
brew install qt5 --with-qtwebkit
brew install qt5
6. Install any missing dependencies::
brew install $(brew deps owncloud-client)
7. Add Qt from brew to the path::
7. 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``
export PATH=/usr/local/Cellar/qt5/5.x.y/bin:$PATH
8. For compilation of the client, follow the :ref:`generic-build-instructions`.
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``
9. Install the Packages_ package creation tool.
9. For compilation of the client, follow the :ref:`generic-build-instructions`.
10. Install the Packages_ package creation tool.
11. In the build directory, run ``admin/osx/create_mac.sh <build_dir> <install_dir>``.
10. In the build directory, run ``admin/osx/create_mac.sh <CMAKE_INSTALL_DIR> <build dir> <installer sign identity>``.
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.
@@ -152,7 +154,7 @@ follow `Windows Installer Build (Cross-Compile)`_ instead.
7. Build the client::
cmake -G "MinGW Makefiles" ../client
cmake -G "MinGW Makefiles" -DNO_SHIBBOLETH=1 ../client
mingw32-make
.. note:: You can try using ninja to build in parallel using
@@ -220,16 +222,14 @@ In order to make setup simple, you can use the provided Dockerfile to build your
Generic Build Instructions
--------------------------
Compared to previous versions, building the desktop sync client has become easier. Unlike
earlier versions, CSync, which is the sync engine library of the client, is now
part of the client source repository and not a separate module.
To build the most up-to-date version of the client:
1. Clone the latest versions of the client from Git_ as follows::
git clone git://github.com/owncloud/client.git
cd client
# master this default, but you can also check out a tag like v2.4.1
git checkout master
git submodule init
git submodule update
@@ -240,19 +240,18 @@ To build the most up-to-date version of the client:
3. Configure the client build::
cmake -DCMAKE_BUILD_TYPE="Debug" ..
.. note:: You must use absolute paths for the ``include`` and ``library``
directories.
cmake -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5 -DCMAKE_INSTALL_PREFIX=/Users/path/to/client/../install/ -DNO_SHIBBOLETH=1 ..``
.. note:: You must use absolute paths for the ``include`` and ``library``
directories.
.. note:: On Mac OS X, you need to specify ``-DCMAKE_INSTALL_PREFIX=target``,
where ``target`` is a private location, i.e. in parallel to your build
dir by specifying ``../install``.
.. note:: qtkeychain must be compiled with the same prefix e.g ``-DCMAKE_INSTALL_PREFIX=/Users/path/to/client/../install/``
.. 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/ -DNO_SHIBBOLETH=1``
4. Call ``make``.
The owncloud binary will appear in the ``bin`` directory.
@@ -264,11 +263,10 @@ The following are known cmake parameters:
* ``QTKEYCHAIN_LIBRARY=/path/to/qtkeychain.dylib -DQTKEYCHAIN_INCLUDE_DIR=/path/to/qtkeychain/``:
Used for stored credentials. When compiling with Qt5, the library is called ``qt5keychain.dylib.``
You need to compile QtKeychain with the same Qt version.
You need to compile QtKeychain with the same Qt version. If you install QtKeychain into the CMAKE_PREFIX_PATH then you don't need to specify the path manually.
* ``WITH_DOC=TRUE``: Creates doc and manpages through running ``make``; also adds install statements,
providing the ability to install using ``make install``.
* ``CMAKE_PREFIX_PATH=/path/to/Qt5.2.0/5.2.0/yourarch/lib/cmake/``: Builds using Qt5.
* ``BUILD_WITH_QT4=ON``: Builds using Qt4 (even if Qt5 is found).
* ``CMAKE_PREFIX_PATH=/path/to/Qt5.10.1/5.10.1/yourarch/lib/cmake/``: Builds using that Qt version.
* ``CMAKE_INSTALL_PREFIX=path``: Set an install prefix. This is mandatory on Mac OS
.. _ownCloud repository from OBS: http://software.opensuse.org/download/package?
@@ -285,3 +283,4 @@ The following are known cmake parameters:
.. _QtKeychain: https://github.com/frankosterfeld/qtkeychain
.. _Packages: http://s.sudre.free.fr/Software/Packages/about.html
.. _Index of repositories: http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/
.. _ownBrander: https://doc.owncloud.org/branded_clients/

View File

@@ -1,292 +0,0 @@
# -*- coding: utf-8 -*-
#
# ownCloud Documentation documentation build configuration file, created by
# sphinx-quickstart on Mon Oct 22 23:16:40 2012.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.todo']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['@CMAKE_CURRENT_SOURCE_DIR@/ocdoc/_shared_assets/templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'ownCloud Client Manual'
copyright = u'2013-2016, The ownCloud developers'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '2.4.0'
# The full version, including alpha/beta/rc tags.
release = '2.4.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build','scripts/*']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
2
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
html_theme_path = ['@CMAKE_CURRENT_SOURCE_DIR@/ocdoc/_shared_assets/themes']
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#html_theme = 'bootstrap'
html_theme = 'default'
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
html_short_title = "Client Manual"
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['@CMAKE_CURRENT_SOURCE_DIR@/ocdoc/_shared_assets/static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
html_show_sphinx = False
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'ownCloudClientManual'
# -- Options for LaTeX output --------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'ownCloudClientManual.tex', u'ownCloud Client Manual',
u'The ownCloud developers', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
latex_logo = 'logo-blue.pdf'
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('owncloud.1', 'owncloud', u'File synchronisation desktop utility.',
[u'The ownCloud developers'], 1),
('owncloudcmd.1', 'owncloudcmd', u'Command line ownCloud client tool.',
[u'The ownCloud developers'], 1),
]
# If true, show URL addresses after external links.
man_show_urls = True
# -- Options for Texinfo output ------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'ownCloudClientManual', u'ownCloud Client Manual',
u'The ownCloud developers', 'ownCloud', 'The ownCloud Client Manual.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# -- Options for Epub output ---------------------------------------------------
# Bibliographic Dublin Core info.
epub_title = u'ownCloud Client Manual'
epub_author = u'The ownCloud developers'
epub_publisher = u'The ownCloud developers'
epub_copyright = u'2013-2016, The ownCloud developers'
# The language of the text. It defaults to the language option
# or en if the language is not set.
#epub_language = ''
# The scheme of the identifier. Typical schemes are ISBN or URL.
#epub_scheme = ''
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#epub_identifier = ''
# A unique identification for the text.
#epub_uid = ''
# A tuple containing the cover image and cover page html template filenames.
#epub_cover = ()
# HTML files that should be inserted before the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#epub_pre_files = []
# HTML files shat should be inserted after the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#epub_post_files = []
# A list of files that should not be packed into the epub file.
#epub_exclude_files = []
# The depth of the table of contents in toc.ncx.
#epub_tocdepth = 3
# Allow duplicate toc entries.
#epub_tocdup = True
# Include todos?
todo_include_todos = True
rst_epilog = '.. |version| replace:: %s' % version

View File

@@ -12,6 +12,7 @@
# serve to show the default.
import sys, os
from datetime import datetime
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
@@ -28,7 +29,7 @@ import sys, os
extensions = ['sphinx.ext.todo']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['@CMAKE_CURRENT_SOURCE_DIR@/ocdoc/_shared_assets/templates']
templates_path = ['@CMAKE_CURRENT_SOURCE_DIR@/docs-themes/templates']
# The suffix of source filenames.
source_suffix = '.rst'
@@ -41,7 +42,7 @@ master_doc = 'index'
# General information about the project.
project = u'ownCloud Client Manual'
copyright = u'2013-2016, The ownCloud developers'
copyright = u'2013-{:%Y}, The ownCloud developers'.format(datetime.now())
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -95,7 +96,7 @@ pygments_style = 'sphinx'
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
html_theme_path = ['@CMAKE_CURRENT_SOURCE_DIR@/ocdoc/_shared_assets/themes']
html_theme_path = ['@CMAKE_CURRENT_SOURCE_DIR@/docs-themes/themes']
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
@@ -120,7 +121,7 @@ html_short_title = "Client Manual"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['@CMAKE_CURRENT_SOURCE_DIR@/ocdoc/_shared_assets/static']
html_static_path = ['@CMAKE_CURRENT_SOURCE_DIR@/docs-themes/static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
@@ -250,7 +251,7 @@ texinfo_documents = [
epub_title = u'ownCloud Client Manual'
epub_author = u'The ownCloud developers'
epub_publisher = u'The ownCloud developers'
epub_copyright = u'2013-2016, The ownCloud developers'
epub_copyright = u'2013-{:%Y}, The ownCloud developers'.format(datetime.now())
# The language of the text. It defaults to the language option
# or en if the language is not set.

View File

@@ -46,6 +46,13 @@ Some interesting values that can be set on the configuration file are:
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
| ``timeout`` | ``300`` | The timeout for network connections in seconds. |
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
| ``moveToTrash`` | ``false`` | If non-locally deleted files should be moved to trash instead of deleting them completely. |
| | | This option only works on linux |
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
| ``showExperimentalOptions`` | ``false`` | Whether to show experimental options that are still undergoing testing in the user interface. |
| | | Turning this on does not enable experimental behavior on its own. It does enable user inferface |
| | | options that can be used to opt in to experimental features. |
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
+----------------------------------------------------------------------------------------------------------------------------------------------------------+

61
doc/conflicts.rst Normal file
View File

@@ -0,0 +1,61 @@
=========
Conflicts
=========
.. index:: conflicts
Overview
--------
The ownCloud desktop client uploads local changes and downloads remote changes.
When a file has changed on the local side and on the remote between synchronization
runs the client will be unable to resolve the situation on its own. It will
create a conflict file with the local version, download the remote version and
notify the user that a conflict occured which needs attention.
Example
-------
Imagine there is a file called ``mydata.txt`` your synchronized folder. It has
not changed for a while and contains the text "contents" locally and remotely.
Now, nearly at the same time you update it locally to say "local contents" while
the file on the server gets updated to contain "remote contents" by someone else.
When attempting to upload your local changes the desktop client will notice that
the server version has also changed. It creates a conflict and you will now have
two files on your local machine:
- ``mydata.txt`` containing "remote contents"
- ``mydata (conflicted copy 2018-04-10 093612).txt`` containing "local contents"
In this situation the file ``mydata.txt`` has the remote changes (and will continue
to be updated with further remote changes when they happen), but your local
adjustments have not been sent to the server (unless the server enables conflict
uploading, see below).
The desktop client notifies you of this situation via system notifications, the
system tray icon and a yellow "unresolved conflicts" badge in the account settings
window. Clicking this badge shows a list that includes the unresolved conflicts
and clicking one of them opens an explorer window pointing at the relevant file.
To resolve this conflict, open both files, compare the differences and copy your
local changes from the "conflicted copy" file into the base file where applicable.
In this example you might change ``mydata.txt`` to say "local and remote contents"
and delete the file with "conflicted copy" in its name. With that, the conflict
is resolved.
Uploading conflicts (experimental)
----------------------------------
By default the conflict file (the file with "conflicted copy" in its name that
contains your local conflicting changes) is not uploaded to the server. The idea
is that you, the author of the changes, are the best person for resolving the
conflict and showing the conflict to other users might create confusion.
However, in some scenarios it makes a lot of sense to upload these conflicting
changes such that local work can become visible even if the conflict won't be
resolved immediately.
In the future there might be a server-wide switch for this behavior. For now it
can already be tested by setting the environment variable
``OWNCLOUD_UPLOAD_CONFLICT_FILES=1``.

1
doc/docs-themes Submodule

Submodule doc/docs-themes added at 90bd26b118

View File

@@ -21,6 +21,25 @@ When a deeply nested directory is excluded from synchronization it will be
listed with other ignored files and directories in the "Not synced" tab of
the "Activity" pane.
There Was A Warning About Changes In Synchronized Folders Not Being Tracked Reliably.
-------------------------------------------------------------------------------------
On linux when the synchronized folder contains very many subfolders the
operating system may not allow for enough inotify watches to monitor the
changes in all of them.
In this case the client will not be able to immediately start the
synchronization process when a file in one of the unmonitored folders changes.
Instead, the client will show the warning and manually scan folders for changes
in a regular interval (two hours by default).
This problem can be solved by setting the fs.inotify.max_user_watches
sysctl to a higher value. This can usually be done either temporarily::
echo 524288 > /proc/sys/fs/inotify/max_user_watches
or permanently by adjusting ``/etc/sysctl.conf``.
I Want To Move My Local Sync Folder
-----------------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

View File

@@ -9,6 +9,7 @@ ownCloud Desktop Client Manual
introduction
installing
navigating
conflicts
advancedusage
autoupdate
building
@@ -16,4 +17,4 @@ ownCloud Desktop Client Manual
troubleshooting
faq
glossary

View File

@@ -30,13 +30,13 @@ System Requirements
- Windows 7+
- Mac OS X 10.7+ (**64-bit only**)
- CentOS 6 & 7 (64-bit only)
- Debian 7.0 & 8.0 & 9.0
- Fedora 24 & 25 & 26
- Ubuntu 16.04 & 16.10 & 17.04
- openSUSE Leap 42.1 & 42.2 & 42.3
- Debian 8.0 & 9.0
- Fedora 25 & 26 & 27
- Ubuntu 16.04 & 17.04 & 17.10
- openSUSE Leap 42.2 & 42.3
.. note::
For Linux distributions, we support, if technically feasible, the latest 2 versions per platform and the previous `LTS`_.
For Linux distributions, we support, if technically feasible, the latest 2 versions per platform and the previous Ubuntu `LTS`_.
Installation Wizard
-------------------
@@ -67,12 +67,7 @@ server, and when it is successful you'll see two buttons: one to connect to
your ownCloud Web GUI, and one to open your local folder. It will also start
synchronizing your files.
.. image:: images/client-4.png
:alt: A successful server connection, showing a button to connect to your
Web GUI, and one to open your local ownCloud folder
Click the Finish button, and you're all done.
.. Links
.. _ownCloud download page: https://owncloud.com/download/#desktop-clients
.. _LTS: https://wiki.ubuntu.com/LTS

View File

@@ -23,11 +23,3 @@ The |version| release of the ownCloud desktop sync client has many new features
improvements. (See the `complete changelog
<https://owncloud.org/changelog/desktop/>`_.)
* Show server notifications on the client
* Improved sync speed
* Improved handling of Win32 file locks and network files
* Improved user notifications about ignored files and conflicts
* Add warnings for old server versions
* Update of QtKeyChain to support Windows credential store
* Packaging of dolphin overlay icon module for bleeding edge distributions

View File

@@ -5,7 +5,7 @@ Using the Synchronization Client
.. index:: navigating, usage
The ownCloud Desktop Client remains in the background and is visible as an icon
in the system tray (Windows, KDE), status bar (Mac OS X), or notification area
in the system tray (Windows, KDE), menu bar (macOS), or notification area
(Linux).
.. figure:: images/icon.png

View File

@@ -107,14 +107,25 @@ Log Files
Effectively debugging software requires as much relevant information as can be
obtained. To assist the ownCloud support personnel, please try to provide as
many relevant logs as possible. Log output can help with tracking down
many relevant logs as possible. Log output can help with tracking down
problems and, if you report a bug, log output can help to resolve an issue more
quickly.
The client log file is often the most helpful log to provide.
Obtaining the Client Log File
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To obtain the client log file:
There are several ways to produce log files. The most commonly useful is enabling
logging to a temporary directory, described first.
Note: Client log files contain file and folder names, metadata, server urls and
other private information. Only upload them if you are comfortable sharing the
information. Logs are often essential for tracking down a problem though, so
please consider providing them to developers privately.
Logging to a Temporary Directory
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1. Open the ownCloud Desktop Client.
@@ -124,37 +135,22 @@ To obtain the client log file:
.. image:: images/log_output_window.png
3. Click the 'Save' button.
3. Enable the 'Permanently save logs' checkbox.
The Save Log File window opens.
4. Look at its tooltip and take note of the directory the logs will be saved to.
.. image:: images/save_log_file.png
5. Navigate to this directory.
4. Migrate to a location on your system where you want to save your log file.
6. Select the logs for the timeframe in which the issue occurred.
5. Name the log file and click the 'Save' button.
The log file is saved in the location specified.
Alternatively, you can launch the ownCloud Log Output window using the
``--logwindow`` command. After issuing this command, the Log Output window
opens to show the current log. You can then follow the same procedures
mentioned above to save the log to a file.
.. note:: You can also open a log window for an already running session, by
restarting the client using the following command:
* Windows: ``C:\Program Files (x86)\ownCloud\owncloud.exe --logwindow``
* Mac OS X: ``/Applications/owncloud.app/Contents/MacOS/owncloud --logwindow``
* Linux: ``owncloud --logwindow``
Note that the choice to enable logging will be persist across client restarts.
Saving Files Directly
~~~~~~~~~~~~~~~~~~~~~
^^^^^^^^^^^^^^^^^^^^^
The ownCloud client enables you to save log files directly to a predefined file
or directory. This is a useful option for troubleshooting sporadic issues as
it enables you to log large amounts of data and bypasses the limited buffer
settings associated with the log window.
The ownCloud client allows you to save log files directly to a custom file
or directory. This is a useful option for easily reproducible problems, as well
as for cases where you want logs to be saved to a different location.
To save log files to a file or a directory:
@@ -170,6 +166,8 @@ the amount of data that accumulates over time, you can specify the
the client automatically erases saved log data in the directory that is older
than the specified number of hours.
Adding the ``--logdebug`` flag increases the verbosity of the generated log files.
As an example, to define a test where you keep log data for two days, you can
issue the following command:

View File

@@ -8,77 +8,7 @@ GenericName=Folder Sync
Icon=@APPLICATION_EXECUTABLE@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
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
MimeType=application/x-@APPLICATION_EXECUTABLE@
# Translations
@@ -246,7 +176,7 @@ Icon[eu]=@APPLICATION_EXECUTABLE@
GenericName[fa]=همسان سازی پوشه‌ها
Name[fa]=@APPLICATION_EXECUTABLE@ نسخه‌ی همسان سازی مشتری
Icon[fa]=@APPLICATION_EXECUTABLE@
Comment[fr]=Synchronisez vos dossiers avec un serveur @APPLICATION_NAME@
Comment[fr]=Client de synchronisation @APPLICATION_NAME@
GenericName[fr]=Synchronisation de dossier
Name[fr]=Client de synchronisation @APPLICATION_NAME@
Icon[fr]=@APPLICATION_EXECUTABLE@
@@ -278,9 +208,15 @@ Comment[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
GenericName[ko]=폴더 동기화
Name[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
Icon[ko]=@APPLICATION_EXECUTABLE@
Comment[lo]=@APPLICATION_NAME@ ການປະສານຂໍ້ມູນຄອມພິວເຕີລູກຂ່າຍ
GenericName[lo]=ໂຟນເດີຊິງ
Name[lo]=@APPLICATION_NAME@ ຊິງຄອມພິວເຕີລູກຂ່າຍ
Icon[lo]=@APPLICATION_EXECUTABLE@
GenericName[mk]=Папка за синхронизација
Icon[mk]=@APPLICATION_EXECUTABLE@
Comment[hu_HU]=@APPLICATION_NAME@ asztali szinkronizációs kliens
GenericName[hu_HU]=Könyvtár szinkronizálás
Name[hu_HU]=@APPLICATION_NAME@ asztali szinkr. kliens
GenericName[hu_HU]=Mappaszinkronizálás
Name[hu_HU]=@APPLICATION_NAME@ asztali szinkronizációs kliens
Icon[hu_HU]=@APPLICATION_EXECUTABLE@
Comment[af_ZA]=@APPLICATION_NAME@ werkskermsinchroniseerkliënt
GenericName[af_ZA]=Vouersinchronisering
@@ -355,9 +291,9 @@ Comment[lt_LT]=@APPLICATION_NAME@ darbalaukio sinchronizavimo programa
GenericName[lt_LT]=Katalogo sinchnorizacija
Name[lt_LT]=@APPLICATION_NAME@ darbalaukio programa
Icon[lt_LT]=@APPLICATION_EXECUTABLE@
Comment[th_TH]=@APPLICATION_NAME@ ไคลเอนต์ประสานข้อมูลเดสก์ท็อป
Comment[th_TH]=@APPLICATION_NAME@ ประสานข้อมูลด้วยโปรแกรมบนเดสก์ท็อป
GenericName[th_TH]=ประสานข้อมูลโฟลเดอร์
Name[th_TH]= @APPLICATION_NAME@ ไคลเอนต์ประสานข้อมูลเดสก์ท็อป
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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 B

5
resources/more.svg Normal file
View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/">
<rect style="color:#000000" fill-opacity="0" height="97.986" width="163.31" y="-32.993" x="-62.897"/>
<path d="m3 6c-1.1046 0-2 0.8954-2 2s0.8954 2 2 2 2-0.8954 2-2-0.8954-2-2-2zm5 0c-1.1046 0-2 0.8954-2 2s0.8954 2 2 2 2-0.8954 2-2-0.8954-2-2-2zm5 0c-1.105 0-2 0.8954-2 2s0.895 2 2 2 2-0.8954 2-2-0.895-2-2-2z" fill-rule="evenodd"/>
</svg>

After

Width:  |  Height:  |  Size: 660 B

View File

@@ -23,6 +23,7 @@
NSMutableSet *_registeredDirectories;
NSString *_shareMenuTitle;
NSMutableDictionary *_strings;
NSMutableArray *_menuItems;
}
@end

View File

@@ -21,7 +21,7 @@
- (instancetype)init
{
self = [super init];
FIFinderSyncController *syncController = [FIFinderSyncController defaultController];
NSBundle *extBundle = [NSBundle bundleForClass:[self class]];
// This was added to the bundle's Info.plist to get it from the build system
@@ -43,7 +43,7 @@
[syncController setBadgeImage:sync label:@"Synchronizing" forBadgeIdentifier:@"NEW+SWM"];
[syncController setBadgeImage:warning label:@"Ignored" forBadgeIdentifier:@"IGNORE+SWM"];
[syncController setBadgeImage:error label:@"Error" forBadgeIdentifier:@"ERROR+SWM"];
// The Mach port name needs to:
// - Be prefixed with the code signing Team ID
// - Then infixed with the sandbox App Group
@@ -55,12 +55,12 @@
// the sandboxed App Extension needs.
// https://developer.apple.com/library/mac/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW24
NSString *serverName = [socketApiPrefix stringByAppendingString:@".socketApi"];
// NSLog(@"FinderSync serverName %@", serverName);
//NSLog(@"FinderSync serverName %@", serverName);
_syncClientProxy = [[SyncClientProxy alloc] initWithDelegate:self serverName:serverName];
_registeredDirectories = [[NSMutableSet alloc] init];
_strings = [[NSMutableDictionary alloc] init];
[_syncClientProxy start];
return self;
}
@@ -74,13 +74,27 @@
NSLog(@"ERROR: Could not determine file type of %@", [url path]);
isDir = NO;
}
NSString* normalizedPath = [[url path] decomposedStringWithCanonicalMapping];
[_syncClientProxy askForIcon:normalizedPath isDirectory:isDir];
}
#pragma mark - Menu and toolbar item support
- (NSString*) selectedPathsSeparatedByRecordSeparator
{
FIFinderSyncController *syncController = [FIFinderSyncController defaultController];
NSMutableString *string = [[NSMutableString alloc] init];
[syncController.selectedItemURLs enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
if (string.length > 0) {
[string appendString:@"\x1e"]; // record separator
}
NSString* normalizedPath = [[obj path] decomposedStringWithCanonicalMapping];
[string appendString:normalizedPath];
}];
return string;
}
- (NSMenu *)menuForMenuKind:(FIMenuKind)whichMenu
{
FIFinderSyncController *syncController = [FIFinderSyncController defaultController];
@@ -101,54 +115,43 @@
}
}];
NSString *paths = [self selectedPathsSeparatedByRecordSeparator];
// calling this IPC calls us back from client with several MENU_ITEM entries and then our askOnSocket returns again
[_syncClientProxy askOnSocket:paths query:@"GET_MENU_ITEMS"];
id contextMenuTitle = [_strings objectForKey:@"CONTEXT_MENU_TITLE"];
id shareTitle = [_strings objectForKey:@"SHARE_MENU_TITLE"];
id copyLinkTitle = [_strings objectForKey:@"COPY_PRIVATE_LINK_MENU_TITLE"];
id emailLinkTitle = [_strings objectForKey:@"EMAIL_PRIVATE_LINK_MENU_TITLE"];
if (contextMenuTitle && !onlyRootsSelected) {
NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
NSMenu *subMenu = [[NSMenu alloc] initWithTitle:@""];
NSMenuItem *subMenuItem = [menu addItemWithTitle:contextMenuTitle action:nil keyEquivalent:@""];
subMenuItem.submenu = subMenu;
subMenuItem.image = [[NSBundle mainBundle] imageForResource:@"app.icns"];
[subMenu addItemWithTitle:shareTitle action:@selector(shareMenuAction:) keyEquivalent:@""];
[subMenu addItemWithTitle:copyLinkTitle action:@selector(copyLinkMenuAction:) keyEquivalent:@""];
[subMenu addItemWithTitle:emailLinkTitle action:@selector(emailLinkMenuAction:) keyEquivalent:@""];
NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
NSMenu *subMenu = [[NSMenu alloc] initWithTitle:@""];
NSMenuItem *subMenuItem = [menu addItemWithTitle:contextMenuTitle action:nil keyEquivalent:@""];
subMenuItem.submenu = subMenu;
subMenuItem.image = [[NSBundle mainBundle] imageForResource:@"app.icns"];
// There is an annoying bug in macOS (at least 10.13.3), it does not use/copy over the representedObject of a menu item
// So we have to use tag instead.
int idx = 0;
for (NSArray* item in _menuItems) {
NSMenuItem *actionItem = [subMenu addItemWithTitle:[item valueForKey:@"text"]
action:@selector(subMenuActionClicked:)
keyEquivalent:@""];
[actionItem setTag:idx];
[actionItem setTarget:self];
NSString *flags = [item valueForKey:@"flags"]; // e.g. "d"
if ([flags rangeOfString:@"d"].location != NSNotFound) {
[actionItem setEnabled:false];
}
idx++;
}
return menu;
}
return nil;
}
- (IBAction)shareMenuAction:(id)sender
{
NSArray* items = [[FIFinderSyncController defaultController] selectedItemURLs];
[items enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
NSString* normalizedPath = [[obj path] decomposedStringWithCanonicalMapping];
[_syncClientProxy askOnSocket:normalizedPath query:@"SHARE"];
}];
}
- (IBAction)copyLinkMenuAction:(id)sender
{
NSArray* items = [[FIFinderSyncController defaultController] selectedItemURLs];
[items enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
NSString* normalizedPath = [[obj path] decomposedStringWithCanonicalMapping];
[_syncClientProxy askOnSocket:normalizedPath query:@"COPY_PRIVATE_LINK"];
}];
}
- (IBAction)emailLinkMenuAction:(id)sender
{
NSArray* items = [[FIFinderSyncController defaultController] selectedItemURLs];
[items enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
NSString* normalizedPath = [[obj path] decomposedStringWithCanonicalMapping];
[_syncClientProxy askOnSocket:normalizedPath query:@"EMAIL_PRIVATE_LINK"];
}];
- (void)subMenuActionClicked:(id)sender {
long idx = [(NSMenuItem*)sender tag];
NSString *command = [[_menuItems objectAtIndex:idx] valueForKey:@"command"];
NSString *paths = [self selectedPathsSeparatedByRecordSeparator];
[_syncClientProxy askOnSocket:paths query:command];
}
#pragma mark - SyncClientProxyDelegate implementation
@@ -181,6 +184,14 @@
[_strings setObject:value forKey:key];
}
- (void)resetMenuItems
{
_menuItems = [[NSMutableArray alloc] init];
}
- (void)addMenuItem:(NSDictionary *)item {
[_menuItems addObject:item];
}
- (void)connectionDidDie
{
[_strings removeAllObjects];

View File

@@ -21,6 +21,8 @@
- (void)registerPath:(NSString*)path;
- (void)unregisterPath:(NSString*)path;
- (void)setString:(NSString*)key value:(NSString*)value;
- (void)resetMenuItems;
- (void)addMenuItem:(NSDictionary *)item;
- (void)connectionDidDie;
@end

View File

@@ -27,7 +27,7 @@
- (instancetype)initWithDelegate:(id)arg1 serverName:(NSString*)serverName
{
self = [super init];
self.delegate = arg1;
_serverName = serverName;
_remoteEnd = nil;
@@ -41,20 +41,20 @@
{
if (_remoteEnd)
return;
// Lookup the server connection
NSConnection *conn = [NSConnection connectionWithRegisteredName:_serverName host:nil];
if (!conn) {
// Could not connect to the sync client
[self scheduleRetry];
return;
}
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(connectionDidDie:)
name:NSConnectionDidDieNotification
object:conn];
selector:@selector(connectionDidDie:)
name:NSConnectionDidDieNotification
object:conn];
NSDistantObject <ServerProtocol> *server = (NSDistantObject <ServerProtocol> *)[conn rootProxy];
assert(server);
@@ -71,7 +71,7 @@
// The server replied with the distant object that we will use for tx
_remoteEnd = (NSDistantObject <ChannelProtocol> *)tx;
[_remoteEnd setProtocolForProxy:@protocol(ChannelProtocol)];
// Everything is set up, start querying
[self askOnSocket:@"" query:@"GET_STRINGS"];
}
@@ -83,7 +83,7 @@
- (void)connectionDidDie:(NSNotification*)notification
{
#pragma unused(notification)
#pragma unused(notification)
_remoteEnd = nil;
[_delegate connectionDidDie];
@@ -95,11 +95,11 @@
- (void)sendMessage:(NSData*)msg
{
NSString *answer = [[NSString alloc] initWithData:msg encoding:NSUTF8StringEncoding];
// Cut the trailing newline
// Cut the trailing newline. We always only receive one line from the client.
answer = [answer substringToIndex:[answer length] - 1];
NSArray *chunks = [answer componentsSeparatedByString: @":"];
if( [[chunks objectAtIndex:0] isEqualToString:@"STATUS"] ) {
NSString *result = [chunks objectAtIndex:1];
NSString *path = [chunks objectAtIndex:2];
@@ -123,6 +123,18 @@
// BEGIN and END messages, do nothing.
} else if( [[chunks objectAtIndex:0 ] isEqualToString:@"STRING"] ) {
[_delegate setString:[chunks objectAtIndex:1] value:[chunks objectAtIndex:2]];
} else if( [[chunks objectAtIndex:0 ] isEqualToString:@"GET_MENU_ITEMS"] ) {
if ([[chunks objectAtIndex:1] isEqualToString:@"BEGIN"]) {
[_delegate resetMenuItems];
} else if ([[chunks objectAtIndex:1] isEqualToString:@"END"]) {
// Don't do anything special, the askOnSocket call in FinderSync menuForMenuKind will return after this line
}
} else if( [[chunks objectAtIndex:0 ] isEqualToString:@"MENU_ITEM"] ) {
NSMutableDictionary *item = [[NSMutableDictionary alloc] init];
[item setValue:[chunks objectAtIndex:1] forKey:@"command"]; // e.g. "COPY_PRIVATE_LINK"
[item setValue:[chunks objectAtIndex:2] forKey:@"flags"]; // e.g. "d"
[item setValue:[chunks objectAtIndex:3] forKey:@"text"]; // e.g. "Copy private link to clipboard"
[_delegate addMenuItem:item];
} else {
NSLog(@"SyncState: Unknown command %@", [chunks objectAtIndex:0]);
}
@@ -131,7 +143,7 @@
- (void)askOnSocket:(NSString*)path query:(NSString*)verb
{
NSString *query = [NSString stringWithFormat:@"%@:%@\n", verb,path];
@try {
[_remoteEnd sendMessage:[query dataUsingEncoding:NSUTF8StringEncoding]];
} @catch(NSException* e) {

View File

@@ -19,6 +19,7 @@
#include <QtNetwork/QLocalSocket>
#include <qcoreevent.h>
#include <QStandardPaths>
#include <QFile>
#include "ownclouddolphinpluginhelper.h"
#include "config.h"
@@ -68,12 +69,14 @@ void OwncloudDolphinPluginHelper::tryConnect()
if (_socket.state() != QLocalSocket::UnconnectedState) {
return;
}
QString runtimeDir = QFile::decodeName(qgetenv("XDG_RUNTIME_DIR"));
runtimeDir.append( QChar('/'));
runtimeDir.append( QLatin1String(APPLICATION_SHORTNAME) );
QString socketPath = QStandardPaths::locate(QStandardPaths::RuntimeLocation,
APPLICATION_SHORTNAME,
QStandardPaths::LocateDirectory);
if(socketPath.isEmpty())
return;
const QString socketPath = runtimeDir + QLatin1String("/socket");
_socket.connectToServer(socketPath);
_socket.connectToServer(socketPath + QLatin1String("/socket"));
}
void OwncloudDolphinPluginHelper::slotReadyRead()

View File

@@ -35,12 +35,15 @@ from gi.repository import GObject, Nautilus
appname = 'ownCloud'
print("Initializing "+appname+"-client-nautilus extension")
print("Using python version {}".format(sys.version_info))
def get_local_path(url):
if url[0:7] == 'file://':
url = url[7:]
unquote = urllib.parse.unquote if python3 else urllib.unquote
return unquote(url)
if python3:
return urllib.parse.unquote(url)
else:
return urllib.unquote(url).decode('utf-8')
def get_runtime_dir():
"""Returns the value of $XDG_RUNTIME_DIR, a directory path.
@@ -62,7 +65,7 @@ class SocketConnect(GObject.GObject):
self._watch_id = 0
self._sock = None
self._listeners = [self._update_registered_paths, self._get_version]
self._remainder = ''.encode()
self._remainder = ''.encode('utf-8')
self.protocolVersion = '1.0'
self.nautilusVFSFile_table = {} # not needed in this object actually but shared
# all over the other objects.
@@ -81,7 +84,7 @@ class SocketConnect(GObject.GObject):
# print("Server command: " + cmd)
if self.connected:
try:
self._sock.send(cmd.encode())
self._sock.send(cmd.encode('utf-8'))
except:
print("Sending failed.")
self.reconnect()
@@ -96,19 +99,16 @@ class SocketConnect(GObject.GObject):
self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
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))
self.sendCommand('VERSION:\n')
self.sendCommand('GET_STRINGS:\n')
return False # Don't run again
except Exception as e:
print("Could not connect to unix socket. " + str(e))
print("Could not connect to unix socket " + sock_file + ". " + str(e))
except Exception as e: # Bad habbit
print("Connect could not be established, try again later.")
self._sock.close()
@@ -131,12 +131,12 @@ class SocketConnect(GObject.GObject):
# Parses response lines out of collected data, returns list of strings
def get_available_responses(self):
end = self._remainder.rfind('\n'.encode())
end = self._remainder.rfind(b'\n')
if end == -1:
return []
data = self._remainder[:end]
self._remainder = self._remainder[end+1:]
return data.decode().split('\n')
return data.decode('utf-8').split('\n')
# Notify is the raw answer from the socket
def _handle_notify(self, source, condition):
@@ -152,7 +152,7 @@ class SocketConnect(GObject.GObject):
return True # Run again
def handle_server_response(self, line):
print("Server response: " + line)
# print("Server response: " + line)
parts = line.split(':')
action = parts[0]
args = parts[1:]
@@ -342,11 +342,11 @@ class MenuExtension(GObject.GObject, Nautilus.MenuProvider):
def context_menu_action(self, menu, action, filename):
print("Context menu: " + action + ' ' + filename)
# print("Context menu: " + action + ' ' + filename)
socketConnect.sendCommand(action + ":" + filename + "\n")
class SyncStateExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.InfoProvider):
class SyncStateExtension(GObject.GObject, Nautilus.InfoProvider):
def __init__(self):
GObject.GObject.__init__(self)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -23,17 +23,16 @@
#include <QFileInfo>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkProxy>
#include <qdebug.h>
#include "account.h"
#include "clientproxy.h"
#include "configfile.h" // ONLY ACCESS THE STATIC FUNCTIONS!
#include "creds/httpcredentials.h"
#include "simplesslerrorhandler.h"
#include "syncengine.h"
#include "common/syncjournaldb.h"
#include "config.h"
#include "connectionvalidator.h"
#include "cmd.h"
@@ -83,8 +82,6 @@ struct CmdOptions
// So we have to use a global variable
CmdOptions *opts = 0;
const qint64 timeoutToUseMsec = qMax(1000, ConnectionValidator::DefaultCallingIntervalMsec - 5 * 1000);
class EchoDisabler
{
public:
@@ -327,7 +324,6 @@ int main(int argc, char **argv)
options.restartTimes = 3;
options.uplimit = 0;
options.downlimit = 0;
ClientProxy clientProxy;
parseOptions(app.arguments(), &options);
@@ -439,8 +435,6 @@ int main(int argc, char **argv)
} else {
qFatal("Could not read httpproxy. The proxy should have the format \"http://hostname:port\".");
}
} else {
clientProxy.setupQtProxyFromConfig();
}
SimpleSslErrorHandler *sslErrorHandler = new SimpleSslErrorHandler;
@@ -454,24 +448,29 @@ int main(int argc, char **argv)
account->setCredentials(cred);
account->setSslErrorHandler(sslErrorHandler);
//obtain capabilities using event loop
QEventLoop loop;
// Perform a call to get the capabilities.
if (!options.nonShib) {
// Do not do it if '--nonshib' was passed. This mean we should only connect to the 'nonshib'
// dav endpoint. Since we do not get the capabilities, in that case, this has the additional
// side effect that chunking-ng will be disabled. (because otherwise it would use the new
// 'dav' endpoint instead of the nonshib one (which still use the old chunking)
JsonApiJob *job = new JsonApiJob(account, QLatin1String("ocs/v1.php/cloud/capabilities"));
job->setTimeout(timeoutToUseMsec);
QObject::connect(job, &JsonApiJob::jsonReceived, [&](const QJsonDocument &json) {
auto caps = json.object().value("ocs").toObject().value("data").toObject().value("capabilities").toObject();
qDebug() << "Server capabilities" << caps;
account->setCapabilities(caps.toVariantMap());
loop.quit();
});
job->start();
QEventLoop loop;
JsonApiJob *job = new JsonApiJob(account, QLatin1String("ocs/v1.php/cloud/capabilities"));
QObject::connect(job, &JsonApiJob::jsonReceived, [&](const QJsonDocument &json) {
auto caps = json.object().value("ocs").toObject().value("data").toObject().value("capabilities").toObject();
qDebug() << "Server capabilities" << caps;
account->setCapabilities(caps.toVariantMap());
loop.quit();
});
job->start();
loop.exec();
loop.exec();
if (job->reply()->error() != QNetworkReply::NoError){
std::cout<<"Error connecting to server\n";
return EXIT_FAILURE;
if (job->reply()->error() != QNetworkReply::NoError){
std::cout<<"Error connecting to server\n";
return EXIT_FAILURE;
}
}
// much lower age than the default since this utility is usually made to be run right after a change in the tests

View File

@@ -19,8 +19,11 @@
#include "filesystembase.h"
#include <QDateTime>
#include <QDir>
#include <QUrl>
#include <QFile>
#include <QCryptographicHash>
#include <QCoreApplication>
#include <sys/stat.h>
#include <sys/types.h>
@@ -422,6 +425,83 @@ bool FileSystem::remove(const QString &fileName, QString *errorString)
return true;
}
bool FileSystem::moveToTrash(const QString &fileName, QString *errorString)
{
#if defined Q_OS_UNIX && !defined Q_OS_MAC
QString trashPath, trashFilePath, trashInfoPath;
QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME"));
if (xdgDataHome.isEmpty()) {
trashPath = QDir::homePath() + "/.local/share/Trash/"; // trash path that should exist
} else {
trashPath = xdgDataHome + "/Trash/";
}
trashFilePath = trashPath + "files/"; // trash file path contain delete files
trashInfoPath = trashPath + "info/"; // trash info path contain delete files information
if (!(QDir().mkpath(trashFilePath) && QDir().mkpath(trashInfoPath))) {
*errorString = QCoreApplication::translate("FileSystem", "Could not make directories in trash");
return false; //mkpath will return true if path exists
}
QFileInfo f(fileName);
QDir file;
int suffix_number = 1;
if (file.exists(trashFilePath + f.fileName())) { //file in trash already exists, move to "filename.1"
QString path = trashFilePath + f.fileName() + ".";
while (file.exists(path + QString::number(suffix_number))) { //or to "filename.2" if "filename.1" exists, etc
suffix_number++;
}
if (!file.rename(f.absoluteFilePath(), path + QString::number(suffix_number))) { // rename(file old path, file trash path)
*errorString = QCoreApplication::translate("FileSystem", "Could not move '%1' to '%2'")
.arg(f.absoluteFilePath(), path + QString::number(suffix_number));
return false;
}
} else {
if (!file.rename(f.absoluteFilePath(), trashFilePath + f.fileName())) { // rename(file old path, file trash path)
*errorString = QCoreApplication::translate("FileSystem", "Could not move '%1' to '%2'")
.arg(f.absoluteFilePath(), trashFilePath + f.fileName());
return false;
}
}
// create file format for trash info file----- START
QFile infoFile;
if (file.exists(trashInfoPath + f.fileName() + ".trashinfo")) { //TrashInfo file already exists, create "filename.1.trashinfo"
QString filename = trashInfoPath + f.fileName() + "." + QString::number(suffix_number) + ".trashinfo";
infoFile.setFileName(filename); //filename+.trashinfo // create file information file in /.local/share/Trash/info/ folder
} else {
QString filename = trashInfoPath + f.fileName() + ".trashinfo";
infoFile.setFileName(filename); //filename+.trashinfo // create file information file in /.local/share/Trash/info/ folder
}
infoFile.open(QIODevice::ReadWrite);
QTextStream stream(&infoFile); // for write data on open file
QByteArray info = "[Trash Info]\n";
info += "Path=";
info += QUrl::toPercentEncoding(f.absoluteFilePath(), "~_-./");
info += '\n';
info += "DeletionDate=";
info += QDateTime::currentDateTime().toString(Qt::ISODate).toLatin1();
info += '\n';
stream << info;
infoFile.close();
// create info file format of trash file----- END
return true;
#else
Q_UNUSED(fileName)
*errorString = QCoreApplication::translate("FileSystem", "Moving to the trash is not implemented on this platform");
return false;
#endif
}
bool FileSystem::isFileLocked(const QString &fileName)
{
#ifdef Q_OS_WIN
@@ -457,4 +537,22 @@ bool FileSystem::isLnkFile(const QString &filename)
return filename.endsWith(".lnk");
}
bool FileSystem::isJunction(const QString &filename)
{
#ifdef Q_OS_WIN
WIN32_FIND_DATA findData;
HANDLE hFind = FindFirstFileEx((const wchar_t *)filename.utf16(), FindExInfoBasic, &findData, FindExSearchNameMatch, NULL, 0);
if (hFind != INVALID_HANDLE_VALUE) {
FindClose(hFind);
return false;
}
return findData.dwFileAttributes != INVALID_FILE_ATTRIBUTES
&& findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT
&& findData.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
#else
Q_UNUSED(filename);
return false;
#endif
}
} // namespace OCC

View File

@@ -109,6 +109,11 @@ namespace FileSystem {
*/
bool OCSYNC_EXPORT remove(const QString &fileName, QString *errorString = 0);
/**
* Move the specified file or folder to the trash. (Only implemented on linux)
*/
bool OCSYNC_EXPORT moveToTrash(const QString &filename, QString *errorString);
/**
* Replacement for QFile::open(ReadOnly) followed by a seek().
* This version sets a more permissive sharing mode on Windows.
@@ -136,8 +141,16 @@ namespace FileSystem {
*/
bool OCSYNC_EXPORT isFileLocked(const QString &fileName);
/**
* Returns whether the file is a shortcut file (ends with .lnk)
*/
bool OCSYNC_EXPORT isLnkFile(const QString &filename);
/**
* Returns whether the file is a junction (windows only)
*/
bool OCSYNC_EXPORT isJunction(const QString &filename);
/*
* This function takes a path and converts it to a UNC representation of the
* string. That means that it prepends a \\?\ (unless already UNC) and converts

View File

@@ -49,6 +49,12 @@ SqlDatabase::SqlDatabase()
{
}
SqlDatabase::~SqlDatabase()
{
close();
}
bool SqlDatabase::isOpen()
{
return _db != 0;
@@ -184,6 +190,9 @@ QString SqlDatabase::error() const
void SqlDatabase::close()
{
if (_db) {
foreach (auto q, _queries) {
q->finish();
}
SQLITE_DO(sqlite3_close(_db));
if (_errId != SQLITE_OK)
qCWarning(lcSql) << "Closing database failed" << _error;
@@ -217,9 +226,8 @@ sqlite3 *SqlDatabase::sqliteDb()
/* =========================================================================================== */
SqlQuery::SqlQuery(SqlDatabase &db)
: _db(db.sqliteDb())
, _stmt(0)
, _errId(0)
: _sqldb(&db)
, _db(db.sqliteDb())
{
}
@@ -230,18 +238,16 @@ SqlQuery::~SqlQuery()
}
}
SqlQuery::SqlQuery(const QString &sql, SqlDatabase &db)
: _db(db.sqliteDb())
, _stmt(0)
, _errId(0)
SqlQuery::SqlQuery(const QByteArray &sql, SqlDatabase &db)
: _sqldb(&db)
, _db(db.sqliteDb())
{
prepare(sql);
}
int SqlQuery::prepare(const QString &sql, bool allow_failure)
int SqlQuery::prepare(const QByteArray &sql, bool allow_failure)
{
QString s(sql);
_sql = s.trimmed();
_sql = sql.trimmed();
if (_stmt) {
finish();
}
@@ -249,7 +255,7 @@ int SqlQuery::prepare(const QString &sql, bool allow_failure)
int n = 0;
int rc;
do {
rc = sqlite3_prepare_v2(_db, _sql.toUtf8().constData(), -1, &_stmt, 0);
rc = sqlite3_prepare_v2(_db, _sql.constData(), -1, &_stmt, 0);
if ((rc == SQLITE_BUSY) || (rc == SQLITE_LOCKED)) {
n++;
OCC::Utility::usleep(SQLITE_SLEEP_TIME_USEC);
@@ -261,19 +267,32 @@ int SqlQuery::prepare(const QString &sql, bool allow_failure)
_error = QString::fromUtf8(sqlite3_errmsg(_db));
qCWarning(lcSql) << "Sqlite prepare statement error:" << _error << "in" << _sql;
ENFORCE(allow_failure, "SQLITE Prepare error");
} else {
ASSERT(_stmt);
_sqldb->_queries.insert(this);
}
}
return _errId;
}
/**
* There is no overloads to QByteArray::startWith that takes Qt::CaseInsensitive.
* Returns true if 'a' starts with 'b' in a case insensitive way
*/
static bool startsWithInsensitive(const QByteArray &a, const char *b)
{
int len = strlen(b);
return a.size() >= len && qstrnicmp(a.constData(), b, len) == 0;
}
bool SqlQuery::isSelect()
{
return (!_sql.isEmpty() && _sql.startsWith("SELECT", Qt::CaseInsensitive));
return startsWithInsensitive(_sql, "SELECT");
}
bool SqlQuery::isPragma()
{
return (!_sql.isEmpty() && _sql.startsWith("PRAGMA", Qt::CaseInsensitive));
return startsWithInsensitive(_sql, "PRAGMA");
}
bool SqlQuery::exec()
@@ -440,8 +459,13 @@ int SqlQuery::numRowsAffected()
void SqlQuery::finish()
{
if (!_stmt)
return;
SQLITE_DO(sqlite3_finalize(_stmt));
_stmt = 0;
if (_sqldb) {
_sqldb->_queries.remove(this);
}
}
void SqlQuery::reset_and_clear_bindings()
@@ -452,4 +476,18 @@ void SqlQuery::reset_and_clear_bindings()
}
}
bool SqlQuery::initOrReset(const QByteArray &sql, OCC::SqlDatabase &db)
{
ENFORCE(!_sqldb || &db == _sqldb);
_sqldb = &db;
_db = db.sqliteDb();
if (_stmt) {
reset_and_clear_bindings();
return true;
} else {
return prepare(sql) == 0;
}
}
} // namespace OCC

View File

@@ -21,6 +21,7 @@
#include <QObject>
#include <QVariant>
#include <QSet>
#include "ocsynclib.h"
@@ -29,6 +30,8 @@ struct sqlite3_stmt;
namespace OCC {
class SqlQuery;
/**
* @brief The SqlDatabase class
* @ingroup libsync
@@ -38,6 +41,7 @@ class OCSYNC_EXPORT SqlDatabase
Q_DISABLE_COPY(SqlDatabase)
public:
explicit SqlDatabase();
~SqlDatabase();
bool isOpen();
bool openOrCreateReadWrite(const QString &filename);
@@ -62,18 +66,54 @@ private:
sqlite3 *_db;
QString _error; // last error string
int _errId;
friend class SqlQuery;
QSet<SqlQuery *> _queries;
};
/**
* @brief The SqlQuery class
* @ingroup libsync
*
* There is basically 3 ways to initialize and use a query:
*
SqlQuery q1;
[...]
q1.initOrReset(...);
q1.bindValue(...);
q1.exec(...)
*
SqlQuery q2(db);
q2.prepare(...);
[...]
q2.reset_and_clear_bindings();
q2.bindValue(...);
q2.exec(...)
*
SqlQuery q3("...", db);
q3.bindValue(...);
q3.exec(...)
*
*/
class OCSYNC_EXPORT SqlQuery
{
Q_DISABLE_COPY(SqlQuery)
public:
explicit SqlQuery() = default;
explicit SqlQuery(SqlDatabase &db);
explicit SqlQuery(const QString &sql, SqlDatabase &db);
explicit SqlQuery(const QByteArray &sql, SqlDatabase &db);
/**
* Prepare the SqlQuery if it was not prepared yet.
* Otherwise, clear the results and the bindings.
* return false if there is an error
*/
bool initOrReset(const QByteArray &sql, SqlDatabase &db);
/**
* Prepare the SqlQuery.
* If the query was already prepared, this will first call finish(), and re-prepare it.
* This function must only be used if the constructor was setting a SqlDatabase
*/
int prepare(const QByteArray &sql, bool allow_failure = false);
~SqlQuery();
QString error() const;
@@ -82,16 +122,13 @@ public:
/// Checks whether the value at the given column index is NULL
bool nullValue(int index);
QString stringValue(int index);
int intValue(int index);
quint64 int64Value(int index);
QByteArray baValue(int index);
bool isSelect();
bool isPragma();
bool exec();
int prepare(const QString &sql, bool allow_failure = false);
bool next();
void bindValue(int pos, const QVariant &value);
QString lastQuery() const;
@@ -100,11 +137,12 @@ public:
void finish();
private:
sqlite3 *_db;
sqlite3_stmt *_stmt;
SqlDatabase *_sqldb = nullptr;
sqlite3 *_db = nullptr;
sqlite3_stmt *_stmt = nullptr;
QString _error;
int _errId;
QString _sql;
QByteArray _sql;
};
} // namespace OCC

File diff suppressed because it is too large Load Diff

View File

@@ -113,6 +113,12 @@ public:
int _errorCount;
bool _valid;
QByteArray _contentChecksum;
/**
* Returns true if this entry refers to a chunked upload that can be continued.
* (As opposed to a small file transfer which is stored in the db so we can detect the case
* when the upload succeeded, but the connection was dropped before we got the answer)
*/
bool isChunked() const { return _transferid != 0; }
};
struct PollInfo
@@ -159,20 +165,29 @@ public:
void setSelectiveSyncList(SelectiveSyncListType type, const QStringList &list);
/**
* Make sure that on the next sync, fileName is not read from the DB but uses the PROPFIND to
* get the info from the server
* Make sure that on the next sync fileName and its parents are discovered from the server.
*
* Specifically, this sets the md5 field of fileName and all its parents to _invalid_.
* That means its metadata and, if it's a directory, its direct contents.
*
* Specifically, etag (md5 field) of fileName and all its parents are set to _invalid_.
* That causes a metadata difference and a resulting discovery from the remote for the
* affected folders.
*
* Since folders in the selective sync list will not be rediscovered (csync_ftw,
* _csync_detect_update skip them), the _invalid_ marker will stay and it. And any
* _csync_detect_update skip them), the _invalid_ marker will stay. And any
* child items in the db will be ignored when reading a remote tree from the database.
*
* Any setFileRecord() call to affected directories before the next sync run will be
* adjusted to retain the invalid etag via _etagStorageFilter.
*/
void avoidReadFromDbOnNextSync(const QString &fileName) { avoidReadFromDbOnNextSync(fileName.toUtf8()); }
void avoidReadFromDbOnNextSync(const QByteArray &fileName);
/**
* Wipe _etagStorageFilter. Also done implicitly on close().
*/
void clearEtagStorageFilter();
/**
* Ensures full remote discovery happens on the next sync.
*
@@ -213,13 +228,13 @@ public:
/// Store a new or updated record in the database
void setConflictRecord(const ConflictRecord &record);
/// Retrieve a conflict record by path of the _conflict- file
/// Retrieve a conflict record by path of the file with the conflict tag
ConflictRecord conflictRecord(const QByteArray &path);
/// Delete a conflict record by path of the _conflict- file
/// Delete a conflict record by path of the file with the conflict tag
void deleteConflictRecord(const QByteArray &path);
/// Return all paths of _conflict- files with records in the db
/// Return all paths of files with a conflict tag in the name and records in the db
QByteArrayList conflictRecordPaths();
@@ -239,7 +254,7 @@ private:
void commitInternal(const QString &context, bool startTrans = true);
void startTransaction();
void commitTransaction();
QStringList tableColumns(const QString &table);
QVector<QByteArray> tableColumns(const QByteArray &table);
bool checkConnect();
// Same as forceRemoteDiscoveryNextSync but without acquiring the lock
@@ -256,48 +271,56 @@ private:
int _transaction;
bool _metadataTableIsEmpty;
// NOTE! when adding a query, don't forget to reset it in SyncJournalDb::close
QScopedPointer<SqlQuery> _getFileRecordQuery;
QScopedPointer<SqlQuery> _getFileRecordQueryByInode;
QScopedPointer<SqlQuery> _getFileRecordQueryByFileId;
QScopedPointer<SqlQuery> _getFilesBelowPathQuery;
QScopedPointer<SqlQuery> _getAllFilesQuery;
QScopedPointer<SqlQuery> _setFileRecordQuery;
QScopedPointer<SqlQuery> _setFileRecordChecksumQuery;
QScopedPointer<SqlQuery> _setFileRecordLocalMetadataQuery;
QScopedPointer<SqlQuery> _getDownloadInfoQuery;
QScopedPointer<SqlQuery> _setDownloadInfoQuery;
QScopedPointer<SqlQuery> _deleteDownloadInfoQuery;
QScopedPointer<SqlQuery> _getUploadInfoQuery;
QScopedPointer<SqlQuery> _setUploadInfoQuery;
QScopedPointer<SqlQuery> _deleteUploadInfoQuery;
QScopedPointer<SqlQuery> _deleteFileRecordPhash;
QScopedPointer<SqlQuery> _deleteFileRecordRecursively;
QScopedPointer<SqlQuery> _getErrorBlacklistQuery;
QScopedPointer<SqlQuery> _setErrorBlacklistQuery;
QScopedPointer<SqlQuery> _getSelectiveSyncListQuery;
QScopedPointer<SqlQuery> _getChecksumTypeIdQuery;
QScopedPointer<SqlQuery> _getChecksumTypeQuery;
QScopedPointer<SqlQuery> _insertChecksumTypeQuery;
QScopedPointer<SqlQuery> _getDataFingerprintQuery;
QScopedPointer<SqlQuery> _setDataFingerprintQuery1;
QScopedPointer<SqlQuery> _setDataFingerprintQuery2;
QScopedPointer<SqlQuery> _getConflictRecordQuery;
QScopedPointer<SqlQuery> _setConflictRecordQuery;
QScopedPointer<SqlQuery> _deleteConflictRecordQuery;
SqlQuery _getFileRecordQuery;
SqlQuery _getFileRecordQueryByInode;
SqlQuery _getFileRecordQueryByFileId;
SqlQuery _getFilesBelowPathQuery;
SqlQuery _getAllFilesQuery;
SqlQuery _setFileRecordQuery;
SqlQuery _setFileRecordChecksumQuery;
SqlQuery _setFileRecordLocalMetadataQuery;
SqlQuery _getDownloadInfoQuery;
SqlQuery _setDownloadInfoQuery;
SqlQuery _deleteDownloadInfoQuery;
SqlQuery _getUploadInfoQuery;
SqlQuery _setUploadInfoQuery;
SqlQuery _deleteUploadInfoQuery;
SqlQuery _deleteFileRecordPhash;
SqlQuery _deleteFileRecordRecursively;
SqlQuery _getErrorBlacklistQuery;
SqlQuery _setErrorBlacklistQuery;
SqlQuery _getSelectiveSyncListQuery;
SqlQuery _getChecksumTypeIdQuery;
SqlQuery _getChecksumTypeQuery;
SqlQuery _insertChecksumTypeQuery;
SqlQuery _getDataFingerprintQuery;
SqlQuery _setDataFingerprintQuery1;
SqlQuery _setDataFingerprintQuery2;
SqlQuery _getConflictRecordQuery;
SqlQuery _setConflictRecordQuery;
SqlQuery _deleteConflictRecordQuery;
/* This is the list of paths we called avoidReadFromDbOnNextSync on.
* It means that they should not be written to the DB in any case since doing
* that would write the etag and would void the purpose of avoidReadFromDbOnNextSync
/* Storing etags to these folders, or their parent folders, is filtered out.
*
* When avoidReadFromDbOnNextSync() is called some etags to _invalid_ in the
* database. If this is done during a sync run, a later propagation job might
* undo that by writing the correct etag to the database instead. This filter
* will prevent this write and instead guarantee the _invalid_ etag stays in
* place.
*
* The list is cleared on close() (end of sync run) and explicitly with
* clearEtagStorageFilter() (start of sync run).
*
* The contained paths have a trailing /.
*/
QList<QByteArray> _avoidReadFromDbOnNextSyncFilter;
QList<QByteArray> _etagStorageFilter;
/** The journal mode to use for the db.
*
* Typically WAL initially, but may be set to other modes via environment
* variable, for specific filesystems, or when WAL fails in a particular way.
*/
QString _journalMode;
QByteArray _journalMode;
};
bool OCSYNC_EXPORT

View File

@@ -109,23 +109,23 @@ public:
QString _file;
QString _renameTarget;
/// The last X-Request-ID of the request that failled
QByteArray _requestId;
bool isValid() const;
};
/** Represents a conflict in the conflicts table.
*
* In the following the "conflict file" is the file with the "_conflict-"
* tag and the base file is the file that its a conflict for. So if
* a/foo.txt is the base file, its conflict file could be
* a/foo_conflict-1234.txt.
* In the following the "conflict file" is the file that has the conflict
* tag in the filename, and the base file is the file that it's a conflict for.
* So if "a/foo.txt" is the base file, its conflict file could be
* "a/foo (conflicted copy 1234).txt".
*/
class OCSYNC_EXPORT ConflictRecord
{
public:
/** Path to the _conflict- file
*
* So if a/foo.txt has a conflict, this path would point to
* a/foo_conflict-1234.txt.
/** Path to the file with the conflict tag in the name
*
* The path is sync-folder relative.
*/

View File

@@ -254,15 +254,17 @@ void Utility::usleep(int usec)
QThread::usleep(usec);
}
bool Utility::fsCasePreserving()
{
#ifdef WITH_TESTING
// This can be overriden from the tests
OCSYNC_EXPORT bool fsCasePreserving_override = []()-> bool {
QByteArray env = qgetenv("OWNCLOUD_TEST_CASE_PRESERVING");
if (!env.isEmpty())
return env.toInt();
#endif
return Utility::isWindows() || Utility::isMac();
}();
return isWindows() || isMac();
bool Utility::fsCasePreserving()
{
return fsCasePreserving_override;
}
bool Utility::fileNamesEqual(const QString &fn1, const QString &fn2)
@@ -542,18 +544,29 @@ QUrl Utility::concatUrlPath(const QUrl &url, const QString &concatPath,
return tmpUrl;
}
QString Utility::makeConflictFileName(const QString &fn, const QDateTime &dt)
QString Utility::makeConflictFileName(
const QString &fn, const QDateTime &dt, const QString &user)
{
QString conflictFileName(fn);
// Add _conflict-XXXX before the extension.
// Add conflict tag before the extension.
int dotLocation = conflictFileName.lastIndexOf('.');
// If no extension, add it at the end (take care of cases like foo/.hidden or foo.bar/file)
if (dotLocation <= conflictFileName.lastIndexOf('/') + 1) {
dotLocation = conflictFileName.size();
}
QString timeString = dt.toString("yyyyMMdd-hhmmss");
conflictFileName.insert(dotLocation, "_conflict-" + timeString);
QString conflictMarker = QStringLiteral(" (conflicted copy ");
if (!user.isEmpty()) {
// Don't allow parens in the user name, to ensure
// we can find the beginning and end of the conflict tag.
const auto userName = sanitizeForFileName(user).replace('(', '_').replace(')', '_');
conflictMarker.append(userName);
conflictMarker.append(' ');
}
conflictMarker.append(dt.toString("yyyy-MM-dd hhmmss"));
conflictMarker.append(')');
conflictFileName.insert(dotLocation, conflictMarker);
return conflictFileName;
}
@@ -566,13 +579,28 @@ bool Utility::isConflictFile(const char *name)
bname = name;
}
return std::strstr(bname, "_conflict-");
// Old pattern
if (std::strstr(bname, "_conflict-"))
return true;
// New pattern
if (std::strstr(bname, "(conflicted copy"))
return true;
return false;
}
bool Utility::isConflictFile(const QString &name)
{
auto bname = name.midRef(name.lastIndexOf('/') + 1);
return bname.contains("_conflict-", Utility::fsCasePreserving() ? Qt::CaseInsensitive : Qt::CaseSensitive);
if (bname.contains(QStringLiteral("_conflict-")))
return true;
if (bname.contains(QStringLiteral("(conflicted copy")))
return true;
return false;
}
QByteArray Utility::conflictFileBaseName(const QByteArray &conflictName)
@@ -580,19 +608,44 @@ QByteArray Utility::conflictFileBaseName(const QByteArray &conflictName)
// This function must be able to deal with conflict files for conflict files.
// To do this, we scan backwards, for the outermost conflict marker and
// strip only that to generate the conflict file base name.
int from = conflictName.size();
while (from != -1) {
auto start = conflictName.lastIndexOf("_conflict-", from);
if (start == -1)
return "";
from = start - 1;
auto startOld = conflictName.lastIndexOf("_conflict-");
auto end = conflictName.indexOf('.', start);
if (end == -1)
end = conflictName.size();
return conflictName.left(start) + conflictName.mid(end);
// A single space before "(conflicted copy" is considered part of the tag
auto startNew = conflictName.lastIndexOf("(conflicted copy");
if (startNew > 0 && conflictName[startNew - 1] == ' ')
startNew -= 1;
// The rightmost tag is relevant
auto tagStart = qMax(startOld, startNew);
if (tagStart == -1)
return "";
// Find the end of the tag
auto tagEnd = conflictName.size();
auto dot = conflictName.lastIndexOf('.'); // dot could be part of user name for new tag!
if (dot > tagStart)
tagEnd = dot;
if (tagStart == startNew) {
auto paren = conflictName.indexOf(')', tagStart);
if (paren != -1)
tagEnd = paren + 1;
}
return "";
return conflictName.left(tagStart) + conflictName.mid(tagEnd);
}
QString Utility::sanitizeForFileName(const QString &name)
{
const auto invalid = QStringLiteral("/?<>\\:*|\"");
QString result;
result.reserve(name.size());
for (const auto c : name) {
if (!invalid.contains(c)
&& c.category() != QChar::Other_Control
&& c.category() != QChar::Other_Format) {
result.append(c);
}
}
return result;
}
} // namespace OCC

View File

@@ -182,9 +182,24 @@ namespace Utility {
with the given parent. If no parent is specified, the caller must destroy the settings */
OCSYNC_EXPORT std::unique_ptr<QSettings> settingsWithGroup(const QString &group, QObject *parent = 0);
/** Sanitizes a string that shall become part of a filename.
*
* Filters out reserved characters like
* - unicode control and format characters
* - reserved characters: /, ?, <, >, \, :, *, |, and "
*
* Warning: This does not sanitize the whole resulting string, so
* - unix reserved filenames ('.', '..')
* - trailing periods and spaces
* - windows reserved filenames ('CON' etc)
* will pass unchanged.
*/
OCSYNC_EXPORT QString sanitizeForFileName(const QString &name);
/** Returns a file name based on \a fn that's suitable for a conflict.
*/
OCSYNC_EXPORT QString makeConflictFileName(const QString &fn, const QDateTime &dt);
OCSYNC_EXPORT QString makeConflictFileName(
const QString &fn, const QDateTime &dt, const QString &user);
/** Returns whether a file name indicates a conflict file
*/

View File

@@ -1,9 +1,6 @@
PROJECT( CrashReporter )
cmake_policy(SET CMP0017 NEW)
list(APPEND crashreporter_SOURCES main.cpp)
list(APPEND crashreporter_RC resources.qrc)
# TODO: differentiate release channel
# if(BUILD_RELEASE)
# set(CRASHREPORTER_RELEASE_CHANNEL "release")
@@ -11,9 +8,27 @@ list(APPEND crashreporter_RC resources.qrc)
set(CRASHREPORTER_RELEASE_CHANNEL "nightly")
# endif()
# Theme
if(DEFINED OEM_THEME_DIR AND EXISTS "${OEM_THEME_DIR}/theme/colored")
set(CRASHREPORTER_ICON_DIR "${OEM_THEME_DIR}/theme/colored")
else()
set(CRASHREPORTER_ICON_DIR "${CMAKE_SOURCE_DIR}/theme/colored")
endif()
set(CRASHREPORTER_ICON_FILENAME "${APPLICATION_ICON_NAME}-icon.png")
set(CRASHREPORTER_ICON ":/${CRASHREPORTER_ICON_FILENAME}")
set(CRASHREPORTER_ICON_SIZE "128")
set(CRASHREPORTER_ICON_PATH "${CRASHREPORTER_ICON_DIR}/${CRASHREPORTER_ICON_SIZE}-${CRASHREPORTER_ICON_FILENAME}")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources.qrc.in
${CMAKE_CURRENT_BINARY_DIR}/resources.qrc)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CrashReporterConfig.h.in
${CMAKE_CURRENT_BINARY_DIR}/CrashReporterConfig.h)
# Sources
list(APPEND crashreporter_SOURCES main.cpp)
list(APPEND crashreporter_RC "${CMAKE_CURRENT_BINARY_DIR}/resources.qrc")
if(NOT BUILD_LIBRARIES_ONLY)
@@ -21,13 +36,14 @@ if(NOT BUILD_LIBRARIES_ONLY)
${crashreporter_SOURCES}
${crashreporter_HEADERS_MOC}
${crashreporter_UI_HEADERS}
${crashreporter_RC_RCC}
${crashreporter_RC}
)
find_package(Qt5 REQUIRED COMPONENTS Widgets)
target_include_directories(${CRASHREPORTER_EXECUTABLE} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
set_target_properties(${CRASHREPORTER_EXECUTABLE} PROPERTIES AUTOMOC ON)
set_target_properties(${CRASHREPORTER_EXECUTABLE} PROPERTIES AUTORCC ON)
set_target_properties(${CRASHREPORTER_EXECUTABLE} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY} )
set_target_properties(${CRASHREPORTER_EXECUTABLE} PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/${APPLICATION_EXECUTABLE}" )
target_link_libraries(${CRASHREPORTER_EXECUTABLE}

View File

@@ -1,5 +0,0 @@
<RCC>
<qresource prefix="/">
<file alias="owncloud-icon.png">../../theme/colored/owncloud-icon-128.png</file>
</qresource>
</RCC>

View File

@@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/">
<file alias="@CRASHREPORTER_ICON_FILENAME@">@CRASHREPORTER_ICON_PATH@</file>
</qresource>
</RCC>

View File

@@ -17,4 +17,3 @@
#cmakedefine HAVE___MINGW_ASPRINTF 1
#cmakedefine HAVE_ASPRINTF 1
#cmakedefine WITH_TESTING 1

View File

@@ -126,12 +126,7 @@ int csync_update(CSYNC *ctx) {
}
int csync_reconcile(CSYNC *ctx) {
int rc = -1;
if (ctx == NULL) {
errno = EBADF;
return -1;
}
Q_ASSERT(ctx);
ctx->status_code = CSYNC_STATUS_OK;
/* Reconciliation for local replica */
@@ -140,54 +135,31 @@ int csync_reconcile(CSYNC *ctx) {
ctx->current = LOCAL_REPLICA;
rc = csync_reconcile_updates(ctx);
csync_reconcile_updates(ctx);
qCInfo(lcCSync) << "Reconciliation for local replica took " << timer.elapsed() / 1000.
<< "seconds visiting " << ctx->local.files.size() << " files.";
if (rc < 0) {
if (!CSYNC_STATUS_IS_OK(ctx->status_code)) {
ctx->status_code = csync_errno_to_status( errno, CSYNC_STATUS_RECONCILE_ERROR );
}
return rc;
}
/* Reconciliation for remote replica */
timer.restart();
ctx->current = REMOTE_REPLICA;
rc = csync_reconcile_updates(ctx);
csync_reconcile_updates(ctx);
qCInfo(lcCSync) << "Reconciliation for remote replica took " << timer.elapsed() / 1000.
<< "seconds visiting " << ctx->remote.files.size() << " files.";
if (rc < 0) {
if (!CSYNC_STATUS_IS_OK(ctx->status_code)) {
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_RECONCILE_ERROR );
}
return rc;
}
ctx->status |= CSYNC_STATUS_RECONCILE;
rc = 0;
return rc;
return 0;
}
/*
* local visitor which calls the user visitor with repacked stat info.
*/
static int _csync_treewalk_visitor(csync_file_stat_t *cur, CSYNC * ctx) {
int rc = 0;
csync_treewalk_visit_func *visitor = NULL;
_csync_treewalk_context *twctx = NULL;
static int _csync_treewalk_visitor(csync_file_stat_t *cur, CSYNC * ctx, const csync_treewalk_visit_func &visitor) {
csync_s::FileMap *other_tree = nullptr;
if (ctx == NULL) {
return -1;
}
/* we need the opposite tree! */
switch (ctx->current) {
case LOCAL_REPLICA:
@@ -220,80 +192,41 @@ static int _csync_treewalk_visitor(csync_file_stat_t *cur, CSYNC * ctx) {
ctx->status_code = CSYNC_STATUS_OK;
twctx = (_csync_treewalk_context*) ctx->callbacks.userdata;
if (twctx == NULL) {
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
return -1;
}
if (twctx->instruction_filter > 0 &&
!(twctx->instruction_filter & cur->instruction) ) {
return 0;
}
visitor = (csync_treewalk_visit_func*)(twctx->user_visitor);
if (visitor != NULL) {
rc = (*visitor)(cur, other, twctx->userdata);
return rc;
}
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
return -1;
Q_ASSERT(visitor);
return visitor(cur, other);
}
/*
* treewalk function, called from its wrappers below.
*
* it encapsulates the user visitor function, the filter and the userdata
* into a treewalk_context structure and calls the rb treewalk function,
* which calls the local _csync_treewalk_visitor in this module.
* The user visitor is called from there.
*/
static int _csync_walk_tree(CSYNC *ctx, csync_s::FileMap *tree, csync_treewalk_visit_func *visitor, int filter)
static int _csync_walk_tree(CSYNC *ctx, csync_s::FileMap &tree, const csync_treewalk_visit_func &visitor)
{
_csync_treewalk_context tw_ctx;
int rc = 0;
tw_ctx.userdata = ctx->callbacks.userdata;
tw_ctx.user_visitor = visitor;
tw_ctx.instruction_filter = filter;
ctx->callbacks.userdata = &tw_ctx;
for (auto &pair : *tree) {
if (_csync_treewalk_visitor(pair.second.get(), ctx) < 0) {
rc = -1;
break;
for (auto &pair : tree) {
if (_csync_treewalk_visitor(pair.second.get(), ctx, visitor) < 0) {
return -1;
}
}
if( rc < 0 ) {
if( ctx->status_code == CSYNC_STATUS_OK )
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_TREE_ERROR);
}
ctx->callbacks.userdata = tw_ctx.userdata;
return rc;
return 0;
}
/*
* wrapper function for treewalk on the remote tree
*/
int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter)
int csync_walk_remote_tree(CSYNC *ctx, const csync_treewalk_visit_func &visitor)
{
ctx->status_code = CSYNC_STATUS_OK;
ctx->current = REMOTE_REPLICA;
return _csync_walk_tree(ctx, &ctx->remote.files, visitor, filter);
return _csync_walk_tree(ctx, ctx->remote.files, visitor);
}
/*
* wrapper function for treewalk on the local tree
*/
int csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter)
int csync_walk_local_tree(CSYNC *ctx, const csync_treewalk_visit_func &visitor)
{
ctx->status_code = CSYNC_STATUS_OK;
ctx->current = LOCAL_REPLICA;
return _csync_walk_tree(ctx, &ctx->local.files, visitor, filter);
return _csync_walk_tree(ctx, ctx->local.files, visitor);
}
int csync_s::reinitialize() {
@@ -310,9 +243,6 @@ int csync_s::reinitialize() {
renames.folder_renamed_from.clear();
renames.folder_renamed_to.clear();
local_discovery_style = LocalDiscoveryStyle::FilesystemOnly;
locally_touched_dirs.clear();
status = CSYNC_STATUS_INIT;
SAFE_FREE(error_string);

View File

@@ -40,6 +40,7 @@
#include <stdint.h>
#include <sys/types.h>
#include <config_csync.h>
#include <functional>
#include <memory>
#include <QByteArray>
#include "common/remotepermissions.h"
@@ -64,40 +65,17 @@ enum csync_status_codes_e {
CSYNC_STATUS_ERROR = 1024, /* don't use this code,
*/
CSYNC_STATUS_UNSUCCESSFUL, /* Unspecific problem happend */
CSYNC_STATUS_NO_LOCK, /* OBSOLETE does not happen anymore */
CSYNC_STATUS_STATEDB_LOAD_ERROR, /* Statedb can not be loaded. */
CSYNC_STATUS_STATEDB_CORRUPTED, /* Statedb is corrupted */
CSYNC_STATUS_NO_MODULE, /* URL passed to csync does not start with owncloud:// or ownclouds:// */
CSYNC_STATUS_TIMESKEW, /* OBSOLETE */
CSYNC_STATUS_FILESYSTEM_UNKNOWN, /* UNUSED */
CSYNC_STATUS_TREE_ERROR, /* csync trees could not be created */
CSYNC_STATUS_PARAM_ERROR, /* parameter is zero where not expected */
CSYNC_STATUS_UPDATE_ERROR, /* general update or discovery error */
CSYNC_STATUS_RECONCILE_ERROR, /* general reconcile error */
CSYNC_STATUS_PROPAGATE_ERROR, /* OBSOLETE */
CSYNC_STATUS_REMOTE_ACCESS_ERROR, /* UNUSED */
CSYNC_STATUS_REMOTE_CREATE_ERROR, /* UNUSED */
CSYNC_STATUS_REMOTE_STAT_ERROR, /* UNUSED */
CSYNC_STATUS_LOCAL_CREATE_ERROR, /* UNUSED */
CSYNC_STATUS_LOCAL_STAT_ERROR, /* UNUSED */
CSYNC_STATUS_PROXY_ERROR, /* UNUSED */
CSYNC_STATUS_LOOKUP_ERROR, /* Neon fails to find proxy. Almost OBSOLETE */
CSYNC_STATUS_SERVER_AUTH_ERROR, /* UNUSED */
CSYNC_STATUS_PROXY_AUTH_ERROR, /* UNUSED */
CSYNC_STATUS_CONNECT_ERROR, /* neon driven connection failed */
CSYNC_STATUS_TIMEOUT, /* UNUSED */
CSYNC_STATUS_HTTP_ERROR, /* UNUSED */
CSYNC_STATUS_PERMISSION_DENIED, /* */
CSYNC_STATUS_NOT_FOUND,
CSYNC_STATUS_FILE_EXISTS,
CSYNC_STATUS_OUT_OF_SPACE,
CSYNC_STATUS_QUOTA_EXCEEDED, /* UNUSED */
CSYNC_STATUS_SERVICE_UNAVAILABLE,
CSYNC_STATUS_STORAGE_UNAVAILABLE,
CSYNC_STATUS_FILE_SIZE_ERROR,
CSYNC_STATUS_CONTEXT_LOST,
CSYNC_STATUS_MERGE_FILETREE_ERROR,
CSYNC_STATUS_CSYNC_STATUS_ERROR,
CSYNC_STATUS_OPENDIR_ERROR,
CSYNC_STATUS_READDIR_ERROR,
CSYNC_STATUS_OPEN_ERROR,
@@ -159,7 +137,9 @@ enum ItemType {
ItemTypeFile = 0,
ItemTypeSoftLink = 1,
ItemTypeDirectory = 2,
ItemTypeSkip = 3
ItemTypeSkip = 3,
ItemTypeVirtualFile = 4,
ItemTypeVirtualFileDownload = 5
};
@@ -305,29 +285,27 @@ CSYNC_STATUS OCSYNC_EXPORT csync_get_status(CSYNC *ctx);
/* Used for special modes or debugging */
int OCSYNC_EXPORT csync_set_status(CSYNC *ctx, int status);
typedef int csync_treewalk_visit_func(csync_file_stat_t *cur, csync_file_stat_t *other, void*);
using csync_treewalk_visit_func = std::function<int(csync_file_stat_t *cur, csync_file_stat_t *other)>;
/**
* @brief Walk the local file tree and call a visitor function for each file.
*
* @param ctx The csync context.
* @param visitor A callback function to handle the file info.
* @param filter A filter, built from or'ed csync_instructions_e
*
* @return 0 on success, less than 0 if an error occurred.
*/
int OCSYNC_EXPORT csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter);
int OCSYNC_EXPORT csync_walk_local_tree(CSYNC *ctx, const csync_treewalk_visit_func &visitor);
/**
* @brief Walk the remote file tree and call a visitor function for each file.
*
* @param ctx The csync context.
* @param visitor A callback function to handle the file info.
* @param filter A filter, built from and'ed csync_instructions_e
*
* @return 0 on success, less than 0 if an error occurred.
*/
int OCSYNC_EXPORT csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter);
int OCSYNC_EXPORT csync_walk_remote_tree(CSYNC *ctx, const csync_treewalk_visit_func &visitor);
/**
* @brief Get the csync status string.

View File

@@ -33,9 +33,12 @@
#include "csync_misc.h"
#include "common/utility.h"
#include "../version.h"
#include <QString>
#include <QFileInfo>
#include <QFile>
#include <QDir>
/** Expands C-like escape sequences (in place)
@@ -217,8 +220,8 @@ static CSYNC_EXCLUDE_TYPE _csync_excluded_common(const char *path, bool excludeC
}
#endif
/* We create a desktop.ini on Windows for the sidebar icon, make sure we don't sync them. */
if (blen == 11) {
/* We create a Desktop.ini on Windows for the sidebar icon, make sure we don't sync it. */
if (blen == 11 && path == bname) {
rc = csync_fnmatch("Desktop.ini", bname, 0);
if (rc == 0) {
match = CSYNC_FILE_SILENTLY_EXCLUDED;
@@ -240,6 +243,7 @@ static CSYNC_EXCLUDE_TYPE _csync_excluded_common(const char *path, bool excludeC
using namespace OCC;
ExcludedFiles::ExcludedFiles()
: _clientVersion(MIRALL_VERSION_MAJOR, MIRALL_VERSION_MINOR, MIRALL_VERSION_PATCH)
{
// Windows used to use PathMatchSpec which allows *foo to match abc/deffoo.
_wildcardsMatchSlash = Utility::isWindows();
@@ -278,6 +282,11 @@ void ExcludedFiles::setWildcardsMatchSlash(bool onoff)
prepare();
}
void ExcludedFiles::setClientVersion(ExcludedFiles::Version version)
{
_clientVersion = version;
}
bool ExcludedFiles::reloadExcludeFiles()
{
_allExcludes.clear();
@@ -290,6 +299,10 @@ bool ExcludedFiles::reloadExcludeFiles()
}
while (!f.atEnd()) {
QByteArray line = f.readLine().trimmed();
if (line.startsWith("#!version")) {
if (!versionDirectiveKeepNextLine(line))
f.readLine();
}
if (line.isEmpty() || line.startsWith('#'))
continue;
csync_exclude_expand_escapes(line);
@@ -301,6 +314,32 @@ bool ExcludedFiles::reloadExcludeFiles()
return success;
}
bool ExcludedFiles::versionDirectiveKeepNextLine(const QByteArray &directive) const
{
if (!directive.startsWith("#!version"))
return true;
QByteArrayList args = directive.split(' ');
if (args.size() != 3)
return true;
QByteArray op = args[1];
QByteArrayList argVersions = args[2].split('.');
if (argVersions.size() != 3)
return true;
auto argVersion = std::make_tuple(argVersions[0].toInt(), argVersions[1].toInt(), argVersions[2].toInt());
if (op == "<=")
return _clientVersion <= argVersion;
if (op == "<")
return _clientVersion < argVersion;
if (op == ">")
return _clientVersion > argVersion;
if (op == ">=")
return _clientVersion >= argVersion;
if (op == "==")
return _clientVersion == argVersion;
return true;
}
bool ExcludedFiles::isExcluded(
const QString &filePath,
const QString &basePath,

View File

@@ -66,6 +66,8 @@ class OCSYNC_EXPORT ExcludedFiles : public QObject
{
Q_OBJECT
public:
typedef std::tuple<int, int, int> Version;
ExcludedFiles();
~ExcludedFiles();
@@ -114,6 +116,11 @@ public:
*/
void setWildcardsMatchSlash(bool onoff);
/**
* Sets the client version, only used for testing.
*/
void setClientVersion(Version version);
/**
* Generate a hook for traversal exclude pattern matching
* that csync can use.
@@ -131,6 +138,23 @@ public slots:
bool reloadExcludeFiles();
private:
/**
* Returns true if the version directive indicates the next line
* should be skipped.
*
* A version directive has the form "#!version <op> <version>"
* where <op> can be <, <=, ==, >, >= and <version> can be any version
* like 2.5.0.
*
* Example:
*
* #!version < 2.5.0
* myexclude
*
* Would enable the "myexclude" pattern only for versions before 2.5.0.
*/
bool versionDirectiveKeepNextLine(const QByteArray &directive) const;
/**
* @brief Match the exclude pattern against the full path.
*
@@ -216,6 +240,12 @@ private:
*/
bool _wildcardsMatchSlash = false;
/**
* The client version. Used to evaluate version-dependent excludes,
* see versionDirectiveKeepNextLine().
*/
Version _clientVersion;
friend class ExcludedFilesTest;
};

View File

@@ -32,19 +32,8 @@
* should always be larger than the highest system errno. */
#define CSYNC_CUSTOM_ERRNO_BASE 10000
#define ERRNO_GENERAL_ERROR CSYNC_CUSTOM_ERRNO_BASE+2
#define ERRNO_LOOKUP_ERROR CSYNC_CUSTOM_ERRNO_BASE+3
#define ERRNO_USER_UNKNOWN_ON_SERVER CSYNC_CUSTOM_ERRNO_BASE+4
#define ERRNO_PROXY_AUTH CSYNC_CUSTOM_ERRNO_BASE+5
#define ERRNO_CONNECT CSYNC_CUSTOM_ERRNO_BASE+6
#define ERRNO_TIMEOUT CSYNC_CUSTOM_ERRNO_BASE+7
#define ERRNO_PRECONDITION CSYNC_CUSTOM_ERRNO_BASE+8
#define ERRNO_RETRY CSYNC_CUSTOM_ERRNO_BASE+9
#define ERRNO_REDIRECT CSYNC_CUSTOM_ERRNO_BASE+10
#define ERRNO_WRONG_CONTENT CSYNC_CUSTOM_ERRNO_BASE+11
#define ERRNO_ERROR_STRING CSYNC_CUSTOM_ERRNO_BASE+13
#define ERRNO_SERVICE_UNAVAILABLE CSYNC_CUSTOM_ERRNO_BASE+14
#define ERRNO_USER_ABORT CSYNC_CUSTOM_ERRNO_BASE+16
#define ERRNO_STORAGE_UNAVAILABLE CSYNC_CUSTOM_ERRNO_BASE+17
#define ERRNO_FORBIDDEN CSYNC_CUSTOM_ERRNO_BASE+18

View File

@@ -78,24 +78,6 @@ CSYNC_STATUS csync_errno_to_status(int error, CSYNC_STATUS default_status)
status = CSYNC_STATUS_OK;
break;
/* The custom errnos first. */
case ERRNO_GENERAL_ERROR:
status = CSYNC_STATUS_UNSUCCESSFUL;
break;
case ERRNO_LOOKUP_ERROR: /* In Neon: Server or proxy hostname lookup failed */
status = CSYNC_STATUS_LOOKUP_ERROR;
break;
case ERRNO_USER_UNKNOWN_ON_SERVER: /* Neon: User authentication on server failed. */
status = CSYNC_STATUS_SERVER_AUTH_ERROR;
break;
case ERRNO_PROXY_AUTH:
status = CSYNC_STATUS_PROXY_AUTH_ERROR; /* Neon: User authentication on proxy failed */
break;
case ERRNO_CONNECT:
status = CSYNC_STATUS_CONNECT_ERROR; /* Network: Connection error */
break;
case ERRNO_TIMEOUT:
status = CSYNC_STATUS_TIMEOUT; /* Network: Timeout error */
break;
case ERRNO_SERVICE_UNAVAILABLE:
status = CSYNC_STATUS_SERVICE_UNAVAILABLE; /* Service temporarily down */
break;
@@ -105,9 +87,6 @@ CSYNC_STATUS csync_errno_to_status(int error, CSYNC_STATUS default_status)
case EFBIG:
status = CSYNC_STATUS_FILE_SIZE_ERROR; /* File larger than 2MB */
break;
case ERRNO_PRECONDITION:
case ERRNO_RETRY:
case ERRNO_REDIRECT:
case ERRNO_WRONG_CONTENT:
status = CSYNC_STATUS_HTTP_ERROR;
break;
@@ -125,14 +104,12 @@ CSYNC_STATUS csync_errno_to_status(int error, CSYNC_STATUS default_status)
case EEXIST: /* File exists */
status = CSYNC_STATUS_FILE_EXISTS;
break;
case EINVAL:
status = CSYNC_STATUS_PARAM_ERROR;
break;
case ENOSPC:
status = CSYNC_STATUS_OUT_OF_SPACE;
break;
/* All the remaining basic errnos: */
case EINVAL: /* Invalid argument */
case EIO: /* I/O error */
case ESRCH: /* No such process */
case EINTR: /* Interrupted system call */
@@ -162,7 +139,6 @@ CSYNC_STATUS csync_errno_to_status(int error, CSYNC_STATUS default_status)
case EMLINK: /* Too many links */
case EPIPE: /* Broken pipe */
case ERRNO_ERROR_STRING:
default:
status = default_status;
}

View File

@@ -190,20 +190,22 @@ struct OCSYNC_EXPORT csync_s {
*/
bool read_remote_from_db = false;
LocalDiscoveryStyle local_discovery_style = LocalDiscoveryStyle::FilesystemOnly;
/**
* List of folder-relative directory paths that should be scanned on the
* filesystem if the local_discovery_style suggests it.
*
* Their parents will be scanned too. The paths don't start with a /.
*/
std::set<QByteArray> locally_touched_dirs;
std::function<bool(const QByteArray &)> should_discover_locally_fn;
bool ignore_hidden_files = true;
bool upload_conflict_files = false;
/**
* Whether new remote files should start out as virtual.
*/
bool new_files_are_virtual = false;
/**
* The suffix to use for virtual files.
*/
QByteArray virtual_file_suffix;
csync_s(const char *localUri, OCC::SyncJournalDb *statedb);
~csync_s();
int reinitialize();
@@ -216,17 +218,6 @@ struct OCSYNC_EXPORT csync_s {
csync_s &operator=(const csync_s &) = delete;
};
/*
* context for the treewalk function
*/
struct _csync_treewalk_context_s
{
csync_treewalk_visit_func *user_visitor;
int instruction_filter;
void *userdata;
};
typedef struct _csync_treewalk_context_s _csync_treewalk_context;
void set_errno_from_http_errcode( int err );
/**

View File

@@ -92,7 +92,7 @@ static csync_file_stat_t *_csync_check_ignored(csync_s::FileMap *tree, const Byt
* (timestamp is newer), it is not overwritten. If both files, on the
* source and the destination, have been changed, the newer file wins.
*/
static int _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx) {
static void _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx) {
csync_s::FileMap *our_tree = nullptr;
csync_s::FileMap *other_tree = nullptr;
@@ -110,7 +110,7 @@ static int _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx) {
break;
}
csync_file_stat_t *other = other_tree->findFile(cur->path);;
csync_file_stat_t *other = other_tree->findFile(cur->path);
if (!other) {
/* Check the renamed path as well. */
@@ -122,6 +122,31 @@ static int _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx) {
/* If it is ignored, other->instruction will be IGNORE so this one will also be ignored */
}
// If the user adds a file locally check whether a virtual file for that name exists.
// If so, go to "potential conflict" mode by switching the remote entry to be a
// real file.
if (!other
&& ctx->current == LOCAL_REPLICA
&& cur->instruction == CSYNC_INSTRUCTION_NEW
&& cur->type != ItemTypeVirtualFile) {
// Check if we have a virtual file entry in the remote tree
auto virtualFilePath = cur->path;
virtualFilePath.append(ctx->virtual_file_suffix);
other = other_tree->findFile(virtualFilePath);
if (!other) {
/* Check the renamed path as well. */
other = other_tree->findFile(csync_rename_adjust_parent_path(ctx, virtualFilePath));
}
if (other && other->type == ItemTypeVirtualFile) {
qCInfo(lcReconcile) << "Found virtual file for local" << cur->path << "in remote tree";
other->path = cur->path;
other->type = ItemTypeVirtualFileDownload;
other->instruction = CSYNC_INSTRUCTION_EVAL;
} else {
other = nullptr;
}
}
/* file only found on current replica */
if (!other) {
switch(cur->instruction) {
@@ -141,6 +166,15 @@ static int _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx) {
cur->instruction = CSYNC_INSTRUCTION_NEW;
break;
}
/* If the local virtual file is gone, it should be reestablished.
* Unless the base file is seen in the local tree now. */
if (cur->type == ItemTypeVirtualFile
&& ctx->current == REMOTE_REPLICA
&& cur->path.endsWith(ctx->virtual_file_suffix)
&& !other_tree->findFile(cur->path.left(cur->path.size() - ctx->virtual_file_suffix.size()))) {
cur->instruction = CSYNC_INSTRUCTION_NEW;
break;
}
cur->instruction = CSYNC_INSTRUCTION_REMOVE;
break;
case CSYNC_INSTRUCTION_EVAL_RENAME: {
@@ -369,7 +403,10 @@ static int _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx) {
cur->instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
other->instruction = CSYNC_INSTRUCTION_NONE;
} else {
cur->instruction = CSYNC_INSTRUCTION_SYNC;
if (cur->instruction != CSYNC_INSTRUCTION_NEW
&& cur->instruction != CSYNC_INSTRUCTION_SYNC) {
cur->instruction = CSYNC_INSTRUCTION_SYNC;
}
other->instruction = CSYNC_INSTRUCTION_NONE;
}
break;
@@ -388,6 +425,17 @@ static int _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx) {
if (cur->instruction == CSYNC_INSTRUCTION_EVAL)
cur->instruction = CSYNC_INSTRUCTION_NEW;
break;
case CSYNC_INSTRUCTION_NONE:
// NONE/NONE on virtual files might become a REMOVE if the base file
// is found in the local tree.
if (cur->type == ItemTypeVirtualFile
&& other->instruction == CSYNC_INSTRUCTION_NONE
&& ctx->current == LOCAL_REPLICA
&& cur->path.endsWith(ctx->virtual_file_suffix)
&& ctx->local.files.findFile(cur->path.left(cur->path.size() - ctx->virtual_file_suffix.size()))) {
cur->instruction = CSYNC_INSTRUCTION_REMOVE;
}
break;
default:
break;
}
@@ -434,11 +482,9 @@ static int _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx) {
cur->path.constData());
}
}
return 0;
}
int csync_reconcile_updates(CSYNC *ctx) {
void csync_reconcile_updates(CSYNC *ctx) {
csync_s::FileMap *tree = nullptr;
switch (ctx->current) {
@@ -453,12 +499,8 @@ int csync_reconcile_updates(CSYNC *ctx) {
}
for (auto &pair : *tree) {
if (_csync_merge_algorithm_visitor(pair.second.get(), ctx) < 0) {
ctx->status_code = CSYNC_STATUS_RECONCILE_ERROR;
return -1;
}
_csync_merge_algorithm_visitor(pair.second.get(), ctx);
}
return 0;
}
/* vim: set ts=8 sw=2 et cindent: */

View File

@@ -46,11 +46,9 @@
*
* @param ctx The csync context to use.
*
* @return 0 on success, < 0 on error.
*
* @todo Add an argument to set the algorithm to use.
*/
int OCSYNC_EXPORT csync_reconcile_updates(CSYNC *ctx);
void OCSYNC_EXPORT csync_reconcile_updates(CSYNC *ctx);
/**
* }@

View File

@@ -47,6 +47,7 @@
#include "common/asserts.h"
#include <QtCore/QTextCodec>
#include <QtCore/QFile>
// Needed for PRIu64 on MinGW in C++ mode.
#define __STDC_FORMAT_MACROS
@@ -108,15 +109,9 @@ static bool _csync_mtime_equal(time_t a, time_t b)
* See doc/dev/sync-algorithm.md for an overview.
*/
static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> fs) {
Q_ASSERT(fs);
OCC::SyncJournalFileRecord base;
CSYNC_EXCLUDE_TYPE excluded = CSYNC_NOT_EXCLUDED;
if (fs == NULL) {
errno = EINVAL;
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
return -1;
}
if (fs->type == ItemTypeSkip) {
excluded =CSYNC_FILE_EXCLUDE_STAT_FAILED;
} else {
@@ -192,19 +187,64 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
return -1;
}
// The db entry might be for a virtual file, so look for that on the
// remote side. If we find one, change the current fs to look like a
// virtual file too, because that's what one would see if the remote
// db was filled from the database.
if (ctx->current == REMOTE_REPLICA && !base.isValid() && fs->type == ItemTypeFile) {
auto virtualFilePath = fs->path;
virtualFilePath.append(ctx->virtual_file_suffix);
ctx->statedb->getFileRecord(virtualFilePath, &base);
if (base.isValid() && base._type == ItemTypeVirtualFile) {
fs->type = ItemTypeVirtualFile;
fs->path = virtualFilePath;
} else {
base = OCC::SyncJournalFileRecord();
}
}
if(base.isValid()) { /* there is an entry in the database */
/* we have an update! */
qCInfo(lcUpdate, "Database entry found, compare: %" PRId64 " <-> %" PRId64
", etag: %s <-> %s, inode: %" PRId64 " <-> %" PRId64
", size: %" PRId64 " <-> %" PRId64 ", perms: %x <-> %x, ignore: %d",
", size: %" PRId64 " <-> %" PRId64
", perms: %x <-> %x"
", type: %d <-> %d"
", checksum: %s <-> %s"
", ignore: %d",
((int64_t) fs->modtime), ((int64_t) base._modtime),
fs->etag.constData(), base._etag.constData(), (uint64_t) fs->inode, (uint64_t) base._inode,
(uint64_t) fs->size, (uint64_t) base._fileSize, *reinterpret_cast<short*>(&fs->remotePerm), *reinterpret_cast<short*>(&base._remotePerm), base._serverHasIgnoredFiles );
(uint64_t) fs->size, (uint64_t) base._fileSize,
*reinterpret_cast<short*>(&fs->remotePerm), *reinterpret_cast<short*>(&base._remotePerm),
fs->type, base._type,
fs->checksumHeader.constData(), base._checksumHeader.constData(),
base._serverHasIgnoredFiles );
// If the db suggests a virtual file should be downloaded,
// treat the file as new on the remote.
if (ctx->current == REMOTE_REPLICA && base._type == ItemTypeVirtualFileDownload) {
fs->instruction = CSYNC_INSTRUCTION_NEW;
fs->type = ItemTypeVirtualFileDownload;
goto out;
}
// If what the db thinks is a virtual file is actually a file/dir,
// treat it as new locally.
if (ctx->current == LOCAL_REPLICA
&& (base._type == ItemTypeVirtualFile || base._type == ItemTypeVirtualFileDownload)
&& fs->type != ItemTypeVirtualFile) {
fs->instruction = CSYNC_INSTRUCTION_EVAL;
goto out;
}
if (ctx->current == REMOTE_REPLICA && fs->etag != base._etag) {
fs->instruction = CSYNC_INSTRUCTION_EVAL;
// Preserve the EVAL flag later on if the type has changed.
if (base._type != fs->type) {
if (fs->type == ItemTypeVirtualFile) {
// If the local thing is a virtual file, we just update the metadata
fs->instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
} else if (base._type != fs->type) {
// Preserve the EVAL flag later on if the type has changed.
fs->child_modified = true;
}
@@ -325,10 +365,19 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
if (!base.isValid())
return;
if (base._type == ItemTypeVirtualFileDownload) {
// Remote rename of a virtual file we have locally scheduled
// for download. We just consider this NEW but mark it for download.
fs->type = ItemTypeVirtualFileDownload;
done = true;
return;
}
// Some things prohibit rename detection entirely.
// Since we don't do the same checks again in reconcile, we can't
// just skip the candidate, but have to give up completely.
if (base._type != fs->type) {
if (base._type != fs->type
&& base._type != ItemTypeVirtualFile) {
qCWarning(lcUpdate, "file types different, not a rename");
done = true;
return;
@@ -340,6 +389,14 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
return;
}
// Now we know there is a sane rename candidate.
// Rename of a virtual file
if (base._type == ItemTypeVirtualFile && fs->type == ItemTypeFile) {
fs->type = ItemTypeVirtualFile;
fs->path.append(ctx->virtual_file_suffix);
}
// Record directory renames
if (fs->type == ItemTypeDirectory) {
// If the same folder was already renamed by a different entry,
@@ -369,6 +426,15 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
return 1;
}
}
// Turn new remote files into virtual files if the option is enabled.
if (ctx->new_files_are_virtual
&& fs->instruction == CSYNC_INSTRUCTION_NEW
&& fs->type == ItemTypeFile) {
fs->type = ItemTypeVirtualFile;
fs->path.append(ctx->virtual_file_suffix);
}
goto out;
}
}
@@ -471,7 +537,7 @@ int csync_walker(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> fs) {
return rc;
}
static bool fill_tree_from_db(CSYNC *ctx, const char *uri)
static bool fill_tree_from_db(CSYNC *ctx, const char *uri, bool singleFile = false)
{
int64_t count = 0;
QByteArray skipbase;
@@ -526,9 +592,19 @@ static bool fill_tree_from_db(CSYNC *ctx, const char *uri)
++count;
};
if (!ctx->statedb->getFilesBelowPath(uri, rowCallback)) {
ctx->status_code = CSYNC_STATUS_STATEDB_LOAD_ERROR;
return false;
if (singleFile) {
OCC::SyncJournalFileRecord record;
if (ctx->statedb->getFileRecord(QByteArray(uri), &record) && record.isValid()) {
rowCallback(record);
} else {
ctx->status_code = CSYNC_STATUS_STATEDB_LOAD_ERROR;
return false;
}
} else {
if (!ctx->statedb->getFilesBelowPath(uri, rowCallback)) {
ctx->status_code = CSYNC_STATUS_STATEDB_LOAD_ERROR;
return false;
}
}
qInfo(lcUpdate, "%" PRId64 " entries read below path %s from db.", count, uri);
@@ -569,23 +645,12 @@ 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);
const char *db_uri = uri;
if (ctx->current == LOCAL_REPLICA
&& ctx->local_discovery_style == LocalDiscoveryStyle::DatabaseAndFilesystem) {
if (ctx->current == LOCAL_REPLICA && ctx->should_discover_locally_fn) {
const char *local_uri = uri + strlen(ctx->local.uri);
if (*local_uri == '/')
++local_uri;
db_uri = local_uri;
do_read_from_db = true;
// Minor bug: local_uri doesn't have a trailing /. Example: Assume it's "d/foo"
// and we want to check whether we should read from the db. Assume "d/foo a" is
// in locally_touched_dirs. Then this check will say no, don't read from the db!
// (because "d/foo" < "d/foo a" < "d/foo/bar")
// C++14: Could skip the conversion to QByteArray here.
auto it = ctx->locally_touched_dirs.lower_bound(QByteArray(local_uri));
if (it != ctx->locally_touched_dirs.end() && it->startsWith(local_uri)) {
do_read_from_db = false;
}
do_read_from_db = !ctx->should_discover_locally_fn(QByteArray(local_uri));
}
if (!depth) {
@@ -676,6 +741,21 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
fullpath = QByteArray() % uri % '/' % filename;
}
// When encountering virtual files, read the relevant
// entry from the db instead.
if (ctx->current == LOCAL_REPLICA
&& dirent->type == ItemTypeFile
&& filename.endsWith(ctx->virtual_file_suffix)) {
QByteArray db_uri = fullpath.mid(strlen(ctx->local.uri) + 1);
if( ! fill_tree_from_db(ctx, db_uri.constData(), true) ) {
qCWarning(lcUpdate) << "Virtual file without db entry for" << filename;
QFile::remove(fullpath);
}
continue;
}
/* if the filename starts with a . we consider it a hidden file
* For windows, the hidden state is also discovered within the vio
* local stat function.
@@ -689,10 +769,7 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
// Now process to have a relative path to the sync root for the local replica, or to the data root on the remote.
dirent->path = fullpath;
if (ctx->current == LOCAL_REPLICA) {
if (dirent->path.size() <= (int)strlen(ctx->local.uri)) {
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
goto error;
}
ASSERT(dirent->path.startsWith(ctx->local.uri)); // path is relative to uri
// "len + 1" to include the slash in-between.
dirent->path = dirent->path.mid(strlen(ctx->local.uri) + 1);
}

View File

@@ -40,7 +40,7 @@ csync_vio_handle_t *csync_vio_opendir(CSYNC *ctx, const char *name) {
break;
case LOCAL_REPLICA:
if( ctx->callbacks.update_callback ) {
ctx->callbacks.update_callback(ctx->current, name, ctx->callbacks.update_callback_userdata);
ctx->callbacks.update_callback(/*local=*/true, name, ctx->callbacks.update_callback_userdata);
}
return csync_vio_local_opendir(name);
break;

View File

@@ -47,6 +47,8 @@ set(client_SRCS
accountmanager.cpp
accountsettings.cpp
application.cpp
clientproxy.cpp
connectionvalidator.cpp
folder.cpp
folderman.cpp
folderstatusmodel.cpp
@@ -137,7 +139,7 @@ IF( APPLE )
if(SPARKLE_FOUND)
# Define this, we need to check in updater.cpp
add_definitions( -DHAVE_SPARKLE )
list(APPEND updater_SRCS updater/sparkleupdater_mac.mm)
list(APPEND updater_SRCS updater/sparkleupdater_mac.mm updater/sparkleupdater.h)
endif()
ENDIF()
@@ -214,12 +216,6 @@ endif()
# list(APPEND CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
include(ECMAddAppIcon)
# For historical reasons we can not use the application_shortname
# for ownCloud but must rather set it manually.
if (NOT DEFINED APPLICATION_ICON_NAME)
set(APPLICATION_ICON_NAME ${APPLICATION_SHORTNAME})
endif()
file(GLOB_RECURSE OWNCLOUD_ICONS "${theme_dir}/colored/*-${APPLICATION_ICON_NAME}-icon*")
if(APPLE)
file(GLOB_RECURSE OWNCLOUD_SIDEBAR_ICONS "${theme_dir}/colored/*-${APPLICATION_ICON_NAME}-sidebar*")
@@ -349,5 +345,15 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE AND NOT WIN32)
configure_file(${CMAKE_SOURCE_DIR}/mirall.desktop.in
${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_EXECUTABLE}.desktop)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_EXECUTABLE}.desktop DESTINATION ${DATADIR}/applications )
configure_file(owncloud.xml.in ${APPLICATION_EXECUTABLE}.xml)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_EXECUTABLE}.xml DESTINATION ${DATADIR}/mime/packages )
find_package(ECM 1.2.0 CONFIG)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(SharedMimeInfo)
if(SharedMimeInfo_FOUND)
update_xdg_mimetypes( ${DATADIR}/mime/packages )
endif(SharedMimeInfo_FOUND)
endif()

View File

@@ -33,6 +33,10 @@ static const char caCertsKeyC[] = "CaCertificates";
static const char accountsC[] = "Accounts";
static const char versionC[] = "version";
static const char serverVersionC[] = "serverVersion";
// The maximum versions that this client can read
static const int maxAccountsVersion = 2;
static const int maxAccountVersion = 1;
}
@@ -48,6 +52,9 @@ AccountManager *AccountManager::instance()
bool AccountManager::restore()
{
QStringList skipSettingsKeys;
backwardMigrationSettingsKeys(&skipSettingsKeys, &skipSettingsKeys);
auto settings = ConfigFile::settingsWithGroup(QLatin1String(accountsC));
if (settings->status() != QSettings::NoError) {
qCWarning(lcAccountManager) << "Could not read settings from" << settings->fileName()
@@ -55,6 +62,12 @@ bool AccountManager::restore()
return false;
}
if (skipSettingsKeys.contains(settings->group())) {
// Should not happen: bad container keys should have been deleted
qCWarning(lcAccountManager) << "Accounts structure is too new, ignoring";
return true;
}
// If there are no accounts, check the old format.
if (settings->childGroups().isEmpty()
&& !settings->contains(QLatin1String(versionC))) {
@@ -64,11 +77,16 @@ bool AccountManager::restore()
foreach (const auto &accountId, settings->childGroups()) {
settings->beginGroup(accountId);
if (auto acc = loadAccountHelper(*settings)) {
acc->_id = accountId;
if (auto accState = AccountState::loadFromSettings(acc, *settings)) {
addAccountState(accState);
if (!skipSettingsKeys.contains(settings->group())) {
if (auto acc = loadAccountHelper(*settings)) {
acc->_id = accountId;
if (auto accState = AccountState::loadFromSettings(acc, *settings)) {
addAccountState(accState);
}
}
} else {
qCInfo(lcAccountManager) << "Account" << accountId << "is too new, ignoring";
_additionalBlockedAccountIds.insert(accountId);
}
settings->endGroup();
}
@@ -76,6 +94,24 @@ bool AccountManager::restore()
return true;
}
void AccountManager::backwardMigrationSettingsKeys(QStringList *deleteKeys, QStringList *ignoreKeys)
{
auto settings = ConfigFile::settingsWithGroup(QLatin1String(accountsC));
const int accountsVersion = settings->value(QLatin1String(versionC)).toInt();
if (accountsVersion <= maxAccountsVersion) {
foreach (const auto &accountId, settings->childGroups()) {
settings->beginGroup(accountId);
const int accountVersion = settings->value(QLatin1String(versionC), 1).toInt();
if (accountVersion > maxAccountVersion) {
ignoreKeys->append(settings->group());
}
settings->endGroup();
}
} else {
deleteKeys->append(settings->group());
}
}
bool AccountManager::restoreFromLegacySettings()
{
qCInfo(lcAccountManager) << "Migrate: restoreFromLegacySettings, checking settings group"
@@ -136,7 +172,7 @@ bool AccountManager::restoreFromLegacySettings()
void AccountManager::save(bool saveCredentials)
{
auto settings = ConfigFile::settingsWithGroup(QLatin1String(accountsC));
settings->setValue(QLatin1String(versionC), 2);
settings->setValue(QLatin1String(versionC), maxAccountsVersion);
foreach (const auto &acc, _accounts) {
settings->beginGroup(acc->account()->id());
saveAccountHelper(acc->account().data(), *settings, saveCredentials);
@@ -174,6 +210,7 @@ void AccountManager::saveAccountState(AccountState *a)
void AccountManager::saveAccountHelper(Account *acc, QSettings &settings, bool saveCredentials)
{
settings.setValue(QLatin1String(versionC), maxAccountVersion);
settings.setValue(QLatin1String(urlC), acc->_url.toString());
settings.setValue(QLatin1String(serverVersionC), acc->_serverVersion);
if (acc->_credentials) {
@@ -324,7 +361,6 @@ AccountPtr AccountManager::createAccount()
return acc;
}
void AccountManager::shutdown()
{
auto accountsCopy = _accounts;
@@ -341,6 +377,8 @@ bool AccountManager::isAccountIdAvailable(const QString &id) const
return false;
}
}
if (_additionalBlockedAccountIds.contains(id))
return false;
return true;
}

View File

@@ -77,6 +77,12 @@ public:
*/
static AccountPtr createAccount();
/**
* Returns the list of settings keys that can't be read because
* they are from the future.
*/
static void backwardMigrationSettingsKeys(QStringList *deleteKeys, QStringList *ignoreKeys);
private:
// saving and loading Account to settings
void saveAccountHelper(Account *account, QSettings &settings, bool saveCredentials = true);
@@ -105,5 +111,7 @@ Q_SIGNALS:
private:
AccountManager() {}
QList<AccountStatePtr> _accounts;
/// Account ids from settings that weren't read
QSet<QString> _additionalBlockedAccountIds;
};
}

View File

@@ -378,6 +378,7 @@ void AccountSettings::slotFolderWizardAccepted()
folderWizard->field(QLatin1String("sourceFolder")).toString());
definition.targetPath = FolderDefinition::prepareTargetPath(
folderWizard->property("targetPath").toString());
definition.useVirtualFiles = folderWizard->property("useVirtualFiles").toBool();
{
QDir dir(definition.localPath);

View File

@@ -76,11 +76,6 @@ QStringList AccountState::connectionErrors() const
return _connectionErrors;
}
QString AccountState::connectionStatusString(ConnectionStatus status)
{
return ConnectionValidator::statusString(status);
}
AccountState::State AccountState::state() const
{
return _state;
@@ -198,11 +193,11 @@ void AccountState::checkConnectivity()
// IF the account is connected the connection check can be skipped
// if the last successful etag check job is not so long ago.
ConfigFile cfg;
int polltime = cfg.remotePollInterval();
std::chrono::milliseconds polltime = cfg.remotePollInterval();
if (isConnected() && _timeSinceLastETagCheck.isValid()
&& _timeSinceLastETagCheck.elapsed() < polltime) {
qCDebug(lcAccountState) << account()->displayName() << "The last ETag check succeeded within the last " << polltime / 1000 << " secs. No connection check needed!";
&& _timeSinceLastETagCheck.hasExpired(polltime.count())) {
qCDebug(lcAccountState) << account()->displayName() << "The last ETag check succeeded within the last " << polltime.count() / 1000 << " secs. No connection check needed!";
return;
}
@@ -237,7 +232,7 @@ void AccountState::checkConnectivity()
void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList &errors)
{
if (isSignedOut()) {
qCWarning(lcAccountState) << "Signed out, ignoring" << connectionStatusString(status) << _account->url().toString();
qCWarning(lcAccountState) << "Signed out, ignoring" << status << _account->url().toString();
return;
}
@@ -260,8 +255,8 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta
if (_connectionStatus != status) {
qCInfo(lcAccountState) << "AccountState connection status change: "
<< connectionStatusString(_connectionStatus) << "->"
<< connectionStatusString(status);
<< _connectionStatus << "->"
<< status;
_connectionStatus = status;
}
_connectionErrors = errors;

View File

@@ -94,7 +94,6 @@ public:
ConnectionStatus connectionStatus() const;
QStringList connectionErrors() const;
static QString connectionStatusString(ConnectionStatus status);
State state() const;
static QString stateString(State state);

View File

@@ -58,9 +58,10 @@ public:
QString _file;
QUrl _link;
QDateTime _dateTime;
QString _accName;
QString _accName; /* display name of the account involved */
QVector<ActivityLink> _links;
QVector<ActivityLink> _links; /* These links are transformed into buttons that
* call links as reactions on the activity */
/**
* @brief Sort operator to sort the list youngest first.
* @param val

View File

@@ -544,10 +544,10 @@ ActivitySettings::ActivitySettings(QWidget *parent)
_tab->setCurrentIndex(1);
}
void ActivitySettings::setNotificationRefreshInterval(quint64 interval)
void ActivitySettings::setNotificationRefreshInterval(std::chrono::milliseconds interval)
{
qCDebug(lcActivity) << "Starting Notification refresh timer with " << interval / 1000 << " sec interval";
_notificationCheckTimer.start(interval);
qCDebug(lcActivity) << "Starting Notification refresh timer with " << interval.count() / 1000 << " sec interval";
_notificationCheckTimer.start(interval.count());
}
void ActivitySettings::setActivityTabHidden(bool hidden)

View File

@@ -19,6 +19,7 @@
#include <QDateTime>
#include <QLocale>
#include <QAbstractListModel>
#include <chrono>
#include "progressdispatcher.h"
#include "owncloudgui.h"
@@ -91,7 +92,7 @@ private slots:
void slotNotifyNetworkError(QNetworkReply *);
void slotNotifyServerFinished(const QString &reply, int replyCode);
void endNotificationRequest(NotificationWidget *widget, int replyCode);
void scheduleWidgetToRemove(NotificationWidget *widget, int milliseconds = 4500);
void scheduleWidgetToRemove(NotificationWidget *widget, int milliseconds = 100);
void slotCheckToCleanWidgets();
private:
@@ -137,7 +138,7 @@ public slots:
void slotRefresh(AccountState *ptr);
void slotRemoveAccount(AccountState *ptr);
void setNotificationRefreshInterval(quint64 interval);
void setNotificationRefreshInterval(std::chrono::milliseconds interval);
void slotShowIssuesTab(const QString &folderAlias);

View File

@@ -37,6 +37,7 @@
#include "updater/ocupdater.h"
#include "owncloudsetupwizard.h"
#include "version.h"
#include "csync_exclude.h"
#include "config.h"
@@ -94,6 +95,66 @@ namespace {
// ----------------------------------------------------------------------------------
bool Application::configVersionMigration()
{
QStringList deleteKeys, ignoreKeys;
AccountManager::backwardMigrationSettingsKeys(&deleteKeys, &ignoreKeys);
FolderMan::backwardMigrationSettingsKeys(&deleteKeys, &ignoreKeys);
ConfigFile configFile;
// Did the client version change?
// (The client version is adjusted further down)
bool versionChanged = configFile.clientVersionString() != MIRALL_VERSION_STRING;
// We want to message the user either for destructive changes,
// or if we're ignoring something and the client version changed.
bool warningMessage = !deleteKeys.isEmpty() || (!ignoreKeys.isEmpty() && versionChanged);
if (!versionChanged && !warningMessage)
return true;
const auto backupFile = configFile.backup();
if (warningMessage) {
QString boldMessage;
if (!deleteKeys.isEmpty()) {
boldMessage = tr("Continuing will mean <b>deleting these settings</b>.");
} else {
boldMessage = tr("Continuing will mean <b>ignoring these settings</b>.");
}
QMessageBox box(
QMessageBox::Warning,
APPLICATION_SHORTNAME,
tr("Some settings were configured in newer versions of this client and "
"use features that are not available in this version.<br>"
"<br>"
"%1<br>"
"<br>"
"The current configuration file was already backed up to <i>%2</i>.")
.arg(boldMessage, backupFile));
box.addButton(tr("Quit"), QMessageBox::AcceptRole);
auto continueBtn = box.addButton(tr("Continue"), QMessageBox::DestructiveRole);
box.exec();
if (box.clickedButton() != continueBtn) {
QTimer::singleShot(0, qApp, SLOT(quit()));
return false;
}
auto settings = ConfigFile::settingsWithGroup("foo");
settings->endGroup();
// Wipe confusing keys from the future, ignore the others
for (const auto &badKey : deleteKeys)
settings->remove(badKey);
}
configFile.setClientVersionString(MIRALL_VERSION_STRING);
return true;
}
Application::Application(int &argc, char **argv)
: SharedTools::QtSingleApplication(Theme::instance()->appName(), argc, argv)
, _gui(0)
@@ -167,8 +228,12 @@ Application::Application(int &argc, char **argv)
setupLogging();
setupTranslations();
// The timeout is initialized with an environment variable, if not, override with the value from the config
if (!configVersionMigration()) {
return;
}
ConfigFile cfg;
// The timeout is initialized with an environment variable, if not, override with the value from the config
if (!AbstractNetworkJob::httpTimeout)
AbstractNetworkJob::httpTimeout = cfg.timeout();
@@ -202,14 +267,16 @@ Application::Application(int &argc, char **argv)
_theme->setSystrayUseMonoIcons(cfg.monoIcons());
connect(_theme, &Theme::systrayUseMonoIconsChanged, this, &Application::slotUseMonoIconsChanged);
FolderMan::instance()->setupFolders();
_proxy.setupQtProxyFromConfig(); // folders have to be defined first, than we set up the Qt proxy.
// Setting up the gui class will allow tray notifications for the
// setup that follows, like folder setup
_gui = new ownCloudGui(this);
if (_showLogWindow) {
_gui->slotToggleLogBrowser(); // _showLogWindow is set in parseOptions.
}
FolderMan::instance()->setupFolders();
_proxy.setupQtProxyFromConfig(); // folders have to be defined first, than we set up the Qt proxy.
// Enable word wrapping of QInputDialog (#4197)
setStyleSheet("QInputDialog QLabel { qproperty-wordWrap:1; }");
@@ -362,7 +429,9 @@ void Application::slotownCloudWizardDone(int res)
shouldSetAutoStart = shouldSetAutoStart
&& QCoreApplication::applicationDirPath().startsWith("/Applications/");
#endif
Utility::setLaunchOnStartup(_theme->appName(), _theme->appNameGUI(), shouldSetAutoStart);
if (shouldSetAutoStart) {
Utility::setLaunchOnStartup(_theme->appName(), _theme->appNameGUI(), true);
}
_gui->slotShowSettings();
}
@@ -371,13 +440,17 @@ void Application::slotownCloudWizardDone(int res)
void Application::setupLogging()
{
// might be called from second instance
Logger::instance()->setLogFile(_logFile);
Logger::instance()->setLogDir(_logDir);
Logger::instance()->setLogExpire(_logExpire);
Logger::instance()->setLogFlush(_logFlush);
Logger::instance()->setLogDebug(_logDebug);
auto logger = Logger::instance();
logger->setLogFile(_logFile);
logger->setLogDir(_logDir);
logger->setLogExpire(_logExpire);
logger->setLogFlush(_logFlush);
logger->setLogDebug(_logDebug);
if (!logger->isLoggingToFile() && ConfigFile().automaticLogDir()) {
logger->setupTemporaryFolderLogDir();
}
Logger::instance()->enterNextLogFile();
logger->enterNextLogFile();
qCInfo(lcApplication) << QString::fromLatin1("################## %1 locale:[%2] ui_lang:[%3] version:[%4] os:[%5]").arg(_theme->appName()).arg(QLocale::system().name()).arg(property("ui_lang").toString()).arg(_theme->version()).arg(Utility::platformName());
}
@@ -456,6 +529,9 @@ void Application::parseOptions(const QStringList &options)
_debugMode = true;
} else if (option == QLatin1String("--version")) {
_versionOnly = true;
} else if (option.endsWith(QStringLiteral(APPLICATION_DOTVIRTUALFILE_SUFFIX))) {
// virtual file, open it after the Folder were created (if the app is not terminated)
QTimer::singleShot(0, this, [this, option] { openVirtualFile(option); });
} else {
showHint("Unrecognized option '" + option.toStdString() + "'");
}
@@ -621,5 +697,43 @@ void Application::showSettingsDialog()
_gui->slotShowSettings();
}
void Application::openVirtualFile(const QString &filename)
{
QString virtualFileExt = QStringLiteral(APPLICATION_DOTVIRTUALFILE_SUFFIX);
if (!filename.endsWith(virtualFileExt)) {
qWarning(lcApplication) << "Can only handle file ending in .owncloud. Unable to open" << filename;
return;
}
QString relativePath;
auto folder = FolderMan::instance()->folderForPath(filename, &relativePath);
if (!folder) {
qWarning(lcApplication) << "Can't find sync folder for" << filename;
// TODO: show a QMessageBox for errors
return;
}
folder->downloadVirtualFile(relativePath);
QString normalName = filename.left(filename.size() - virtualFileExt.size());
auto con = QSharedPointer<QMetaObject::Connection>::create();
*con = QObject::connect(folder, &Folder::syncFinished, [con, normalName] {
QObject::disconnect(*con);
if (QFile::exists(normalName)) {
QDesktopServices::openUrl(QUrl::fromLocalFile(normalName));
}
});
}
bool Application::event(QEvent *event)
{
#ifdef Q_OS_MAC
if (event->type() == QEvent::FileOpen) {
QFileOpenEvent *openEvent = static_cast<QFileOpenEvent *>(event);
qCDebug(lcApplication) << "QFileOpenEvent" << openEvent->file();
// virtual file, open it after the Folder were created (if the app is not terminated)
QString fn = openEvent->file();
QTimer::singleShot(0, this, [this, fn] { openVirtualFile(fn); });
}
#endif
return SharedTools::QtSingleApplication::event(event);
}
} // namespace OCC

View File

@@ -72,11 +72,17 @@ public slots:
// TODO: this should not be public
void slotownCloudWizardDone(int);
void slotCrash();
/**
* Will download a virtual file, and open the result.
* The argument is the filename of the virtual file (including the extension)
*/
void openVirtualFile(const QString &filename);
protected:
void parseOptions(const QStringList &);
void setupTranslations();
void setupLogging();
bool event(QEvent *event);
signals:
void folderRemoved();
@@ -94,6 +100,12 @@ protected slots:
private:
void setHelp();
/**
* Maybe a newer version of the client was used with this config file:
* if so, backup, confirm with user and remove the config that can't be read.
*/
bool configVersionMigration();
QPointer<ownCloudGui> _gui;
Theme *_theme;

View File

@@ -32,7 +32,7 @@ class ConfigFile;
* @brief The ClientProxy class
* @ingroup libsync
*/
class OWNCLOUDSYNC_EXPORT ClientProxy : public QObject
class ClientProxy : public QObject
{
Q_OBJECT
public:
@@ -61,7 +61,7 @@ private:
QUrl _url;
};
OWNCLOUDSYNC_EXPORT QString printQNetworkProxy(const QNetworkProxy &proxy);
QString printQNetworkProxy(const QNetworkProxy &proxy);
}
#endif // CLIENTPROXY_H

View File

@@ -40,35 +40,6 @@ ConnectionValidator::ConnectionValidator(AccountPtr account, QObject *parent)
{
}
QString ConnectionValidator::statusString(Status stat)
{
switch (stat) {
case Undefined:
return QLatin1String("Undefined");
case Connected:
return QLatin1String("Connected");
case NotConfigured:
return QLatin1String("Not configured");
case ServerVersionMismatch:
return QLatin1String("Server Version Mismatch");
case CredentialsNotReady:
return QLatin1String("Credentials not ready");
case CredentialsWrong:
return QLatin1String("Credentials Wrong");
case SslError:
return QLatin1String("SSL Error");
case StatusNotFound:
return QLatin1String("Status not found");
case ServiceUnavailable:
return QLatin1String("Service unavailable");
case MaintenanceMode:
return QLatin1String("Maintenance mode");
case Timeout:
return QLatin1String("Timeout");
}
return QLatin1String("status undeclared.");
}
void ConnectionValidator::checkServerAndAuth()
{
if (!_account) {
@@ -304,19 +275,20 @@ bool ConnectionValidator::setAndCheckServerVersion(const QString &version)
qCInfo(lcConnectionValidator) << _account->url() << "has server version" << version;
_account->setServerVersion(version);
// We cannot deal with servers < 5.0.0
// We cannot deal with servers < 7.0.0
if (_account->serverVersionInt()
&& _account->serverVersionInt() < Account::makeServerVersion(5, 0, 0)) {
&& _account->serverVersionInt() < Account::makeServerVersion(7, 0, 0)) {
_errors.append(tr("The configured server for this client is too old"));
_errors.append(tr("Please update to the latest server and restart the client."));
reportResult(ServerVersionMismatch);
return false;
}
// We attempt to work with servers >= 5.0.0 but warn users.
// We attempt to work with servers >= 7.0.0 but warn users.
// Check usages of Account::serverVersionUnsupported() for details.
#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
// Record that the server supports HTTP/2
// Actual decision if we should use HTTP/2 is done in AccessManager::createRequest
if (auto job = qobject_cast<AbstractNetworkJob *>(sender())) {
if (auto reply = job->reply()) {
_account->setHttp2Supported(

View File

@@ -75,7 +75,7 @@ namespace OCC {
\endcode
*/
class OWNCLOUDSYNC_EXPORT ConnectionValidator : public QObject
class ConnectionValidator : public QObject
{
Q_OBJECT
public:
@@ -94,8 +94,7 @@ public:
MaintenanceMode, // maintenance enabled in status.php
Timeout // actually also used for other errors on the authed request
};
static QString statusString(Status);
Q_ENUM(Status);
// How often should the Application ask this object to check for the connection?
enum { DefaultCallingIntervalMsec = 32 * 1000 };
@@ -109,7 +108,7 @@ public slots:
void checkAuthentication();
signals:
void connectionResult(ConnectionValidator::Status status, QStringList errors);
void connectionResult(ConnectionValidator::Status status, const QStringList &errors);
protected slots:
void slotCheckServerAndAuth();

View File

@@ -30,6 +30,7 @@
#include "socketapi.h"
#include "theme.h"
#include "filesystem.h"
#include "localdiscoverytracker.h"
#include "creds/abstractcredentials.h"
@@ -41,6 +42,8 @@
#include <QMessageBox>
#include <QPushButton>
static const char versionC[] = "version";
namespace OCC {
Q_LOGGING_CATEGORY(lcFolder, "gui.folder", QtInfoMsg)
@@ -107,6 +110,15 @@ Folder::Folder(const FolderDefinition &definition,
_scheduleSelfTimer.setInterval(SyncEngine::minimumFileAgeForUpload);
connect(&_scheduleSelfTimer, &QTimer::timeout,
this, &Folder::slotScheduleThisFolder);
connect(ProgressDispatcher::instance(), &ProgressDispatcher::folderConflicts,
this, &Folder::slotFolderConflicts);
_localDiscoveryTracker.reset(new LocalDiscoveryTracker);
connect(_engine.data(), &SyncEngine::finished,
_localDiscoveryTracker.data(), &LocalDiscoveryTracker::slotSyncFinished);
connect(_engine.data(), &SyncEngine::itemCompleted,
_localDiscoveryTracker.data(), &LocalDiscoveryTracker::slotItemCompleted);
}
Folder::~Folder()
@@ -119,6 +131,10 @@ void Folder::checkLocalPath()
{
const QFileInfo fi(_definition.localPath);
_canonicalLocalPath = fi.canonicalFilePath();
#ifdef Q_OS_MAC
// Workaround QTBUG-55896 (Should be fixed in Qt 5.8)
_canonicalLocalPath = _canonicalLocalPath.normalized(QString::NormalizationForm_C);
#endif
if (_canonicalLocalPath.isEmpty()) {
qCWarning(lcFolder) << "Broken symlink:" << _definition.localPath;
_canonicalLocalPath = _definition.localPath;
@@ -458,8 +474,7 @@ void Folder::slotWatchedPathChanged(const QString &path)
// We do this before checking for our own sync-related changes to make
// extra sure to not miss relevant changes.
auto relativePathBytes = relativePath.toUtf8();
_localDiscoveryPaths.insert(relativePathBytes);
qCDebug(lcFolder) << "local discovery: inserted" << relativePath << "due to file watcher";
_localDiscoveryTracker->addTouchedPath(relativePathBytes);
// The folder watcher fires a lot of bogus notifications during
// a sync operation, both for actual user files and the database
@@ -485,6 +500,8 @@ void Folder::slotWatchedPathChanged(const QString &path)
return; // probably a spurious notification
}
warnOnNewExcludedItem(record, relativePath);
emit watchedFileChangedExternally(path);
// Also schedule this folder for a sync, but only after some delay:
@@ -492,20 +509,35 @@ void Folder::slotWatchedPathChanged(const QString &path)
scheduleThisFolderSoon();
}
void Folder::downloadVirtualFile(const QString &_relativepath)
{
qCInfo(lcFolder) << "Download virtual file: " << _relativepath;
auto relativepath = _relativepath.toUtf8();
// Set in the database that we should download the file
SyncJournalFileRecord record;
_journal.getFileRecord(relativepath, &record);
if (!record.isValid())
return;
record._type = ItemTypeVirtualFileDownload;
_journal.setFileRecord(record);
// Make sure we go over that file during the discovery
_journal.avoidReadFromDbOnNextSync(relativepath);
// Schedule a sync (Folder man will start the sync in a few ms)
slotScheduleThisFolder();
}
void Folder::saveToSettings() const
{
// Remove first to make sure we don't get duplicates
removeFromSettings();
auto settings = _accountState->settings();
QString settingsGroup = QStringLiteral("Multifolders");
// The folder is saved to backwards-compatible "Folders"
// section only if it has the migrate flag set (i.e. was in
// there before) or if the folder is the only one for the
// given target path.
// This ensures that older clients will not read a configuration
// where two folders for different accounts point at the same
// local folders.
// True if the folder path appears in only one account
bool oneAccountOnly = true;
foreach (Folder *other, FolderMan::instance()->map()) {
if (other != this && other->cleanPath() == this->cleanPath()) {
@@ -514,13 +546,25 @@ void Folder::saveToSettings() const
}
}
bool compatible = _saveBackwardsCompatible || oneAccountOnly;
if (compatible) {
settings->beginGroup(QLatin1String("Folders"));
} else {
settings->beginGroup(QLatin1String("Multifolders"));
if (_definition.useVirtualFiles) {
// If virtual files are enabled, save the folder to a group
// that will not be read by older (<2.5.0) clients.
// The name is from when virtual files were called placeholders.
settingsGroup = QStringLiteral("FoldersWithPlaceholders");
} else if (_saveBackwardsCompatible || oneAccountOnly) {
// The folder is saved to backwards-compatible "Folders"
// section only if it has the migrate flag set (i.e. was in
// there before) or if the folder is the only one for the
// given target path.
// This ensures that older clients will not read a configuration
// where two folders for different accounts point at the same
// local folders.
settingsGroup = QStringLiteral("Folders");
}
settings->beginGroup(settingsGroup);
// Note: Each of these groups might have a "version" tag, but that's
// currently unused.
FolderDefinition::save(*settings, _definition);
settings->sync();
@@ -535,6 +579,9 @@ void Folder::removeFromSettings() const
settings->endGroup();
settings->beginGroup(QLatin1String("Multifolders"));
settings->remove(FolderMan::escapeAlias(_definition.alias));
settings->endGroup();
settings->beginGroup(QLatin1String("FoldersWithPlaceholders"));
settings->remove(FolderMan::escapeAlias(_definition.alias));
}
bool Folder::isFileExcludedAbsolute(const QString &fullPath) const
@@ -626,35 +673,31 @@ void Folder::startSync(const QStringList &pathList)
setDirtyNetworkLimits();
setSyncOptions();
static qint64 fullLocalDiscoveryInterval = []() {
static std::chrono::milliseconds fullLocalDiscoveryInterval = []() {
auto interval = ConfigFile().fullLocalDiscoveryInterval();
QByteArray env = qgetenv("OWNCLOUD_FULL_LOCAL_DISCOVERY_INTERVAL");
if (!env.isEmpty()) {
interval = env.toLongLong();
interval = std::chrono::milliseconds(env.toLongLong());
}
return interval;
}();
bool hasDoneFullLocalDiscovery = _timeSinceLastFullLocalDiscovery.isValid();
bool periodicFullLocalDiscoveryNow =
fullLocalDiscoveryInterval.count() >= 0 // negative means we don't require periodic full runs
&& _timeSinceLastFullLocalDiscovery.hasExpired(fullLocalDiscoveryInterval.count());
if (_folderWatcher && _folderWatcher->isReliable()
&& _timeSinceLastFullLocalDiscovery.isValid()
&& (fullLocalDiscoveryInterval < 0
|| _timeSinceLastFullLocalDiscovery.elapsed() < fullLocalDiscoveryInterval)) {
&& hasDoneFullLocalDiscovery
&& !periodicFullLocalDiscoveryNow) {
qCInfo(lcFolder) << "Allowing local discovery to read from the database";
_engine->setLocalDiscoveryOptions(LocalDiscoveryStyle::DatabaseAndFilesystem, _localDiscoveryPaths);
if (lcFolder().isDebugEnabled()) {
QByteArrayList paths;
for (auto &path : _localDiscoveryPaths)
paths.append(path);
qCDebug(lcFolder) << "local discovery paths: " << paths;
}
_previousLocalDiscoveryPaths = std::move(_localDiscoveryPaths);
_engine->setLocalDiscoveryOptions(
LocalDiscoveryStyle::DatabaseAndFilesystem,
_localDiscoveryTracker->localDiscoveryPaths());
_localDiscoveryTracker->startSyncPartialDiscovery();
} else {
qCInfo(lcFolder) << "Forbidding local discovery to read from the database";
_engine->setLocalDiscoveryOptions(LocalDiscoveryStyle::FilesystemOnly);
_previousLocalDiscoveryPaths.clear();
_localDiscoveryTracker->startSyncFullDiscovery();
}
_localDiscoveryPaths.clear();
_engine->setIgnoreHiddenFiles(_definition.ignoreHiddenFiles);
@@ -671,6 +714,9 @@ void Folder::setSyncOptions()
auto newFolderLimit = cfgFile.newBigFolderSizeLimit();
opt._newBigFolderSizeLimit = newFolderLimit.first ? newFolderLimit.second * 1000LL * 1000LL : -1; // convert from MB to B
opt._confirmExternalStorage = cfgFile.confirmExternalStorage();
opt._moveFilesToTrash = cfgFile.moveToTrash();
opt._newFilesAreVirtual = _definition.useVirtualFiles;
opt._virtualFileSuffix = QStringLiteral(APPLICATION_DOTVIRTUALFILE_SUFFIX);
QByteArray chunkSizeEnv = qgetenv("OWNCLOUD_CHUNK_SIZE");
if (!chunkSizeEnv.isEmpty()) {
@@ -700,7 +746,7 @@ void Folder::setSyncOptions()
QByteArray targetChunkUploadDurationEnv = qgetenv("OWNCLOUD_TARGET_CHUNK_UPLOAD_DURATION");
if (!targetChunkUploadDurationEnv.isEmpty()) {
opt._targetChunkUploadDuration = targetChunkUploadDurationEnv.toUInt();
opt._targetChunkUploadDuration = std::chrono::milliseconds(targetChunkUploadDurationEnv.toUInt());
} else {
opt._targetChunkUploadDuration = cfgFile.targetChunkUploadDuration();
}
@@ -794,23 +840,14 @@ void Folder::slotSyncFinished(bool success)
journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncWhiteList, QStringList());
}
// bug: This function uses many different criteria for "sync was successful" - investigate!
if ((_syncResult.status() == SyncResult::Success
|| _syncResult.status() == SyncResult::Problem)
&& success) {
if (_engine->lastLocalDiscoveryStyle() == LocalDiscoveryStyle::FilesystemOnly) {
_timeSinceLastFullLocalDiscovery.start();
}
qCDebug(lcFolder) << "Sync success, forgetting last sync's local discovery path list";
} else {
// On overall-failure we can't forget about last sync's local discovery
// paths yet, reuse them for the next sync again.
// C++17: Could use std::set::merge().
_localDiscoveryPaths.insert(
_previousLocalDiscoveryPaths.begin(), _previousLocalDiscoveryPaths.end());
qCDebug(lcFolder) << "Sync failed, keeping last sync's local discovery path list";
}
_previousLocalDiscoveryPaths.clear();
emit syncStateChange();
@@ -822,7 +859,7 @@ void Folder::slotSyncFinished(bool success)
// all come in.
QTimer::singleShot(200, this, &Folder::slotEmitFinishedDelayed);
_lastSyncDuration = _timeSinceLastSyncStart.elapsed();
_lastSyncDuration = std::chrono::milliseconds(_timeSinceLastSyncStart.elapsed());
_timeSinceLastSyncDone.start();
// Increment the follow-up sync counter if necessary.
@@ -885,25 +922,6 @@ void Folder::slotItemCompleted(const SyncFileItemPtr &item)
_folderWatcher->removePath(path() + item->_file);
}
// Success and failure of sync items adjust what the next sync is
// supposed to do.
//
// For successes, we want to wipe the file from the list to ensure we don't
// rediscover it even if this overall sync fails.
//
// For failures, we want to add the file to the list so the next sync
// will be able to retry it.
if (item->_status == SyncFileItem::Success
|| item->_status == SyncFileItem::FileIgnored
|| item->_status == SyncFileItem::Restoration
|| item->_status == SyncFileItem::Conflict) {
if (_previousLocalDiscoveryPaths.erase(item->_file.toUtf8()))
qCDebug(lcFolder) << "local discovery: wiped" << item->_file;
} else {
_localDiscoveryPaths.insert(item->_file.toUtf8());
qCDebug(lcFolder) << "local discovery: inserted" << item->_file << "due to sync failure";
}
_syncResult.processCompletedItem(item);
_fileLog->logItem(*item);
@@ -961,6 +979,63 @@ void Folder::slotNextSyncFullLocalDiscovery()
_timeSinceLastFullLocalDiscovery.invalidate();
}
void Folder::slotFolderConflicts(const QString &folder, const QStringList &conflictPaths)
{
if (folder != _definition.alias)
return;
auto &r = _syncResult;
// If the number of conflicts is too low, adjust it upwards
if (conflictPaths.size() > r.numNewConflictItems() + r.numOldConflictItems())
r.setNumOldConflictItems(conflictPaths.size() - r.numNewConflictItems());
}
void Folder::warnOnNewExcludedItem(const SyncJournalFileRecord &record, const QStringRef &path)
{
// Never warn for items in the database
if (record.isValid())
return;
// Don't warn for items that no longer exist.
// Note: This assumes we're getting file watcher notifications
// for folders only on creation and deletion - if we got a notification
// on content change that would create spurious warnings.
QFileInfo fi(_canonicalLocalPath + path);
if (!fi.exists())
return;
bool ok = false;
auto blacklist = _journal.getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok);
if (!ok)
return;
if (!blacklist.contains(path + "/"))
return;
const auto message = fi.isDir()
? tr("The folder %1 was created but was excluded from synchronization previously. "
"Data inside it will not be synchronized.")
.arg(fi.filePath())
: tr("The file %1 was created but was excluded from synchronization previously. "
"It will not be synchronized.")
.arg(fi.filePath());
Logger::instance()->postOptionalGuiLog(Theme::instance()->appNameGUI(), message);
}
void Folder::slotWatcherUnreliable(const QString &message)
{
qCWarning(lcFolder) << "Folder watcher for" << path() << "became unreliable:" << message;
auto fullMessage =
tr("Changes in synchronized folders could not be tracked reliably.\n"
"\n"
"This means that the synchronization client might not upload local changes "
"immediately and will instead only scan for local changes and upload them "
"occasionally (every two hours by default).\n"
"\n"
"%1").arg(message);
Logger::instance()->postGuiLog(Theme::instance()->appNameGUI(), fullMessage);
}
void Folder::scheduleThisFolderSoon()
{
if (!_scheduleSelfTimer.isActive()) {
@@ -980,11 +1055,14 @@ void Folder::registerFolderWatcher()
if (!QDir(path()).exists())
return;
_folderWatcher.reset(new FolderWatcher(path(), this));
_folderWatcher.reset(new FolderWatcher(this));
connect(_folderWatcher.data(), &FolderWatcher::pathChanged,
this, &Folder::slotWatchedPathChanged);
connect(_folderWatcher.data(), &FolderWatcher::lostChanges,
this, &Folder::slotNextSyncFullLocalDiscovery);
connect(_folderWatcher.data(), &FolderWatcher::becameUnreliable,
this, &Folder::slotWatcherUnreliable);
_folderWatcher->init(path());
}
void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction dir, bool *cancel)
@@ -1050,6 +1128,8 @@ void FolderDefinition::save(QSettings &settings, const FolderDefinition &folder)
settings.setValue(QLatin1String("targetPath"), folder.targetPath);
settings.setValue(QLatin1String("paused"), folder.paused);
settings.setValue(QLatin1String("ignoreHiddenFiles"), folder.ignoreHiddenFiles);
settings.setValue(QLatin1String("usePlaceholders"), folder.useVirtualFiles);
settings.setValue(QLatin1String(versionC), maxSettingsVersion());
// Happens only on Windows when the explorer integration is enabled.
if (!folder.navigationPaneClsid.isNull())
@@ -1070,6 +1150,7 @@ bool FolderDefinition::load(QSettings &settings, const QString &alias,
folder->paused = settings.value(QLatin1String("paused")).toBool();
folder->ignoreHiddenFiles = settings.value(QLatin1String("ignoreHiddenFiles"), QVariant(true)).toBool();
folder->navigationPaneClsid = settings.value(QLatin1String("navigationPaneClsid")).toUuid();
folder->useVirtualFiles = settings.value(QLatin1String("usePlaceholders")).toBool();
settings.endGroup();
// Old settings can contain paths with native separators. In the rest of the

View File

@@ -20,7 +20,6 @@
#include "syncresult.h"
#include "progressdispatcher.h"
#include "common/syncjournaldb.h"
#include "clientproxy.h"
#include "networkjobs.h"
#include <csync.h>
@@ -29,6 +28,7 @@
#include <QStringList>
#include <QUuid>
#include <set>
#include <chrono>
class QThread;
class QSettings;
@@ -39,6 +39,7 @@ class SyncEngine;
class AccountState;
class SyncRunFileLog;
class FolderWatcher;
class LocalDiscoveryTracker;
/**
* @brief The FolderDefinition class
@@ -65,6 +66,8 @@ public:
bool paused;
/// whether the folder syncs hidden files
bool ignoreHiddenFiles;
/// New files are downloaded as virtual files
bool useVirtualFiles = false;
/// The CLSID where this folder appears in registry for the Explorer navigation pane entry.
QUuid navigationPaneClsid;
@@ -75,6 +78,9 @@ public:
static bool load(QSettings &settings, const QString &alias,
FolderDefinition *folder);
/// The highest version in the settings that load() can read
static int maxSettingsVersion() { return 1; }
/// Ensure / as separator and trailing /.
static QString prepareLocalPath(const QString &path);
@@ -192,8 +198,8 @@ public:
SyncEngine &syncEngine() { return *_engine; }
RequestEtagJob *etagJob() { return _requestEtagJob; }
qint64 msecSinceLastSync() const { return _timeSinceLastSyncDone.elapsed(); }
qint64 msecLastSyncDuration() const { return _lastSyncDuration; }
std::chrono::milliseconds msecSinceLastSync() const { return std::chrono::milliseconds(_timeSinceLastSyncDone.elapsed()); }
std::chrono::milliseconds msecLastSyncDuration() const { return _lastSyncDuration; }
int consecutiveFollowUpSyncs() const { return _consecutiveFollowUpSyncs; }
int consecutiveFailingSyncs() const { return _consecutiveFailingSyncs; }
@@ -282,6 +288,12 @@ public slots:
*/
void slotWatchedPathChanged(const QString &path);
/**
* Mark a virtual file as being ready for download, and start a sync.
* relativePath is the patch to the file (including the extension)
*/
void downloadVirtualFile(const QString &relativepath);
private slots:
void slotSyncStarted();
void slotSyncFinished(bool);
@@ -313,6 +325,19 @@ private slots:
/** Ensures that the next sync performs a full local discovery. */
void slotNextSyncFullLocalDiscovery();
/** Adjust sync result based on conflict data from IssuesWidget.
*
* This is pretty awkward, but IssuesWidget just keeps better track
* of conflicts across partial local discovery.
*/
void slotFolderConflicts(const QString &folder, const QStringList &conflictPaths);
/** Warn users if they create a file or folder that is selective-sync excluded */
void warnOnNewExcludedItem(const SyncJournalFileRecord &record, const QStringRef &path);
/** Warn users about an unreliable folder watcher */
void slotWatcherUnreliable(const QString &message);
private:
bool reloadExcludes();
@@ -347,7 +372,7 @@ private:
QElapsedTimer _timeSinceLastSyncDone;
QElapsedTimer _timeSinceLastSyncStart;
QElapsedTimer _timeSinceLastFullLocalDiscovery;
qint64 _lastSyncDuration;
std::chrono::milliseconds _lastSyncDuration;
/// The number of syncs that failed in a row.
/// Reset when a sync is successful.
@@ -359,8 +384,6 @@ private:
SyncJournalDb _journal;
ClientProxy _clientProxy;
QScopedPointer<SyncRunFileLog> _fileLog;
QTimer _scheduleSelfTimer;
@@ -383,20 +406,9 @@ private:
QScopedPointer<FolderWatcher> _folderWatcher;
/**
* The paths that should be checked by the next local discovery.
*
* Mostly a collection of files the filewatchers have reported as touched.
* Also includes files that have had errors in the last sync run.
* Keeps track of locally dirty files so we can skip local discovery sometimes.
*/
std::set<QByteArray> _localDiscoveryPaths;
/**
* The paths that the current sync run used for local discovery.
*
* For failing syncs, this list will be merged into _localDiscoveryPaths
* again when the sync is done to make sure everything is retried.
*/
std::set<QByteArray> _previousLocalDiscoveryPaths;
QScopedPointer<LocalDiscoveryTracker> _localDiscoveryTracker;
};
}

Some files were not shown because too many files have changed in this diff Show More