mirror of
https://github.com/chylex/Nextcloud-Desktop.git
synced 2026-04-03 18:11:32 +02:00
Compare commits
41 Commits
v2.5.0-alp
...
v2.4.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6e9755121 | ||
|
|
f283c0c59c | ||
|
|
0d83d7cb68 | ||
|
|
2e10cec2cb | ||
|
|
3802131bad | ||
|
|
5467950f62 | ||
|
|
3ba5bb52f3 | ||
|
|
5c011c5c21 | ||
|
|
532e975687 | ||
|
|
7efc3220f4 | ||
|
|
b5444def55 | ||
|
|
c7ba898fe0 | ||
|
|
7a8c8b19c2 | ||
|
|
72c9d207a0 | ||
|
|
1e4727cfec | ||
|
|
8237c5be69 | ||
|
|
63877d5293 | ||
|
|
737353a017 | ||
|
|
528b5e3108 | ||
|
|
5d098140e7 | ||
|
|
aeb4eed7b5 | ||
|
|
c68b112858 | ||
|
|
b4f2c3c369 | ||
|
|
084f522de1 | ||
|
|
5d5e0220b4 | ||
|
|
7b5ce24302 | ||
|
|
19e33d0924 | ||
|
|
f8a4994307 | ||
|
|
04fb952814 | ||
|
|
8d6e9523bb | ||
|
|
b317cc18d0 | ||
|
|
03a5833e29 | ||
|
|
91a9c65173 | ||
|
|
edabed9594 | ||
|
|
838beded20 | ||
|
|
7dcfe9993c | ||
|
|
b73e2fbdab | ||
|
|
d49771b43a | ||
|
|
928cdf4f4f | ||
|
|
8da6fc40a1 | ||
|
|
6e84a8d420 |
@@ -11,7 +11,6 @@ workspace:
|
||||
|
||||
branches:
|
||||
- master
|
||||
- 2.5
|
||||
- 2.4
|
||||
|
||||
clone:
|
||||
|
||||
123
.github/release_template.md
vendored
123
.github/release_template.md
vendored
@@ -16,7 +16,6 @@ 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
|
||||
@@ -26,94 +25,84 @@ Some weeks before the release:
|
||||
* use `git log --format=oneline v<lastrelease>...master` if your memory fails you
|
||||
* [ ] check if enterprise issues are fixed
|
||||
|
||||
For first Alpha/Beta of a Major or Minor release:
|
||||
* [ ] branch off master to new version branch (e.g. master -> 2.1, when releasing 2.1)
|
||||
* [ ] Adjust `VERSION.cmake` in master and count up (e.g. 2.2)
|
||||
* [ ] Adjust translation jobs for [client](https://ci.owncloud.org/view/translation-sync/job/translation-sync-client/) and [NSIS](https://ci.owncloud.org/view/translation-sync/job/translation-sync-client-nsis/) to point to the release branch (e.g. 2.1).
|
||||
* [ ] Make sure there is a job for the docs of the new master branch and the current release branch on rotor e.g. http://doc.owncloud.org/desktop/1.X/ exists
|
||||
|
||||
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)
|
||||
* (no need to copy builds as they are already in testing directory or repository) (https://github.com/owncloud/enterprise/wiki/Desktop-Signing-Knowledge)
|
||||
* [ ] 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 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:
|
||||
One week before the release:
|
||||
* [ ] Communicate the release schedule on mailinglist release-coordination@owncloud.com. Give a high level overview of the upcoming new features, changes etc.
|
||||
* [ ] Ensure marketing is aware (marketing@owncloud.com) and prepared for the release (social, .com website, cust. communications)
|
||||
* [ ] Inform GCX knows the next version is about 1 week out (gcx@owncloud.com)
|
||||
|
||||
Day before final Release:
|
||||
For all Betas and RCs:
|
||||
* [ ] 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
|
||||
* [ ] Create build for Windows using rotor job owncloud-client-win32 (uncheck the "nightly build" checkbox, check the "sign package" checkboxes) both themes 'ownCloud' and 'testpilotcould'
|
||||
* [ ] Create build for Mac using rotor, job owncloud-client-osx (uncheck the "nightly build" checkbox, check the "sign package" checkboxes) both themes 'ownCloud' and 'testpilotcould'
|
||||
* [ ] Create the beta tarball using Jenkins job ownCloud-client-source
|
||||
* [ ] Create Linux builds using rotor job owncloud-client-linux building (this magically interacts with the ownCloud-client-source job)
|
||||
* [ ] theme 'ownCloud' -> isv:ownCloud:community:testing
|
||||
* [ ] theme 'testpilotcould' -> isv:ownCloud:testpilot:testing
|
||||
* [ ] Copy builds from ```daily``` to ```testing``` on download.owncloud.com, double check the download links.
|
||||
* [ ] 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
|
||||
* [ ] Announce on https://central.owncloud.org
|
||||
* [ ] Create a signed tag using ```git tag -u E94E7B37 tagname``` (https://github.com/owncloud/enterprise/wiki/Desktop-Signing-Knowledge)
|
||||
* [ ] Check crash reporter
|
||||
|
||||
For first Beta of a Major or Minor release:
|
||||
* [ ] branch off master to new version branch (e.g. master -> 2.1, when releasing 2.1)
|
||||
* [ ] Adjust `VERSION.cmake` in master and count up (e.g. 2.2)
|
||||
* [ ] Adjust translation jobs for [client](https://ci.owncloud.org/view/translation-sync/job/translation-sync-client/) and [NSIS](https://ci.owncloud.org/view/translation-sync/job/translation-sync-client-nsis/) to point to the release branch (e.g. 2.1).
|
||||
* [ ] Make sure there is a job for the docs of the new master branch and the current release branch on rotor.
|
||||
|
||||
Day before Release:
|
||||
* [ ] Check the translations coming from transifex: All synchronized?
|
||||
* [ ] Run the tx.pl scripts on the final code tag
|
||||
* [ ] Run ```make test```
|
||||
* [ ] Run smashbox
|
||||
* [ ] Run smashbox on the final code tag
|
||||
* [ ] Inform product management and marketing that we are 1 day out
|
||||
|
||||
On Release Day (for final release):
|
||||
* [ ] Branch off a release branch called like the version (without v, v is for tags)
|
||||
* [ ] Double check ```VERSION.cmake```: Check the version number settings and suffix (beta etc.) to be removed. Commit change to 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
|
||||
* [ ] Add last updates to Changelog in the client source repository.
|
||||
* [ ] 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 (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)```
|
||||
|
||||
* [ ] Create tar ball (automated by `ownCloud-client-source` jenkins job) and **immediately** sign it (asc file). (https://github.com/owncloud/enterprise/wiki/Desktop-Signing-Knowledge)
|
||||
* [ ] Create build for Windows using rotor job owncloud-client-win32 (uncheck the "nightly build" checkbox, check the "sign package" checkboxes) both themes 'ownCloud' and 'testpilotcould'
|
||||
* [ ] Create build for Mac using rotor, job owncloud-client-osx (uncheck the "nightly build" checkbox, check the "sign package" checkboxes) both themes 'ownCloud' and 'testpilotcould'
|
||||
* [ ] Stop publishing on OBS
|
||||
* [ ] 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
|
||||
* [ ] Create Linux builds using rotor job owncloud-client-linux (this magically interacts with the ownCloud-client-source job)
|
||||
* 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`
|
||||
* [ ] theme 'ownCloud' -> isv:ownCloud:desktop
|
||||
* [ ] theme 'testpilotcloud' -> isv:ownCloud:testpilot
|
||||
* [ ] Linux: Update the testing repository to the latest stable version.
|
||||
* [ ] Inform GCX that a new tarball is available.
|
||||
* [ ] Copy builds and source tar ball from ```daily``` to ```stable``` on download.owncloud.com, double check the download links.
|
||||
* [ ] Check if the following packages are on download.owncloud.com/desktop/stable:
|
||||
* Windows binary package
|
||||
* Mac binary package
|
||||
* source tarballs
|
||||
* [ ] 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.
|
||||
* [ ] 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 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"
|
||||
* [ ] Linux: Smoke test
|
||||
* [ ] Linux: Re-enable OBS publishing
|
||||
* Let obs build and publish exactly once. then
|
||||
* [ ] disable publishing and rebuild for the owncloud-client package and all its dependencies.
|
||||
* [ ] double-check that there are no _aggregatepac from other projects, if so disable rebuilding there too.
|
||||
* [ ] Update ASCII Changelog on http://download.owncloud.com/download/changelog-client
|
||||
* [ ] Announce on https://central.owncloud.org
|
||||
* [ ] Announce on announcements@owncloud.org Link to the central post so discussion happens there.
|
||||
* [ ] Inform packagers @dragotin (openSUSE) @hefee (Debian) @Germano0 (Fedora)
|
||||
* [ ] Announce on announcements@owncloud.org
|
||||
* [ ] Create git signed tag in client repository using ```git tag -u E94E7B37 tagname```
|
||||
* [ ] 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
|
||||
* [ ] Days later: Update the updater script ```clientupdater.php``` (check the crash reporter if auto update is a good idea or we need a new release)
|
||||
* [ ] 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
|
||||
|
||||
15 minutes after after release:
|
||||
* [ ] Test all advertised download links to have the expected version
|
||||
* [ ] 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``` 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
3
.gitmodules
vendored
@@ -7,6 +7,3 @@
|
||||
[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
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
cmake_policy(VERSION 2.8.0)
|
||||
if(POLICY CMP0020)
|
||||
cmake_policy(SET CMP0020 NEW)
|
||||
endif()
|
||||
|
||||
project(client)
|
||||
|
||||
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
||||
|
||||
|
||||
set(OEM_THEME_DIR "" CACHE STRING "Define directory containing a custom theme")
|
||||
if ( EXISTS ${OEM_THEME_DIR}/OEM.cmake )
|
||||
include ( ${OEM_THEME_DIR}/OEM.cmake )
|
||||
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")
|
||||
@@ -64,6 +61,14 @@ if(NOT WITH_CRASHREPORTER)
|
||||
message(STATUS "Build of crashreporter disabled.")
|
||||
endif()
|
||||
|
||||
#####
|
||||
## handle DBUS for Fdo notifications
|
||||
if( UNIX AND NOT APPLE )
|
||||
add_definitions( -DUSE_FDO_NOTIFICATIONS)
|
||||
set(WITH_DBUS ON)
|
||||
endif()
|
||||
####
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(DefineInstallationPaths)
|
||||
include(GenerateExportHeader)
|
||||
@@ -72,12 +77,6 @@ include(GetGitRevisionDescription)
|
||||
|
||||
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
||||
|
||||
add_definitions(
|
||||
-DQT_USE_QSTRINGBUILDER
|
||||
-DQT_MESSAGELOGCONTEXT #enable function name and line number in debug output
|
||||
-DQT_DEPRECATED_WARNINGS
|
||||
)
|
||||
|
||||
# if we cannot get it from git, directly try .tag (packages)
|
||||
# this will work if the tar balls have been properly created
|
||||
# via git-archive.
|
||||
@@ -191,11 +190,20 @@ if(BUILD_CLIENT)
|
||||
find_package(Sphinx)
|
||||
find_package(PdfLatex)
|
||||
|
||||
find_package(SQLite3 3.8.0 REQUIRED)
|
||||
# On some OS, we want to use our own, not the system sqlite
|
||||
if (USE_OUR_OWN_SQLITE3)
|
||||
include_directories(BEFORE ${SQLITE3_INCLUDE_DIR})
|
||||
if (WIN32)
|
||||
add_definitions(-DSQLITE_API=__declspec\(dllimport\))
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED APPLICATION_ICON_NAME)
|
||||
set(APPLICATION_ICON_NAME "${APPLICATION_SHORTNAME}")
|
||||
set(APPLICATION_ICON_NAME ${APPLICATION_SHORTNAME})
|
||||
endif()
|
||||
|
||||
include(OwnCloudCPack.cmake)
|
||||
@@ -205,11 +213,22 @@ add_definitions(-D_UNICODE)
|
||||
if( WIN32 )
|
||||
add_definitions( -D__USE_MINGW_ANSI_STDIO=1 )
|
||||
add_definitions( -DNOMINMAX )
|
||||
# Get APIs from from Vista onwards.
|
||||
add_definitions( -D_WIN32_WINNT=0x0600)
|
||||
add_definitions( -DWINVER=0x0600)
|
||||
endif( WIN32 )
|
||||
|
||||
include(QtVersionAbstraction)
|
||||
setup_qt()
|
||||
if (${Qt5Core_VERSION_MAJOR} EQUAL "5")
|
||||
if (${Qt5Core_VERSION_MINOR} EQUAL "6" OR ${Qt5Core_VERSION_MINOR} GREATER 6)
|
||||
else()
|
||||
message(STATUS "If possible compile me with Qt 5.6 or higher.")
|
||||
endif()
|
||||
if (${Qt5Core_VERSION_MINOR} EQUAL "9" OR ${Qt5Core_VERSION_MINOR} GREATER 9)
|
||||
else()
|
||||
message(STATUS "For HTTP2 use Qt 5.9.2 or higher.")
|
||||
endif()
|
||||
endif()
|
||||
message("Qt ${Qt5Core_VERSION} at ${Qt5Core_INCLUDE_DIRS}")
|
||||
|
||||
if (APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
endif()
|
||||
@@ -218,6 +237,9 @@ 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)
|
||||
|
||||
96
ChangeLog
96
ChangeLog
@@ -1,92 +1,24 @@
|
||||
ChangeLog
|
||||
=========
|
||||
|
||||
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
|
||||
version 2.4.2 (2018-06-xx)
|
||||
* Linux: Tray workarounds (#6545)
|
||||
* Fix nautilus/nemo shell issues (#6393, #6406)
|
||||
* Updater: Add update channel feature (#6259)
|
||||
* Updater: Support EXE->MSI upgrade
|
||||
* SyncJournal: Fixes for sync folders on removable media (#6049, #6049)
|
||||
* 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)
|
||||
* Fix assert when using ownCloud server 5 (which you should not) (#6403)
|
||||
* Normalize local path (#4424)
|
||||
* 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)
|
||||
* macdeployqt: Adjust minimum version based on our Qt (#5932)
|
||||
* 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
|
||||
* Upload: Adjust timeout for final job based on file size (#6527)
|
||||
* Sync: When detecting a local move, keep the local mtime (#6629)
|
||||
* Credentials: Retry fetching from the keychain in case the keychain is still starting (#4274, #6522)
|
||||
* OAuth2: Try to refresh the token even if the credentials weren't ready (#6522)
|
||||
|
||||
version 2.4.1 (2018-03-05)
|
||||
version 2.4.1 (2018-02-xx)
|
||||
* 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
|
||||
|
||||
72
Jenkinsfile
vendored
72
Jenkinsfile
vendored
@@ -1,72 +0,0 @@
|
||||
#!groovy
|
||||
|
||||
//
|
||||
// We now run the tests in Debug mode so that ASSERTs are triggered.
|
||||
// Ideally we should run the tests in both Debug and Release so we catch
|
||||
// all possible error combinations.
|
||||
// See also the top comment in syncenginetestutils.h
|
||||
//
|
||||
// We are building "Linux - GCC" with "make" and "Linux - 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.
|
||||
|
||||
// Constructed from the DockerFile in admin/linux/DockerFile
|
||||
def linux = docker.image('dominikschmidt/docker-owncloud-client-linux:latest')
|
||||
// Constructed from the DockerFile in admin/win/docker/DockerFile
|
||||
def win32 = docker.image('dominikschmidt/docker-owncloud-client-win32-cross:latest')
|
||||
|
||||
node('CLIENT') {
|
||||
stage 'Checkout'
|
||||
checkout scm
|
||||
sh '''git submodule update --init'''
|
||||
|
||||
stage 'Linux - Pull Docker Image'
|
||||
linux.pull()
|
||||
|
||||
stage 'Linux - GCC'
|
||||
linux.inside {
|
||||
sh '''
|
||||
export HOME="$(pwd)/home"
|
||||
rm -rf build home
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE="Debug" -DUNIT_TESTING=1 ..
|
||||
make -j4
|
||||
LC_ALL=C.UTF-8 ctest -V --output-on-failure
|
||||
'''
|
||||
}
|
||||
|
||||
stage 'Linux - Clang'
|
||||
linux.inside {
|
||||
sh '''
|
||||
export HOME="$(pwd)/home"
|
||||
rm -rf build home
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE="Debug" -DUNIT_TESTING=1 ..
|
||||
ninja -j4
|
||||
LC_ALL=C.UTF-8 ctest -V --output-on-failure
|
||||
'''
|
||||
}
|
||||
|
||||
stage 'Win32 Cross - Pull Docker Image'
|
||||
win32.pull()
|
||||
|
||||
stage 'Win32 Cross'
|
||||
win32.inside {
|
||||
sh '''
|
||||
rm -rf build-win32
|
||||
mkdir build-win32
|
||||
cd build-win32
|
||||
../admin/win/download_runtimes.sh
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=../admin/win/Toolchain-mingw32-openSUSE.cmake -DWITH_CRASHREPORTER=ON
|
||||
make -j4
|
||||
make package
|
||||
ctest .
|
||||
'''
|
||||
}
|
||||
|
||||
// Stage 'macOS' TODO
|
||||
}
|
||||
@@ -5,7 +5,6 @@ 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" )
|
||||
|
||||
|
||||
34
README.md
34
README.md
@@ -1,7 +1,6 @@
|
||||
# ownCloud Desktop Client
|
||||
|
||||
[](https://jenkins.owncloud.org/job/owncloud-client/job/client/job/master/) [](https://ci.appveyor.com/project/ownclouders/client/branch/master)
|
||||
|
||||
[](https://drone.owncloud.com/owncloud/client)
|
||||
|
||||
## Introduction
|
||||
|
||||
@@ -12,7 +11,7 @@ with your computer.
|
||||
|
||||
### Binary packages
|
||||
|
||||
* Refer to the download page https://owncloud.org/download/#owncloud-desktop-client
|
||||
* Refer to the download page https://owncloud.org/install/#install-clients
|
||||
|
||||
### Source code
|
||||
|
||||
@@ -27,6 +26,18 @@ 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
|
||||
@@ -44,23 +55,6 @@ 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
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
set( MIRALL_VERSION_MAJOR 2 )
|
||||
set( MIRALL_VERSION_MINOR 5 )
|
||||
set( MIRALL_VERSION_PATCH 0 )
|
||||
set( MIRALL_VERSION_MINOR 4 )
|
||||
set( MIRALL_VERSION_PATCH 2 )
|
||||
set( MIRALL_VERSION_YEAR 2018 )
|
||||
set( MIRALL_SOVERSION 0 )
|
||||
|
||||
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||
set( MIRALL_VERSION_SUFFIX "alpha1") #e.g. beta1, beta2, rc1
|
||||
set( MIRALL_VERSION_SUFFIX "") #e.g. beta1, beta2, rc1
|
||||
endif( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||
|
||||
if( NOT DEFINED MIRALL_VERSION_BUILD )
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
# This DockerFile is used to create the image used for Jenkins, the CI system (see Jenkinsfile)
|
||||
# It is not meant to be used to create the production packages.
|
||||
|
||||
# Distro with Qt 5.6
|
||||
FROM ubuntu:yakkety
|
||||
|
||||
RUN apt-get update -q && DEBIAN_FRONTEND=noninteractive apt-get install -q -y --no-install-recommends \
|
||||
locales \
|
||||
build-essential \
|
||||
clang \
|
||||
ninja-build \
|
||||
cmake \
|
||||
extra-cmake-modules \
|
||||
libsqlite3-dev \
|
||||
libssl-dev \
|
||||
libcmocka-dev \
|
||||
qt5-default \
|
||||
qttools5-dev-tools \
|
||||
libqt5webkit5-dev \
|
||||
qt5keychain-dev \
|
||||
kio-dev \
|
||||
&& apt-get clean
|
||||
@@ -12,7 +12,7 @@ else()
|
||||
endif()
|
||||
|
||||
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(create_mac_pkg.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/create_mac.sh)
|
||||
configure_file(macosx.pkgproj ${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)
|
||||
|
||||
@@ -579,9 +579,7 @@
|
||||
</dict>
|
||||
</dict>
|
||||
<key>INSTALLATION TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>MODE</key>
|
||||
<integer>1</integer>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>INSTALLATION_STEPS</key>
|
||||
<array>
|
||||
@@ -701,7 +699,7 @@
|
||||
<key>BUILD_PATH</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
<string>@CMAKE_INSTALL_PREFIX@/.</string>
|
||||
<string>../install/.</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
</dict>
|
||||
@@ -1,16 +1,12 @@
|
||||
#!/bin/sh
|
||||
|
||||
# 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
|
||||
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
|
||||
|
||||
40
admin/osx/sign_dmg.sh
Executable file
40
admin/osx/sign_dmg.sh
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/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"
|
||||
@@ -27,8 +27,8 @@ SET(QT_MKSPECS_DIR ${CMAKE_FIND_ROOT_PATH}/share/qt5/mkspecs)
|
||||
SET(QT_QT_INCLUDE_DIR ${CMAKE_FIND_ROOT_PATH}/include)
|
||||
|
||||
# qt tools
|
||||
SET(QT_QMAKE_EXECUTABLE ${MINGW_PREFIX}-qmake-qt5)
|
||||
SET(QT_MOC_EXECUTABLE ${MINGW_PREFIX}-moc-qt5)
|
||||
SET(QT_RCC_EXECUTABLE ${MINGW_PREFIX}-rcc-qt5)
|
||||
SET(Qt5Widgets_UIC_EXECUTABLE ${MINGW_PREFIX}-uic-qt5)
|
||||
SET(QT_LRELEASE_EXECUTABLE ${MINGW_PREFIX}-lrelease-qt5)
|
||||
SET(QT_QMAKE_EXECUTABLE ${MINGW_PREFIX}-qmake )
|
||||
SET(QT_MOC_EXECUTABLE ${MINGW_PREFIX}-moc)
|
||||
SET(QT_RCC_EXECUTABLE ${MINGW_PREFIX}-rcc)
|
||||
SET(QT_UIC_EXECUTABLE ${MINGW_PREFIX}-uic)
|
||||
SET(QT_LRELEASE_EXECUTABLE ${MINGW_PREFIX}-lrelease)
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
FROM opensuse:42.1
|
||||
|
||||
MAINTAINER Daniel Molkentin <danimo@owncloud.com>
|
||||
|
||||
ENV TERM ansi
|
||||
ENV HOME /root
|
||||
|
||||
ENV REFRESHED_AT 20170113
|
||||
ENV REFRESHED_AT 20160421
|
||||
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys refresh
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys ar http://download.opensuse.org/repositories/windows:/mingw/openSUSE_Leap_42.1/windows:mingw.repo
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys ar http://download.opensuse.org/repositories/isv:ownCloud:toolchains:mingw:win32:2.3/openSUSE_Leap_42.1/isv:ownCloud:toolchains:mingw:win32:2.3.repo
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys install cmake make mingw32-cross-binutils mingw32-cross-cpp mingw32-cross-gcc \
|
||||
mingw32-cross-gcc-c++ mingw32-cross-pkg-config mingw32-filesystem \
|
||||
mingw32-headers mingw32-runtime site-config mingw32-libwebp mingw32-libssp0 \
|
||||
mingw32-headers mingw32-runtime site-config mingw32-libwebp \
|
||||
mingw32-cross-libqt5-qmake mingw32-cross-libqt5-qttools mingw32-libqt5* \
|
||||
mingw32-qt5keychain* mingw32-angleproject* \
|
||||
mingw32-cross-nsis mingw32-libopenssl* \
|
||||
mingw32-sqlite* png2ico \
|
||||
mingw32-sqlite* kdewin-png2ico \
|
||||
osslsigncode wget
|
||||
|
||||
# RPM depends on curl for installs from HTTP
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
; 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
|
||||
50
appveyor.ini
50
appveyor.ini
@@ -1,50 +0,0 @@
|
||||
[General]
|
||||
Branch = master
|
||||
ShallowClone = True
|
||||
Command=craft
|
||||
|
||||
# Variables defined here override the default value
|
||||
# The variable names are casesensitive
|
||||
[Variables]
|
||||
#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
|
||||
# Category is case sensitive
|
||||
|
||||
[GeneralSettings]
|
||||
General/EMERGE_PKGDSTDIR=${Variables:APPVEYOR_BUILD_FOLDER}/binaries
|
||||
Paths/python = C:\Python36
|
||||
Paths/python27 = C:\Python27
|
||||
Paths/downloaddir = ${Variables:Root}\downloads
|
||||
ShortPath/Enabled = False
|
||||
ShortPath/EnableJunctions = True
|
||||
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/
|
||||
Compile/BuildType = RelWithDebInfo
|
||||
ContinuousIntegration/Enabled = True
|
||||
|
||||
[BlueprintSettings]
|
||||
# don't try to pip install on the ci
|
||||
python-modules.ignored = True
|
||||
|
||||
libs/qt5.version = ${Variables:QtVersion}
|
||||
win32libs/openssl.version = ${Variables:OpenSslVersion}
|
||||
craft/craft-core.version = master
|
||||
|
||||
[windows-msvc2017_64-cl]
|
||||
General/ABI = windows-msvc2017_64-cl
|
||||
|
||||
[windows-msvc2017_32-cl]
|
||||
General/ABI = windows-msvc2017_32-cl
|
||||
43
appveyor.yml
43
appveyor.yml
@@ -1,43 +0,0 @@
|
||||
version: '{build}-{branch}'
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
clone_depth: 50
|
||||
|
||||
|
||||
init:
|
||||
- ps: |
|
||||
function craft($target) {
|
||||
& C:\Python36\python.exe "C:\CraftMaster\CraftMaster\CraftMaster.py" --config "$env:APPVEYOR_BUILD_FOLDER\appveyor.ini" --variables "APPVEYOR_BUILD_FOLDER=$env:APPVEYOR_BUILD_FOLDER" --target $target -c $args
|
||||
if($LASTEXITCODE -ne 0) {exit $LASTEXITCODE}
|
||||
}
|
||||
|
||||
install:
|
||||
- ps: |
|
||||
#use cmd to silence powershell behaviour for stderr
|
||||
& 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:
|
||||
- ps: |
|
||||
craft $env:TARGET --no-cache --src-dir $env:APPVEYOR_BUILD_FOLDER owncloud-client
|
||||
|
||||
after_build:
|
||||
- ps: |
|
||||
craft $env:TARGET --src-dir $env:APPVEYOR_BUILD_FOLDER --package owncloud-client
|
||||
|
||||
test_script:
|
||||
- ps: |
|
||||
craft $env:TARGET --src-dir $env:APPVEYOR_BUILD_FOLDER --test owncloud-client
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- TARGET: windows-msvc2017_32-cl
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
- TARGET: windows-msvc2017_64-cl
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
2
binary
2
binary
Submodule binary updated: 09f12de312...3425fab2c6
@@ -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.svg</file>
|
||||
<file>resources/more.png</file>
|
||||
<file>resources/delete.png</file>
|
||||
<file>resources/bell.png</file>
|
||||
</qresource>
|
||||
|
||||
@@ -1,382 +0,0 @@
|
||||
#.rst:
|
||||
# ECMAddAppIcon
|
||||
# -------------
|
||||
#
|
||||
# Add icons to executable files and packages.
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# ecm_add_app_icon(<sources_var>
|
||||
# ICONS <icon> [<icon> [...]]
|
||||
# [SIDEBAR_ICONS <icon> [<icon> [...]] # Since 5.4x
|
||||
# [OUTFILE_BASE <name>]) # Since 5.4x
|
||||
# )
|
||||
#
|
||||
# The given icons, whose names must match the pattern::
|
||||
#
|
||||
# <size>-<other_text>.png
|
||||
#
|
||||
# will be added to the executable target whose sources are specified by
|
||||
# ``<sources_var>`` on platforms that support it (Windows and Mac OS X).
|
||||
# Other icon files are ignored but on Mac SVG files can be supported and
|
||||
# it is thus possible to mix those with png files in a single macro call.
|
||||
#
|
||||
# ``<size>`` is a numeric pixel size (typically 16, 32, 48, 64, 128 or 256).
|
||||
# ``<other_text>`` can be any other text. See the platform notes below for any
|
||||
# recommendations about icon sizes.
|
||||
#
|
||||
# ``SIDEBAR_ICONS`` can be used to add Mac OS X sidebar
|
||||
# icons to the generated iconset. They are used when a folder monitored by the
|
||||
# application is dragged into Finder's sidebar. Since 5.4x.
|
||||
#
|
||||
# ``OUTFILE_BASE`` will be used as the basename for the icon file. If
|
||||
# you specify it, the icon file will be called ``<OUTFILE_BASE>.icns`` on Mac OS X
|
||||
# and ``<OUTFILE_BASE>.ico`` on Windows. If you don't specify it, it defaults
|
||||
# to ``<sources_var>.<ext>``. Since 5.4x.
|
||||
#
|
||||
#
|
||||
# Windows notes
|
||||
# * Icons are compiled into the executable using a resource file.
|
||||
# * Icons may not show up in Windows Explorer if the executable
|
||||
# target does not have the ``WIN32_EXECUTABLE`` property set.
|
||||
# * The tool png2ico is required. See :find-module:`FindPng2Ico`.
|
||||
# * Supported sizes: 16, 32, 48, 64, 128.
|
||||
#
|
||||
# Mac OS X notes
|
||||
# * The executable target must have the ``MACOSX_BUNDLE`` property set.
|
||||
# * Icons are added to the bundle.
|
||||
# * If the ksvg2icns tool from KIconThemes is available, .svg and .svgz
|
||||
# files are accepted; the first that is converted successfully to .icns
|
||||
# will provide the application icon. SVG files are ignored otherwise.
|
||||
# * The tool iconutil (provided by Apple) is required for bitmap icons.
|
||||
# * Supported sizes: 16, 32, 64, 128, 256 (and 512, 1024 after OS X 10.9).
|
||||
# * At least a 128x128px (or an SVG) icon is required.
|
||||
# * Larger sizes are automatically used to substitute for smaller sizes on
|
||||
# "Retina" (high-resolution) displays. For example, a 32px icon, if
|
||||
# provided, will be used as a 32px icon on standard-resolution displays,
|
||||
# and as a 16px-equivalent icon (with an "@2x" tag) on high-resolution
|
||||
# displays. That is why you should provide 64px and 1024px icons although
|
||||
# they are not supported anymore directly. Instead they will be used as
|
||||
# 32px@2x and 512px@2x. ksvg2icns handles this internally.
|
||||
# * This function sets the ``MACOSX_BUNDLE_ICON_FILE`` variable to the name
|
||||
# of the generated icns file, so that it will be used as the
|
||||
# ``MACOSX_BUNDLE_ICON_FILE`` target property when you call
|
||||
# ``add_executable``.
|
||||
# * Sidebar icons should typically provided in 16, 32, 64, 128 and 256px.
|
||||
#
|
||||
# Since 1.7.0.
|
||||
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2014 Alex Merry <alex.merry@kde.org>
|
||||
# Copyright 2014 Ralf Habacker <ralf.habacker@freenet.de>
|
||||
# Copyright 2006-2009 Alexander Neundorf, <neundorf@kde.org>
|
||||
# Copyright 2006, 2007, Laurent Montel, <montel@kde.org>
|
||||
# Copyright 2007 Matthias Kretz <kretz@kde.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. The name of the author may not be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
function(ecm_add_app_icon appsources)
|
||||
set(options)
|
||||
set(oneValueArgs OUTFILE_BASE)
|
||||
set(multiValueArgs ICONS SIDEBAR_ICONS)
|
||||
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(NOT ARG_ICONS)
|
||||
message(FATAL_ERROR "No ICONS argument given to ecm_add_app_icon")
|
||||
endif()
|
||||
if(ARG_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "Unexpected arguments to ecm_add_app_icon: ${ARG_UNPARSED_ARGUMENTS}")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
find_program(KSVG2ICNS NAMES ksvg2icns)
|
||||
foreach(icon ${ARG_ICONS})
|
||||
get_filename_component(icon_full ${icon} ABSOLUTE)
|
||||
get_filename_component(icon_type ${icon_full} EXT)
|
||||
# do we have ksvg2icns in the path and did we receive an svg (or compressed svg) icon?
|
||||
if(KSVG2ICNS AND (${icon_type} STREQUAL ".svg" OR ${icon_type} STREQUAL ".svgz"))
|
||||
# convert the svg icon to an icon resource
|
||||
execute_process(COMMAND ${KSVG2ICNS} "${icon_full}"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} RESULT_VARIABLE KSVG2ICNS_ERROR)
|
||||
if(${KSVG2ICNS_ERROR})
|
||||
message(AUTHOR_WARNING "ksvg2icns could not generate an OS X application icon from ${icon}")
|
||||
else()
|
||||
# install the icns file we just created
|
||||
get_filename_component(icon_name ${icon_full} NAME_WE)
|
||||
set(MACOSX_BUNDLE_ICON_FILE ${icon_name}.icns PARENT_SCOPE)
|
||||
set(${appsources} "${${appsources}};${CMAKE_CURRENT_BINARY_DIR}/${icon_name}.icns" PARENT_SCOPE)
|
||||
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${icon_name}.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
# we're done now
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
|
||||
_ecm_add_app_icon_categorize_icons("${ARG_ICONS}" "icons" "16;32;48;64;128;256;512;1024")
|
||||
if(ARG_SIDEBAR_ICONS)
|
||||
_ecm_add_app_icon_categorize_icons("${ARG_SIDEBAR_ICONS}" "sidebar_icons" "16;18;32;36;64")
|
||||
endif()
|
||||
|
||||
set(mac_icons
|
||||
# Icons: https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Optimizing/Optimizing.html#//apple_ref/doc/uid/TP40012302-CH7-SW4
|
||||
${icons_at_16px}
|
||||
${icons_at_32px}
|
||||
${icons_at_64px}
|
||||
${icons_at_128px}
|
||||
${icons_at_256px}
|
||||
${icons_at_512px}
|
||||
${icons_at_1024px}
|
||||
|
||||
# Sidebar Icons: https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Finder.html#//apple_ref/doc/uid/TP40014214-CH15-SW15
|
||||
${sidebar_icons_at_16px}
|
||||
${sidebar_icons_at_18px}
|
||||
${sidebar_icons_at_32px}
|
||||
${sidebar_icons_at_36px}
|
||||
${sidebar_icons_at_64px})
|
||||
if (NOT icons_at_128px)
|
||||
message(AUTHOR_WARNING "No 128px icon provided; this will not work on Mac OS X")
|
||||
endif()
|
||||
|
||||
|
||||
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()
|
||||
|
||||
if (ARG_OUTFILE_BASE)
|
||||
set (_outfilebasename "${ARG_OUTFILE_BASE}")
|
||||
else()
|
||||
set (_outfilebasename "${appsources}")
|
||||
endif()
|
||||
set (_outfilename "${CMAKE_CURRENT_BINARY_DIR}/${_outfilebasename}")
|
||||
|
||||
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}")
|
||||
|
||||
function(create_windows_icon_and_rc command args deps)
|
||||
add_custom_command(
|
||||
OUTPUT "${_outfilename}.ico"
|
||||
COMMAND ${command}
|
||||
ARGS ${args}
|
||||
DEPENDS ${deps}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
)
|
||||
# this bit's a little hacky to make the dependency stuff work
|
||||
file(WRITE "${_outfilename}.rc.in" "IDI_ICON1 ICON DISCARDABLE \"${_outfilename}.ico\"\n")
|
||||
add_custom_command(
|
||||
OUTPUT "${_outfilename}.rc"
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
ARGS -E copy "${_outfilename}.rc.in" "${_outfilename}.rc"
|
||||
DEPENDS "${_outfilename}.ico"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
)
|
||||
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 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,
|
||||
# to create retina compatible icon, you need png source files in pixel resolution 16x16, 32x32, 64x64, 128x128,
|
||||
# 256x256, 512x512, 1024x1024
|
||||
find_program(ICONUTIL_EXECUTABLE NAMES iconutil)
|
||||
if (ICONUTIL_EXECUTABLE)
|
||||
add_custom_command(
|
||||
OUTPUT "${_outfilename}.iconset"
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
ARGS -E make_directory "${_outfilename}.iconset"
|
||||
)
|
||||
set(iconset_icons)
|
||||
macro(copy_icon filename sizename type)
|
||||
add_custom_command(
|
||||
OUTPUT "${_outfilename}.iconset/${type}_${sizename}.png"
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
ARGS -E copy
|
||||
"${filename}"
|
||||
"${_outfilename}.iconset/${type}_${sizename}.png"
|
||||
DEPENDS
|
||||
"${_outfilename}.iconset"
|
||||
"${filename}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
)
|
||||
list(APPEND iconset_icons
|
||||
"${_outfilename}.iconset/${type}_${sizename}.png")
|
||||
endmacro()
|
||||
foreach(size 16 32 128 256 512)
|
||||
math(EXPR double_size "2 * ${size}")
|
||||
foreach(file ${icons_at_${size}px})
|
||||
copy_icon("${file}" "${size}x${size}" "icon")
|
||||
endforeach()
|
||||
foreach(file ${icons_at_${double_size}px})
|
||||
copy_icon("${file}" "${size}x${size}@2x" "icon")
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
foreach(size 16 18 32)
|
||||
math(EXPR double_size "2 * ${size}")
|
||||
foreach(file ${sidebar_icons_at_${size}px})
|
||||
copy_icon("${file}" "${size}x${size}" "sidebar")
|
||||
endforeach()
|
||||
foreach(file ${sidebar_icons_at_${double_size}px})
|
||||
copy_icon("${file}" "${size}x${size}@2x" "sidebar")
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
# generate .icns icon file
|
||||
add_custom_command(
|
||||
OUTPUT "${_outfilename}.icns"
|
||||
COMMAND ${ICONUTIL_EXECUTABLE}
|
||||
ARGS
|
||||
--convert icns
|
||||
--output "${_outfilename}.icns"
|
||||
"${_outfilename}.iconset"
|
||||
DEPENDS "${iconset_icons}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
)
|
||||
# This will register the icon into the bundle
|
||||
set(MACOSX_BUNDLE_ICON_FILE "${_outfilebasename}.icns" PARENT_SCOPE)
|
||||
|
||||
# Append the icns file to the sources list so it will be a dependency to the
|
||||
# main target
|
||||
set(${appsources} "${${appsources}};${_outfilename}.icns" PARENT_SCOPE)
|
||||
|
||||
# Install the icon into the Resources dir in the bundle
|
||||
set_source_files_properties("${_outfilename}.icns" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
else()
|
||||
message(STATUS "Unable to find the iconutil utility - application will not have an application icon!")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
macro(_ecm_add_app_icon_categorize_icons icons type known_sizes)
|
||||
set(_${type}_known_sizes)
|
||||
foreach(size ${known_sizes})
|
||||
set(${type}_at_${size}px)
|
||||
list(APPEND _${type}_known_sizes ${size})
|
||||
endforeach()
|
||||
|
||||
|
||||
foreach(icon ${icons})
|
||||
get_filename_component(icon_full ${icon} ABSOLUTE)
|
||||
if (NOT EXISTS "${icon_full}")
|
||||
message(AUTHOR_WARNING "${icon_full} does not exist, ignoring")
|
||||
else()
|
||||
get_filename_component(icon_name ${icon} NAME)
|
||||
string(REGEX MATCH "([0-9]+)\\-[^/]+\\.([a-z]+)$"
|
||||
_dummy "${icon_name}")
|
||||
set(size "${CMAKE_MATCH_1}")
|
||||
set(ext "${CMAKE_MATCH_2}")
|
||||
|
||||
if (NOT (ext STREQUAL "svg" OR ext STREQUAL "svgz"))
|
||||
if (NOT size)
|
||||
message(AUTHOR_WARNING "${icon_full} is not named correctly for ecm_add_app_icon - ignoring")
|
||||
elseif (NOT ext STREQUAL "png")
|
||||
message(AUTHOR_WARNING "${icon_full} is not a png file - ignoring")
|
||||
else()
|
||||
list(FIND _${type}_known_sizes ${size} offset)
|
||||
|
||||
if (offset GREATER -1)
|
||||
list(APPEND ${type}_at_${size}px "${icon_full}")
|
||||
elseif()
|
||||
message(STATUS "not found ${type}_at_${size}px ${icon_full}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
@@ -1,297 +0,0 @@
|
||||
#.rst:
|
||||
# ECMFindModuleHelpers
|
||||
# --------------------
|
||||
#
|
||||
# Helper macros for find modules: ecm_find_package_version_check(),
|
||||
# ecm_find_package_parse_components() and
|
||||
# ecm_find_package_handle_library_components().
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# ecm_find_package_version_check(<name>)
|
||||
#
|
||||
# Prints warnings if the CMake version or the project's required CMake version
|
||||
# is older than that required by extra-cmake-modules.
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# ecm_find_package_parse_components(<name>
|
||||
# RESULT_VAR <variable>
|
||||
# KNOWN_COMPONENTS <component1> [<component2> [...]]
|
||||
# [SKIP_DEPENDENCY_HANDLING])
|
||||
#
|
||||
# This macro will populate <variable> with a list of components found in
|
||||
# <name>_FIND_COMPONENTS, after checking that all those components are in the
|
||||
# list of KNOWN_COMPONENTS; if there are any unknown components, it will print
|
||||
# an error or warning (depending on the value of <name>_FIND_REQUIRED) and call
|
||||
# return().
|
||||
#
|
||||
# The order of components in <variable> is guaranteed to match the order they
|
||||
# are listed in the KNOWN_COMPONENTS argument.
|
||||
#
|
||||
# If SKIP_DEPENDENCY_HANDLING is not set, for each component the variable
|
||||
# <name>_<component>_component_deps will be checked for dependent components.
|
||||
# If <component> is listed in <name>_FIND_COMPONENTS, then all its (transitive)
|
||||
# dependencies will also be added to <variable>.
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# ecm_find_package_handle_library_components(<name>
|
||||
# COMPONENTS <component> [<component> [...]]
|
||||
# [SKIP_DEPENDENCY_HANDLING])
|
||||
# [SKIP_PKG_CONFIG])
|
||||
#
|
||||
# Creates an imported library target for each component. The operation of this
|
||||
# macro depends on the presence of a number of CMake variables.
|
||||
#
|
||||
# The <name>_<component>_lib variable should contain the name of this library,
|
||||
# and <name>_<component>_header variable should contain the name of a header
|
||||
# file associated with it (whatever relative path is normally passed to
|
||||
# '#include'). <name>_<component>_header_subdir variable can be used to specify
|
||||
# which subdirectory of the include path the headers will be found in.
|
||||
# ecm_find_package_components() will then search for the library
|
||||
# and include directory (creating appropriate cache variables) and create an
|
||||
# imported library target named <name>::<component>.
|
||||
#
|
||||
# Additional variables can be used to provide additional information:
|
||||
#
|
||||
# If SKIP_PKG_CONFIG, the <name>_<component>_pkg_config variable is set, and
|
||||
# pkg-config is found, the pkg-config module given by
|
||||
# <name>_<component>_pkg_config will be searched for and used to help locate the
|
||||
# library and header file. It will also be used to set
|
||||
# <name>_<component>_VERSION.
|
||||
#
|
||||
# Note that if version information is found via pkg-config,
|
||||
# <name>_<component>_FIND_VERSION can be set to require a particular version
|
||||
# for each component.
|
||||
#
|
||||
# If SKIP_DEPENDENCY_HANDLING is not set, the INTERFACE_LINK_LIBRARIES property
|
||||
# of the imported target for <component> will be set to contain the imported
|
||||
# targets for the components listed in <name>_<component>_component_deps.
|
||||
# <component>_FOUND will also be set to false if any of the compoments in
|
||||
# <name>_<component>_component_deps are not found. This requires the components
|
||||
# in <name>_<component>_component_deps to be listed before <component> in the
|
||||
# COMPONENTS argument.
|
||||
#
|
||||
# The following variables will be set:
|
||||
#
|
||||
# ``<name>_TARGETS``
|
||||
# the imported targets
|
||||
# ``<name>_LIBRARIES``
|
||||
# the found libraries
|
||||
# ``<name>_INCLUDE_DIRS``
|
||||
# the combined required include directories for the components
|
||||
# ``<name>_DEFINITIONS``
|
||||
# the "other" CFLAGS provided by pkg-config, if any
|
||||
# ``<name>_VERSION``
|
||||
# the value of ``<name>_<component>_VERSION`` for the first component that
|
||||
# has this variable set (note that components are searched for in the order
|
||||
# they are passed to the macro), although if it is already set, it will not
|
||||
# be altered
|
||||
#
|
||||
# Note that these variables are never cleared, so if
|
||||
# ecm_find_package_handle_library_components() is called multiple times with
|
||||
# different components (typically because of multiple find_package() calls) then
|
||||
# ``<name>_TARGETS``, for example, will contain all the targets found in any
|
||||
# call (although no duplicates).
|
||||
#
|
||||
# Since pre-1.0.0.
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2014 Alex Merry <alex.merry@kde.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. The name of the author may not be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
macro(ecm_find_package_version_check module_name)
|
||||
if(CMAKE_VERSION VERSION_LESS 2.8.12)
|
||||
message(FATAL_ERROR "CMake 2.8.12 is required by Find${module_name}.cmake")
|
||||
endif()
|
||||
if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12)
|
||||
message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use Find${module_name}.cmake")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(ecm_find_package_parse_components module_name)
|
||||
set(ecm_fppc_options SKIP_DEPENDENCY_HANDLING)
|
||||
set(ecm_fppc_oneValueArgs RESULT_VAR)
|
||||
set(ecm_fppc_multiValueArgs KNOWN_COMPONENTS DEFAULT_COMPONENTS)
|
||||
cmake_parse_arguments(ECM_FPPC "${ecm_fppc_options}" "${ecm_fppc_oneValueArgs}" "${ecm_fppc_multiValueArgs}" ${ARGN})
|
||||
|
||||
if(ECM_FPPC_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "Unexpected arguments to ecm_find_package_parse_components: ${ECM_FPPC_UNPARSED_ARGUMENTS}")
|
||||
endif()
|
||||
if(NOT ECM_FPPC_RESULT_VAR)
|
||||
message(FATAL_ERROR "Missing RESULT_VAR argument to ecm_find_package_parse_components")
|
||||
endif()
|
||||
if(NOT ECM_FPPC_KNOWN_COMPONENTS)
|
||||
message(FATAL_ERROR "Missing KNOWN_COMPONENTS argument to ecm_find_package_parse_components")
|
||||
endif()
|
||||
if(NOT ECM_FPPC_DEFAULT_COMPONENTS)
|
||||
set(ECM_FPPC_DEFAULT_COMPONENTS ${ECM_FPPC_KNOWN_COMPONENTS})
|
||||
endif()
|
||||
|
||||
if(${module_name}_FIND_COMPONENTS)
|
||||
set(ecm_fppc_requestedComps ${${module_name}_FIND_COMPONENTS})
|
||||
|
||||
if(NOT ECM_FPPC_SKIP_DEPENDENCY_HANDLING)
|
||||
# Make sure deps are included
|
||||
foreach(ecm_fppc_comp ${ecm_fppc_requestedComps})
|
||||
foreach(ecm_fppc_dep_comp ${${module_name}_${ecm_fppc_comp}_component_deps})
|
||||
list(FIND ecm_fppc_requestedComps "${ecm_fppc_dep_comp}" ecm_fppc_index)
|
||||
if("${ecm_fppc_index}" STREQUAL "-1")
|
||||
if(NOT ${module_name}_FIND_QUIETLY)
|
||||
message(STATUS "${module_name}: ${ecm_fppc_comp} requires ${${module_name}_${ecm_fppc_comp}_component_deps}")
|
||||
endif()
|
||||
list(APPEND ecm_fppc_requestedComps "${ecm_fppc_dep_comp}")
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
else()
|
||||
message(STATUS "Skipping dependency handling for ${module_name}")
|
||||
endif()
|
||||
list(REMOVE_DUPLICATES ecm_fppc_requestedComps)
|
||||
|
||||
# This makes sure components are listed in the same order as
|
||||
# KNOWN_COMPONENTS (potentially important for inter-dependencies)
|
||||
set(${ECM_FPPC_RESULT_VAR})
|
||||
foreach(ecm_fppc_comp ${ECM_FPPC_KNOWN_COMPONENTS})
|
||||
list(FIND ecm_fppc_requestedComps "${ecm_fppc_comp}" ecm_fppc_index)
|
||||
if(NOT "${ecm_fppc_index}" STREQUAL "-1")
|
||||
list(APPEND ${ECM_FPPC_RESULT_VAR} "${ecm_fppc_comp}")
|
||||
list(REMOVE_AT ecm_fppc_requestedComps ${ecm_fppc_index})
|
||||
endif()
|
||||
endforeach()
|
||||
# if there are any left, they are unknown components
|
||||
if(ecm_fppc_requestedComps)
|
||||
set(ecm_fppc_msgType STATUS)
|
||||
if(${module_name}_FIND_REQUIRED)
|
||||
set(ecm_fppc_msgType FATAL_ERROR)
|
||||
endif()
|
||||
if(NOT ${module_name}_FIND_QUIETLY)
|
||||
message(${ecm_fppc_msgType} "${module_name}: requested unknown components ${ecm_fppc_requestedComps}")
|
||||
endif()
|
||||
return()
|
||||
endif()
|
||||
else()
|
||||
set(${ECM_FPPC_RESULT_VAR} ${ECM_FPPC_DEFAULT_COMPONENTS})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(ecm_find_package_handle_library_components module_name)
|
||||
set(ecm_fpwc_options SKIP_PKG_CONFIG SKIP_DEPENDENCY_HANDLING)
|
||||
set(ecm_fpwc_oneValueArgs)
|
||||
set(ecm_fpwc_multiValueArgs COMPONENTS)
|
||||
cmake_parse_arguments(ECM_FPWC "${ecm_fpwc_options}" "${ecm_fpwc_oneValueArgs}" "${ecm_fpwc_multiValueArgs}" ${ARGN})
|
||||
|
||||
if(ECM_FPWC_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "Unexpected arguments to ecm_find_package_handle_components: ${ECM_FPWC_UNPARSED_ARGUMENTS}")
|
||||
endif()
|
||||
if(NOT ECM_FPWC_COMPONENTS)
|
||||
message(FATAL_ERROR "Missing COMPONENTS argument to ecm_find_package_handle_components")
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package(PkgConfig)
|
||||
foreach(ecm_fpwc_comp ${ECM_FPWC_COMPONENTS})
|
||||
set(ecm_fpwc_dep_vars)
|
||||
set(ecm_fpwc_dep_targets)
|
||||
if(NOT SKIP_DEPENDENCY_HANDLING)
|
||||
foreach(ecm_fpwc_dep ${${module_name}_${ecm_fpwc_comp}_component_deps})
|
||||
list(APPEND ecm_fpwc_dep_vars "${module_name}_${ecm_fpwc_dep}_FOUND")
|
||||
list(APPEND ecm_fpwc_dep_targets "${module_name}::${ecm_fpwc_dep}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(NOT ECM_FPWC_SKIP_PKG_CONFIG AND ${module_name}_${ecm_fpwc_comp}_pkg_config)
|
||||
pkg_check_modules(PKG_${module_name}_${ecm_fpwc_comp} QUIET
|
||||
${${module_name}_${ecm_fpwc_comp}_pkg_config})
|
||||
endif()
|
||||
|
||||
find_path(${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR
|
||||
NAMES ${${module_name}_${ecm_fpwc_comp}_header}
|
||||
HINTS ${PKG_${module_name}_${ecm_fpwc_comp}_INCLUDE_DIRS}
|
||||
PATH_SUFFIXES ${${module_name}_${ecm_fpwc_comp}_header_subdir}
|
||||
)
|
||||
find_library(${module_name}_${ecm_fpwc_comp}_LIBRARY
|
||||
NAMES ${${module_name}_${ecm_fpwc_comp}_lib}
|
||||
HINTS ${PKG_${module_name}_${ecm_fpwc_comp}_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
set(${module_name}_${ecm_fpwc_comp}_VERSION "${PKG_${module_name}_${ecm_fpwc_comp}_VERSION}")
|
||||
if(NOT ${module_name}_VERSION)
|
||||
set(${module_name}_VERSION ${${module_name}_${ecm_fpwc_comp}_VERSION})
|
||||
endif()
|
||||
|
||||
find_package_handle_standard_args(${module_name}_${ecm_fpwc_comp}
|
||||
FOUND_VAR
|
||||
${module_name}_${ecm_fpwc_comp}_FOUND
|
||||
REQUIRED_VARS
|
||||
${module_name}_${ecm_fpwc_comp}_LIBRARY
|
||||
${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR
|
||||
${ecm_fpwc_dep_vars}
|
||||
VERSION_VAR
|
||||
${module_name}_${ecm_fpwc_comp}_VERSION
|
||||
)
|
||||
|
||||
mark_as_advanced(
|
||||
${module_name}_${ecm_fpwc_comp}_LIBRARY
|
||||
${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR
|
||||
)
|
||||
|
||||
if(${module_name}_${ecm_fpwc_comp}_FOUND)
|
||||
list(APPEND ${module_name}_LIBRARIES
|
||||
"${${module_name}_${ecm_fpwc_comp}_LIBRARY}")
|
||||
list(APPEND ${module_name}_INCLUDE_DIRS
|
||||
"${${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR}")
|
||||
set(${module_name}_DEFINITIONS
|
||||
${${module_name}_DEFINITIONS}
|
||||
${PKG_${module_name}_${ecm_fpwc_comp}_DEFINITIONS})
|
||||
if(NOT TARGET ${module_name}::${ecm_fpwc_comp})
|
||||
add_library(${module_name}::${ecm_fpwc_comp} UNKNOWN IMPORTED)
|
||||
set_target_properties(${module_name}::${ecm_fpwc_comp} PROPERTIES
|
||||
IMPORTED_LOCATION "${${module_name}_${ecm_fpwc_comp}_LIBRARY}"
|
||||
INTERFACE_COMPILE_OPTIONS "${PKG_${module_name}_${ecm_fpwc_comp}_DEFINITIONS}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES "${ecm_fpwc_dep_targets}"
|
||||
)
|
||||
endif()
|
||||
list(APPEND ${module_name}_TARGETS
|
||||
"${module_name}::${ecm_fpwc_comp}")
|
||||
endif()
|
||||
endforeach()
|
||||
if(${module_name}_LIBRARIES)
|
||||
list(REMOVE_DUPLICATES ${module_name}_LIBRARIES)
|
||||
endif()
|
||||
if(${module_name}_INCLUDE_DIRS)
|
||||
list(REMOVE_DUPLICATES ${module_name}_INCLUDE_DIRS)
|
||||
endif()
|
||||
if(${module_name}_DEFINITIONS)
|
||||
list(REMOVE_DUPLICATES ${module_name}_DEFINITIONS)
|
||||
endif()
|
||||
if(${module_name}_TARGETS)
|
||||
list(REMOVE_DUPLICATES ${module_name}_TARGETS)
|
||||
endif()
|
||||
endmacro()
|
||||
@@ -1 +0,0 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../modules/ECMFindModuleHelpers.cmake)
|
||||
@@ -1,27 +0,0 @@
|
||||
# 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"
|
||||
)
|
||||
@@ -1,117 +0,0 @@
|
||||
#.rst:
|
||||
# FindPng2Ico
|
||||
# -----------
|
||||
#
|
||||
# Try to find png2ico.
|
||||
#
|
||||
# If the png2ico executable is not in your PATH, you can provide
|
||||
# an alternative name or full path location with the ``Png2Ico_EXECUTABLE``
|
||||
# variable.
|
||||
#
|
||||
# This will define the following variables:
|
||||
#
|
||||
# ``Png2Ico_FOUND``
|
||||
# True if png2ico is available.
|
||||
#
|
||||
# ``Png2Ico_EXECUTABLE``
|
||||
# The png2ico executable.
|
||||
#
|
||||
# If ``Png2Ico_FOUND`` is TRUE, it will also define the following imported
|
||||
# target:
|
||||
#
|
||||
# ``Png2Ico::Png2Ico``
|
||||
# The png2ico executable.
|
||||
#
|
||||
# and the following variables:
|
||||
#
|
||||
# ``Png2Ico_HAS_COLORS_ARGUMENT``
|
||||
# Whether png2ico accepts a ``--colors`` argument. `Matthias Benkmann's
|
||||
# tool <http://www.winterdrache.de/freeware/png2ico/>`_ does, while the
|
||||
# version of png2ico from the `"KDE On Windows" (kdewin)
|
||||
# <https://projects.kde.org/projects/kdesupport/kdewin>`_ project does not.
|
||||
#
|
||||
# ``Png2Ico_HAS_RCFILE_ARGUMENT``
|
||||
# Whether png2ico accepts an ``--rcfile`` argument. The version of png2ico
|
||||
# from the `"KDE On Windows" (kdewin)
|
||||
# <https://projects.kde.org/projects/kdesupport/kdewin>`_ project does,
|
||||
# while `Matthias Benkmann's tool
|
||||
# <http://www.winterdrache.de/freeware/png2ico/>`_ does not.
|
||||
#
|
||||
# Since 1.7.0.
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2014 Alex Merry <alex.merry@kde.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. The name of the author may not be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#=============================================================================
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake)
|
||||
|
||||
ecm_find_package_version_check(Png2Ico)
|
||||
|
||||
# Find png2ico
|
||||
find_program(Png2Ico_EXECUTABLE NAMES png2ico)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Png2Ico
|
||||
FOUND_VAR
|
||||
Png2Ico_FOUND
|
||||
REQUIRED_VARS
|
||||
Png2Ico_EXECUTABLE
|
||||
)
|
||||
|
||||
mark_as_advanced(Png2Ico_EXECUTABLE)
|
||||
|
||||
if (Png2Ico_FOUND)
|
||||
execute_process(
|
||||
COMMAND "${Png2Ico_EXECUTABLE}" --help
|
||||
OUTPUT_VARIABLE _png2ico_help_text
|
||||
ERROR_VARIABLE _png2ico_help_text
|
||||
)
|
||||
if (_png2ico_help_text MATCHES ".*--rcfile .*")
|
||||
set(Png2Ico_HAS_RCFILE_ARGUMENT TRUE)
|
||||
else()
|
||||
set(Png2Ico_HAS_RCFILE_ARGUMENT FALSE)
|
||||
endif()
|
||||
if (_png2ico_help_text MATCHES ".*--colors .*")
|
||||
set(Png2Ico_HAS_COLORS_ARGUMENT TRUE)
|
||||
else()
|
||||
set(Png2Ico_HAS_COLORS_ARGUMENT FALSE)
|
||||
endif()
|
||||
unset(_png2ico_help_text)
|
||||
|
||||
if (NOT TARGET Png2Ico::Png2Ico)
|
||||
add_executable(Png2Ico::Png2Ico IMPORTED)
|
||||
set_target_properties(Png2Ico::Png2Ico PROPERTIES
|
||||
IMPORTED_LOCATION "${Png2Ico_EXECUTABLE}"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(FeatureSummary)
|
||||
set_package_properties(Png2Ico PROPERTIES
|
||||
URL "http://www.winterdrache.de/freeware/png2ico/ or https://projects.kde.org/projects/kdesupport/kdewin"
|
||||
DESCRIPTION "Executable that converts a collection of PNG files into a Windows icon file"
|
||||
)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>@APPLICATION_EXECUTABLE@</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>@APPLICATION_EXECUTABLE@.icns</string>
|
||||
<string>ownCloud.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>@APPLICATION_REV_DOMAIN@</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
@@ -32,42 +32,5 @@
|
||||
<false/>
|
||||
<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>
|
||||
|
||||
30
cmake/modules/MacroAddPlugin.cmake
Normal file
30
cmake/modules/MacroAddPlugin.cmake
Normal file
@@ -0,0 +1,30 @@
|
||||
# - MACRO_ADD_PLUGIN(name [WITH_PREFIX] file1 .. fileN)
|
||||
#
|
||||
# Create a plugin from the given source files.
|
||||
# If WITH_PREFIX is given, the resulting plugin will have the
|
||||
# prefix "lib", otherwise it won't.
|
||||
#
|
||||
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
|
||||
# Copyright (c) 2006, Laurent Montel, <montel@kde.org>
|
||||
# Copyright (c) 2006, Andreas Schneider, <asn@cryptomilk.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
|
||||
macro (MACRO_ADD_PLUGIN _target_NAME _with_PREFIX)
|
||||
|
||||
if (${_with_PREFIX} STREQUAL "WITH_PREFIX")
|
||||
set(_first_SRC)
|
||||
else (${_with_PREFIX} STREQUAL "WITH_PREFIX")
|
||||
set(_first_SRC ${_with_PREFIX})
|
||||
endif (${_with_PREFIX} STREQUAL "WITH_PREFIX")
|
||||
|
||||
add_library(${_target_NAME} MODULE ${_first_SRC} ${ARGN})
|
||||
|
||||
if (_first_SRC)
|
||||
set_target_properties(${_target_NAME} PROPERTIES PREFIX "")
|
||||
endif (_first_SRC)
|
||||
|
||||
endmacro (MACRO_ADD_PLUGIN _name _sources)
|
||||
|
||||
37
cmake/modules/MacroCopyFile.cmake
Normal file
37
cmake/modules/MacroCopyFile.cmake
Normal file
@@ -0,0 +1,37 @@
|
||||
# (c) 2014 Copyright ownCloud GmbH
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# - macro_copy_file(_src _dst)
|
||||
# Copies a file to ${_dst} only if ${_src} is different (newer) than ${_dst}
|
||||
#
|
||||
# Example:
|
||||
# macro_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/icon.png ${CMAKE_CURRENT_BINARY_DIR}/.)
|
||||
# Copies file icon.png to ${CMAKE_CURRENT_BINARY_DIR} directory
|
||||
#
|
||||
# Copyright (c) 2006-2007 Wengo
|
||||
# Copyright (c) 2006-2008 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING file.
|
||||
|
||||
|
||||
macro (macro_copy_file _src _dst)
|
||||
# Removes all path containing .svn or CVS or CMakeLists.txt during the copy
|
||||
if (NOT ${_src} MATCHES ".*\\.svn|CVS|CMakeLists\\.txt.*")
|
||||
|
||||
if (CMAKE_VERBOSE_MAKEFILE)
|
||||
message(STATUS "Copy file from ${_src} to ${_dst}")
|
||||
endif (CMAKE_VERBOSE_MAKEFILE)
|
||||
|
||||
# Creates directory if necessary
|
||||
get_filename_component(_path ${_dst} PATH)
|
||||
file(MAKE_DIRECTORY ${_path})
|
||||
|
||||
execute_process(
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy_if_different ${_src} ${_dst}
|
||||
OUTPUT_QUIET
|
||||
)
|
||||
endif (NOT ${_src} MATCHES ".*\\.svn|CVS|CMakeLists\\.txt.*")
|
||||
endmacro (macro_copy_file)
|
||||
@@ -7,8 +7,6 @@
|
||||
!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@"
|
||||
@@ -102,8 +100,6 @@ 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.
|
||||
;-----------------------------------------------------------------------------
|
||||
@@ -407,8 +403,6 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qgif.dll"
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qjpeg.dll"
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qico.dll"
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qsvg.dll"
|
||||
; PNG is built in Qt
|
||||
|
||||
SetOutPath "$INSTDIR\sqldrivers"
|
||||
File "${SQLITE_DLL_PATH}\qsqlite.dll"
|
||||
@@ -426,7 +420,6 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
|
||||
File "${QT_DLL_PATH}\Qt5Gui.dll"
|
||||
File "${QT_DLL_PATH}\Qt5Network.dll"
|
||||
File "${QT_DLL_PATH}\Qt5PrintSupport.dll"
|
||||
File "${QT_DLL_PATH}\Qt5Svg.dll"
|
||||
File "${QT_DLL_PATH}\Qt5Qml.dll"
|
||||
File "${QT_DLL_PATH}\Qt5Sql.dll"
|
||||
File "${QT_DLL_PATH}\Qt5WebKit.dll"
|
||||
@@ -468,14 +461,10 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
|
||||
File "${MING_BIN}\libgcc_s_sjlj-1.dll"
|
||||
File "${MING_BIN}\libstdc++-6.dll"
|
||||
File "${MING_BIN}\libwinpthread-1.dll"
|
||||
File "${MING_BIN}\libssp-0.dll"
|
||||
|
||||
;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
|
||||
@@ -614,35 +603,6 @@ Section Uninstall
|
||||
Abort $UNINSTALL_ABORT
|
||||
owncloud_installed:
|
||||
|
||||
; Delete Navigation Pane entries added for Windows 10.
|
||||
; On 64bit Windows, the client will be writing to the 64bit registry.
|
||||
${If} ${RunningX64}
|
||||
SetRegView 64
|
||||
${EndIf}
|
||||
StrCpy $0 0
|
||||
loop:
|
||||
; Look at every registered explorer namespace for HKCU and check if it was added by our application
|
||||
; (we write to a custom "ApplicationName" value there).
|
||||
EnumRegKey $1 HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace" $0
|
||||
StrCmp $1 "" done
|
||||
|
||||
ReadRegStr $R0 HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\$1" "ApplicationName"
|
||||
StrCmp $R0 "${APPLICATION_NAME}" deleteClsid
|
||||
; Increment the index when not deleting the enumerated key.
|
||||
IntOp $0 $0 + 1
|
||||
goto loop
|
||||
|
||||
deleteClsid:
|
||||
DetailPrint "Removing Navigation Pane CLSID $1"
|
||||
; Should match FolderMan::updateCloudStorageRegistry
|
||||
DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\$1"
|
||||
DeleteRegKey HKCU "Software\Classes\CLSID\$1"
|
||||
DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel" $1
|
||||
goto loop
|
||||
done:
|
||||
; Go back to the 32bit registry.
|
||||
SetRegView lastused
|
||||
|
||||
;Delete registry keys.
|
||||
DeleteRegValue HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "VersionBuild"
|
||||
DeleteRegValue HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "VersionMajor"
|
||||
@@ -653,9 +613,6 @@ 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
|
||||
|
||||
104
cmake/modules/QtVersionAbstraction.cmake
Normal file
104
cmake/modules/QtVersionAbstraction.cmake
Normal file
@@ -0,0 +1,104 @@
|
||||
# (c) 2014 Copyright ownCloud GmbH
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
include (MacroOptionalFindPackage)
|
||||
include (MacroLogFeature)
|
||||
|
||||
find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Network REQUIRED)
|
||||
find_package(Qt5Xml REQUIRED)
|
||||
find_package(Qt5Concurrent REQUIRED)
|
||||
if(UNIT_TESTING)
|
||||
find_package(Qt5Test REQUIRED)
|
||||
endif()
|
||||
|
||||
if(NOT TOKEN_AUTH_ONLY)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
if(APPLE)
|
||||
find_package(Qt5MacExtras REQUIRED)
|
||||
endif(APPLE)
|
||||
|
||||
if(NOT NO_SHIBBOLETH)
|
||||
find_package(Qt5WebKitWidgets)
|
||||
find_package(Qt5WebKit)
|
||||
if(NOT Qt5WebKitWidgets_FOUND)
|
||||
message(FATAL_ERROR "Qt5WebKit required for Shibboleth. Use -DNO_SHIBBOLETH=1 to disable it.")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# We need this to find the paths to qdbusxml2cpp and co
|
||||
if (WITH_DBUS)
|
||||
find_package(Qt5DBus REQUIRED)
|
||||
include_directories(${Qt5DBus_INCLUDES})
|
||||
add_definitions(${Qt5DBus_DEFINITIONS})
|
||||
endif (WITH_DBUS)
|
||||
include_directories(${Qt5Core_INCLUDES})
|
||||
add_definitions(${Qt5Core_DEFINITIONS})
|
||||
if (NOT WIN32) #implied on Win32
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
endif(NOT WIN32)
|
||||
# set(CMAKE_CXX_FLAGS "${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
|
||||
|
||||
if(APPLE AND NOT TOKEN_AUTH_ONLY)
|
||||
include_directories(${Qt5MacExtras_INCLUDE_DIRS})
|
||||
add_definitions(${Qt5MacExtras_DEFINITIONS})
|
||||
set (QT_LIBRARIES ${QT_LIBRARIES} ${Qt5MacExtras_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(NOT BUILD_LIBRARIES_ONLY)
|
||||
macro(qt_wrap_ui)
|
||||
qt5_wrap_ui(${ARGN})
|
||||
endmacro()
|
||||
else()
|
||||
# hack
|
||||
SET(QT_UIC_EXECUTABLE "")
|
||||
endif()
|
||||
|
||||
macro(qt_add_resources)
|
||||
qt5_add_resources(${ARGN})
|
||||
endmacro()
|
||||
|
||||
if(NOT TOKEN_AUTH_ONLY)
|
||||
find_package(Qt5LinguistTools)
|
||||
if(Qt5LinguistTools_FOUND)
|
||||
macro(qt_add_translation)
|
||||
qt5_add_translation(${ARGN})
|
||||
endmacro()
|
||||
else()
|
||||
macro(qt_add_translation)
|
||||
endmacro()
|
||||
endif()
|
||||
else()
|
||||
macro(qt_add_translation)
|
||||
endmacro()
|
||||
endif()
|
||||
|
||||
macro(qt_add_dbus_interface)
|
||||
qt5_add_dbus_interface(${ARGN})
|
||||
endmacro()
|
||||
|
||||
macro(qt_add_dbus_adaptor)
|
||||
qt5_add_dbus_adaptor(${ARGN})
|
||||
endmacro()
|
||||
|
||||
macro(qt_wrap_cpp)
|
||||
qt5_wrap_cpp(${ARGN})
|
||||
endmacro()
|
||||
|
||||
macro(install_qt_executable)
|
||||
install_qt5_executable(${ARGN})
|
||||
endmacro()
|
||||
|
||||
macro(setup_qt)
|
||||
endmacro()
|
||||
|
||||
set(QT_RCC_EXECUTABLE "${Qt5Core_RCC_EXECUTABLE}")
|
||||
|
||||
#Enable deprecated symbols
|
||||
add_definitions("-DQT_DISABLE_DEPRECATED_BEFORE=0")
|
||||
|
||||
add_definitions("-DQT_USE_QSTRINGBUILDER") #optimize string concatenation
|
||||
add_definitions("-DQT_MESSAGELOGCONTEXT") #enable function name and line number in debug output
|
||||
|
||||
58
cmake/modules/UseAsciidoc.cmake
Normal file
58
cmake/modules/UseAsciidoc.cmake
Normal file
@@ -0,0 +1,58 @@
|
||||
# - macro_asciidoc2man(inputfile outputfile)
|
||||
#
|
||||
# Create a manpage with asciidoc.
|
||||
# Example: macro_asciidoc2man(foo.txt foo.1)
|
||||
#
|
||||
# Copyright (c) 2006, Andreas Schneider, <asn@cryptomilk.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
include(MacroCopyFile)
|
||||
|
||||
macro(MACRO_ASCIIDOC2MAN _a2m_input _a2m_output)
|
||||
find_program(A2X
|
||||
NAMES
|
||||
a2x
|
||||
)
|
||||
#message("+++ A2X: ${A2X}")
|
||||
|
||||
if (A2X)
|
||||
|
||||
#message("+++ ${A2X} --doctype=manpage --format=manpage --destination-dir=${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${_a2m_input}")
|
||||
macro_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/${_a2m_input} ${CMAKE_CURRENT_BINARY_DIR}/${_a2m_input})
|
||||
|
||||
execute_process(
|
||||
COMMAND
|
||||
${A2X} --doctype=manpage --format=manpage ${_a2m_input}
|
||||
WORKING_DIRECTORY
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
RESULT_VARIABLE
|
||||
A2M_MAN_GENERATED
|
||||
ERROR_QUIET
|
||||
)
|
||||
|
||||
#message("+++ A2M_MAN_GENERATED: ${A2M_MAN_GENERATED}")
|
||||
if (A2M_MAN_GENERATED EQUAL 0)
|
||||
find_file(A2M_MAN_FILE
|
||||
NAME
|
||||
${_a2m_output}
|
||||
PATHS
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
if (A2M_MAN_FILE)
|
||||
get_filename_component(A2M_MAN_CATEGORY ${A2M_MAN_FILE} EXT)
|
||||
string(SUBSTRING ${A2M_MAN_CATEGORY} 1 1 A2M_MAN_CATEGORY)
|
||||
install(
|
||||
FILES
|
||||
${A2M_MAN_FILE}
|
||||
DESTINATION
|
||||
${MAN_INSTALL_DIR}/man${A2M_MAN_CATEGORY}
|
||||
)
|
||||
endif (A2M_MAN_FILE)
|
||||
endif (A2M_MAN_GENERATED EQUAL 0)
|
||||
|
||||
endif (A2X)
|
||||
endmacro(MACRO_ASCIIDOC2MAN _a2m_input _a2m_file)
|
||||
@@ -4,14 +4,9 @@
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long -Wno-gnu-zero-variadic-macro-arguments")
|
||||
|
||||
# Fix sqlite compilation on macOS
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-incompatible-pointer-types-discards-qualifiers")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
|
||||
460
csync/tests/csync_tests/check_csync_update.cpp
Normal file
460
csync/tests/csync_tests/check_csync_update.cpp
Normal file
@@ -0,0 +1,460 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "csync_update.cpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
#define TESTDB "/tmp/check_csync/journal.db"
|
||||
|
||||
static int firstrun = 1;
|
||||
|
||||
static void statedb_create_metadata_table(sqlite3 *db)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if( db ) {
|
||||
const char *sql = "CREATE TABLE IF NOT EXISTS metadata("
|
||||
"phash INTEGER(8),"
|
||||
"pathlen INTEGER,"
|
||||
"path VARCHAR(4096),"
|
||||
"inode INTEGER,"
|
||||
"uid INTEGER,"
|
||||
"gid INTEGER,"
|
||||
"mode INTEGER,"
|
||||
"modtime INTEGER(8),"
|
||||
"type INTEGER,"
|
||||
"md5 VARCHAR(32),"
|
||||
"fileid VARCHAR(128),"
|
||||
"remotePerm VARCHAR(128),"
|
||||
"filesize BIGINT,"
|
||||
"ignoredChildrenRemote INT,"
|
||||
"contentChecksum TEXT,"
|
||||
"contentChecksumTypeId INTEGER,"
|
||||
"PRIMARY KEY(phash));";
|
||||
|
||||
rc = sqlite3_exec(db, sql, NULL, NULL, NULL);
|
||||
//const char *msg = sqlite3_errmsg(db);
|
||||
assert_int_equal( rc, SQLITE_OK );
|
||||
|
||||
sql = "CREATE TABLE IF NOT EXISTS checksumtype("
|
||||
"id INTEGER PRIMARY KEY,"
|
||||
"name TEXT UNIQUE"
|
||||
");";
|
||||
rc = sqlite3_exec(db, sql, NULL, NULL, NULL);
|
||||
assert_int_equal( rc, SQLITE_OK );
|
||||
}
|
||||
}
|
||||
|
||||
static void statedb_insert_metadata(sqlite3 *db)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if( db ) {
|
||||
char *stmt = sqlite3_mprintf("INSERT INTO metadata"
|
||||
"(phash, pathlen, path, inode, uid, gid, mode, modtime,type,md5) VALUES"
|
||||
"(%lld, %d, '%q', %d, %d, %d, %d, %lld, %d, '%q');",
|
||||
(long long signed int)42,
|
||||
42,
|
||||
"I_was_wurst_before_I_became_wurstsalat",
|
||||
619070,
|
||||
42,
|
||||
42,
|
||||
42,
|
||||
(long long signed int)42,
|
||||
0,
|
||||
"4711");
|
||||
|
||||
char *errmsg;
|
||||
rc = sqlite3_exec(db, stmt, NULL, NULL, &errmsg);
|
||||
sqlite3_free(stmt);
|
||||
assert_int_equal( rc, SQLITE_OK );
|
||||
}
|
||||
}
|
||||
|
||||
static int setup(void **state)
|
||||
{
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
unlink(TESTDB);
|
||||
rc = system("mkdir -p /tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
csync_init(csync, TESTDB);
|
||||
|
||||
/* Create a new db with metadata */
|
||||
sqlite3 *db;
|
||||
csync->statedb.file = c_strdup(TESTDB);
|
||||
rc = sqlite3_open(csync->statedb.file, &db);
|
||||
statedb_create_metadata_table(db);
|
||||
if( firstrun ) {
|
||||
statedb_insert_metadata(db);
|
||||
firstrun = 0;
|
||||
}
|
||||
sqlite3_close(db);
|
||||
|
||||
rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = csync;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_ftw(void **state)
|
||||
{
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp");
|
||||
csync_init(csync, TESTDB);
|
||||
|
||||
sqlite3 *db = NULL;
|
||||
rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
|
||||
assert_int_equal(rc, SQLITE_OK);
|
||||
statedb_create_metadata_table(db);
|
||||
rc = sqlite3_close(db);
|
||||
assert_int_equal(rc, SQLITE_OK);
|
||||
|
||||
rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync->statedb.file = c_strdup( TESTDB );
|
||||
*state = csync;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int teardown(void **state)
|
||||
{
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
int rc;
|
||||
|
||||
unlink( csync->statedb.file);
|
||||
rc = csync_destroy(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int teardown_rm(void **state) {
|
||||
int rc;
|
||||
|
||||
teardown(state);
|
||||
|
||||
rc = system("rm -rf /tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* create a file stat, caller must free memory */
|
||||
static csync_vio_file_stat_t* create_fstat(const char *name,
|
||||
ino_t inode,
|
||||
time_t mtime)
|
||||
{
|
||||
csync_vio_file_stat_t *fs = NULL;
|
||||
time_t t;
|
||||
|
||||
fs = csync_vio_file_stat_new();
|
||||
if (fs == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (name && *name) {
|
||||
fs->name = c_strdup(name);
|
||||
} else {
|
||||
fs->name = c_strdup("file.txt");
|
||||
}
|
||||
|
||||
if (fs->name == NULL) {
|
||||
csync_vio_file_stat_destroy(fs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fs->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
|
||||
|
||||
fs->type = CSYNC_VIO_FILE_TYPE_REGULAR;
|
||||
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
|
||||
|
||||
|
||||
if (inode == 0) {
|
||||
fs->inode = 619070;
|
||||
} else {
|
||||
fs->inode = inode;
|
||||
}
|
||||
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_INODE;
|
||||
|
||||
|
||||
fs->size = 157459;
|
||||
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
|
||||
|
||||
|
||||
|
||||
if (mtime == 0) {
|
||||
fs->atime = fs->ctime = fs->mtime = time(&t);
|
||||
} else {
|
||||
fs->atime = fs->ctime = fs->mtime = mtime;
|
||||
}
|
||||
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ATIME;
|
||||
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_CTIME;
|
||||
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;
|
||||
|
||||
return fs;
|
||||
}
|
||||
|
||||
static int failing_fn(CSYNC *ctx,
|
||||
const char *file,
|
||||
const csync_vio_file_stat_t *fs,
|
||||
int flag)
|
||||
{
|
||||
(void) ctx;
|
||||
(void) file;
|
||||
(void) fs;
|
||||
(void) flag;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* detect a new file */
|
||||
static void check_csync_detect_update(void **state)
|
||||
{
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
csync_file_stat_t *st;
|
||||
csync_vio_file_stat_t *fs;
|
||||
int rc;
|
||||
|
||||
fs = create_fstat("file.txt", 0, 1217597845);
|
||||
assert_non_null(fs);
|
||||
|
||||
rc = _csync_detect_update(csync,
|
||||
"/tmp/check_csync1/file.txt",
|
||||
fs,
|
||||
CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
/* the instruction should be set to new */
|
||||
st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root);
|
||||
assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW);
|
||||
|
||||
/* create a statedb */
|
||||
csync_set_status(csync, 0xFFFF);
|
||||
|
||||
csync_vio_file_stat_destroy(fs);
|
||||
}
|
||||
|
||||
/* Test behaviour in case no db is there. For that its important that the
|
||||
* test before this one uses teardown_rm.
|
||||
*/
|
||||
static void check_csync_detect_update_db_none(void **state)
|
||||
{
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
csync_file_stat_t *st;
|
||||
csync_vio_file_stat_t *fs;
|
||||
int rc;
|
||||
|
||||
fs = create_fstat("file.txt", 0, 1217597845);
|
||||
assert_non_null(fs);
|
||||
|
||||
rc = _csync_detect_update(csync,
|
||||
"/tmp/check_csync1/file.txt",
|
||||
fs,
|
||||
CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
/* the instruction should be set to new */
|
||||
st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root);
|
||||
assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW);
|
||||
|
||||
|
||||
/* create a statedb */
|
||||
csync_set_status(csync, 0xFFFF);
|
||||
|
||||
csync_vio_file_stat_destroy(fs);
|
||||
}
|
||||
|
||||
static void check_csync_detect_update_db_eval(void **state)
|
||||
{
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
csync_file_stat_t *st;
|
||||
csync_vio_file_stat_t *fs;
|
||||
int rc;
|
||||
|
||||
fs = create_fstat("file.txt", 0, 42);
|
||||
assert_non_null(fs);
|
||||
|
||||
rc = _csync_detect_update(csync,
|
||||
"/tmp/check_csync1/file.txt",
|
||||
fs,
|
||||
CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
/* the instruction should be set to new */
|
||||
st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root);
|
||||
assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW);
|
||||
|
||||
/* create a statedb */
|
||||
csync_set_status(csync, 0xFFFF);
|
||||
|
||||
csync_vio_file_stat_destroy(fs);
|
||||
}
|
||||
|
||||
|
||||
static void check_csync_detect_update_db_rename(void **state)
|
||||
{
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
// csync_file_stat_t *st;
|
||||
|
||||
csync_vio_file_stat_t *fs;
|
||||
int rc = 0;
|
||||
|
||||
fs = create_fstat("wurst.txt", 0, 42);
|
||||
assert_non_null(fs);
|
||||
csync_set_statedb_exists(csync, 1);
|
||||
|
||||
rc = _csync_detect_update(csync,
|
||||
"/tmp/check_csync1/wurst.txt",
|
||||
fs,
|
||||
CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
/* the instruction should be set to rename */
|
||||
/*
|
||||
* temporarily broken.
|
||||
st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root);
|
||||
assert_int_equal(st->instruction, CSYNC_INSTRUCTION_RENAME);
|
||||
|
||||
st->instruction = CSYNC_INSTRUCTION_UPDATED;
|
||||
*/
|
||||
/* create a statedb */
|
||||
csync_set_status(csync, 0xFFFF);
|
||||
|
||||
csync_vio_file_stat_destroy(fs);
|
||||
}
|
||||
|
||||
static void check_csync_detect_update_db_new(void **state)
|
||||
{
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
csync_file_stat_t *st;
|
||||
csync_vio_file_stat_t *fs;
|
||||
int rc;
|
||||
|
||||
fs = create_fstat("file.txt", 42000, 0);
|
||||
assert_non_null(fs);
|
||||
|
||||
rc = _csync_detect_update(csync,
|
||||
"/tmp/check_csync1/file.txt",
|
||||
fs,
|
||||
CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
/* the instruction should be set to new */
|
||||
st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root);
|
||||
assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW);
|
||||
|
||||
|
||||
/* create a statedb */
|
||||
csync_set_status(csync, 0xFFFF);
|
||||
|
||||
csync_vio_file_stat_destroy(fs);
|
||||
}
|
||||
|
||||
static void check_csync_detect_update_null(void **state)
|
||||
{
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
csync_vio_file_stat_t *fs;
|
||||
int rc;
|
||||
|
||||
fs = create_fstat("file.txt", 0, 0);
|
||||
assert_non_null(fs);
|
||||
|
||||
rc = _csync_detect_update(csync,
|
||||
NULL,
|
||||
fs,
|
||||
CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, -1);
|
||||
|
||||
rc = _csync_detect_update(csync,
|
||||
"/tmp/check_csync1/file.txt",
|
||||
NULL,
|
||||
CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, -1);
|
||||
|
||||
csync_vio_file_stat_destroy(fs);
|
||||
}
|
||||
|
||||
static void check_csync_ftw(void **state)
|
||||
{
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
int rc;
|
||||
|
||||
rc = csync_ftw(csync, "/tmp", csync_walker, MAX_DEPTH);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void check_csync_ftw_empty_uri(void **state)
|
||||
{
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
int rc;
|
||||
|
||||
rc = csync_ftw(csync, "", csync_walker, MAX_DEPTH);
|
||||
assert_int_equal(rc, -1);
|
||||
}
|
||||
|
||||
static void check_csync_ftw_failing_fn(void **state)
|
||||
{
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
int rc;
|
||||
|
||||
rc = csync_ftw(csync, "/tmp", failing_fn, MAX_DEPTH);
|
||||
assert_int_equal(rc, -1);
|
||||
}
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(check_csync_detect_update, setup, teardown_rm),
|
||||
cmocka_unit_test_setup_teardown(check_csync_detect_update_db_none, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_detect_update_db_eval, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_detect_update_db_rename, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_detect_update_db_new, setup, teardown_rm),
|
||||
cmocka_unit_test_setup_teardown(check_csync_detect_update_null, setup, teardown_rm),
|
||||
|
||||
cmocka_unit_test_setup_teardown(check_csync_ftw, setup_ftw, teardown_rm),
|
||||
cmocka_unit_test_setup_teardown(check_csync_ftw_empty_uri, setup_ftw, teardown_rm),
|
||||
cmocka_unit_test_setup_teardown(check_csync_ftw_failing_fn, setup_ftw, teardown_rm),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
2
doc/.gitignore
vendored
2
doc/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
conf.py
|
||||
Makefile
|
||||
@@ -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}/docs-themes")
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ocdoc/_shared_assets")
|
||||
add_dependencies(doc doc-html-org)
|
||||
add_dependencies(doc doc-html-com)
|
||||
endif()
|
||||
@@ -38,13 +38,7 @@ if(SPHINX_FOUND)
|
||||
-D latex_logo=${LATEX_LOGO}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${SPHINX_PDF_DIR} )
|
||||
|
||||
set(MAKE "make" CACHE FILEPATH "make to be used for documentation generation if not using make as generator anyway")
|
||||
if(CMAKE_GENERATOR MATCHES "Makefiles")
|
||||
set(MAKE "$(MAKE)")
|
||||
endif()
|
||||
|
||||
add_custom_target(doc-pdf ${MAKE} -C ${SPHINX_PDF_DIR} all-pdf
|
||||
add_custom_target(doc-pdf $(MAKE) -C ${SPHINX_PDF_DIR} all-pdf
|
||||
DEPENDS doc-latex )
|
||||
add_dependencies(doc doc-pdf)
|
||||
endif(PDFLATEX_FOUND)
|
||||
@@ -90,4 +84,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)
|
||||
174
doc/Makefile
Normal file
174
doc/Makefile
Normal file
@@ -0,0 +1,174 @@
|
||||
|
||||
# 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."
|
||||
@@ -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 (conflicted copy 2016-01-01 153110).txt"
|
||||
and the remote file will be downloaded and saved as message.txt.
|
||||
the local changes will be renamed to message_conflict-20160101-153110.txt and
|
||||
the remote file will be downloaded and saved as message.txt.
|
||||
|
||||
Conflict files are always created on the client and never on the server.
|
||||
|
||||
@@ -276,15 +276,9 @@ 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 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.
|
||||
* 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.
|
||||
|
||||
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
|
||||
|
||||
@@ -119,7 +119,7 @@ Preventing Automatic Updates in Linux Environments
|
||||
|
||||
Because the Linux client does not provide automatic updating functionality, there is no
|
||||
need to remove the automatic-update check. However, if you want to disable it edit your desktop
|
||||
client configuration file, ``$HOME/.config/ownCloud/owncloud.cfg``.
|
||||
client configuration file, ``$HOME/.local/share/data/ownCloud/owncloud.cfg``.
|
||||
Add this line to the [General] section::
|
||||
|
||||
skipUpdateCheck=true
|
||||
|
||||
@@ -13,14 +13,6 @@ 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
|
||||
-------------------
|
||||
|
||||
@@ -59,8 +51,8 @@ distribution. Make sure the repositories for source packages are enabled.
|
||||
|
||||
3. Follow the :ref:`generic-build-instructions`, starting with step 2.
|
||||
|
||||
macOS
|
||||
-----
|
||||
Mac OS X
|
||||
--------
|
||||
|
||||
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
|
||||
@@ -85,23 +77,29 @@ To set up your build environment for development using HomeBrew_:
|
||||
|
||||
brew tap owncloud/owncloud
|
||||
|
||||
5. Install a Qt5 version, ideally from from 5.10.1::
|
||||
5. Install a Qt5 version with qtwebkit support::
|
||||
|
||||
brew install qt5
|
||||
brew install qt5 --with-qtwebkit
|
||||
|
||||
6. Install any missing dependencies::
|
||||
|
||||
brew install $(brew deps owncloud-client)
|
||||
|
||||
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``
|
||||
7. Add Qt from brew to the path::
|
||||
|
||||
8. For compilation of the client, follow the :ref:`generic-build-instructions`.
|
||||
export PATH=/usr/local/Cellar/qt5/5.x.y/bin:$PATH
|
||||
|
||||
9. Install the Packages_ package creation tool.
|
||||
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``
|
||||
|
||||
10. In the build directory, run ``admin/osx/create_mac.sh <CMAKE_INSTALL_DIR> <build dir> <installer sign identity>``.
|
||||
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>``.
|
||||
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.
|
||||
@@ -154,7 +152,7 @@ follow `Windows Installer Build (Cross-Compile)`_ instead.
|
||||
|
||||
7. Build the client::
|
||||
|
||||
cmake -G "MinGW Makefiles" -DNO_SHIBBOLETH=1 ../client
|
||||
cmake -G "MinGW Makefiles" ../client
|
||||
mingw32-make
|
||||
|
||||
.. note:: You can try using ninja to build in parallel using
|
||||
@@ -222,14 +220,16 @@ 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,18 +240,19 @@ To build the most up-to-date version of the client:
|
||||
|
||||
3. Configure the client build::
|
||||
|
||||
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/``
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE="Debug" ..
|
||||
|
||||
.. 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 ``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.
|
||||
@@ -263,10 +264,11 @@ 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. If you install QtKeychain into the CMAKE_PREFIX_PATH then you don't need to specify the path manually.
|
||||
You need to compile QtKeychain with the same Qt version.
|
||||
* ``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.10.1/5.10.1/yourarch/lib/cmake/``: Builds using that Qt version.
|
||||
* ``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_INSTALL_PREFIX=path``: Set an install prefix. This is mandatory on Mac OS
|
||||
|
||||
.. _ownCloud repository from OBS: http://software.opensuse.org/download/package?
|
||||
@@ -283,4 +285,3 @@ 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/
|
||||
|
||||
292
doc/conf.py
Normal file
292
doc/conf.py
Normal file
@@ -0,0 +1,292 @@
|
||||
# -*- 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
|
||||
@@ -12,7 +12,6 @@
|
||||
# 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
|
||||
@@ -29,7 +28,7 @@ from datetime import datetime
|
||||
extensions = ['sphinx.ext.todo']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['@CMAKE_CURRENT_SOURCE_DIR@/docs-themes/templates']
|
||||
templates_path = ['@CMAKE_CURRENT_SOURCE_DIR@/ocdoc/_shared_assets/templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
@@ -42,7 +41,7 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'ownCloud Client Manual'
|
||||
copyright = u'2013-{:%Y}, The ownCloud developers'.format(datetime.now())
|
||||
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
|
||||
@@ -96,7 +95,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@/docs-themes/themes']
|
||||
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.
|
||||
@@ -121,7 +120,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@/docs-themes/static']
|
||||
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.
|
||||
@@ -251,7 +250,7 @@ texinfo_documents = [
|
||||
epub_title = u'ownCloud Client Manual'
|
||||
epub_author = u'The ownCloud developers'
|
||||
epub_publisher = u'The ownCloud developers'
|
||||
epub_copyright = u'2013-{:%Y}, The ownCloud developers'.format(datetime.now())
|
||||
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.
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
The ownCloud Client reads a configuration file. You can locate this configuration file as follows:
|
||||
|
||||
On Linux distributions:
|
||||
``$HOME/.config/ownCloud/owncloud.cfg``
|
||||
``$HOME/.local/share/data/ownCloud/owncloud.cfg``
|
||||
|
||||
On Microsoft Windows systems:
|
||||
``%APPDATA%\ownCloud\owncloud.cfg``
|
||||
``%LOCALAPPDATA%\ownCloud\owncloud.cfg``
|
||||
|
||||
On MAC OS X systems:
|
||||
``$HOME/Library/Preferences/ownCloud/owncloud.cfg``
|
||||
``$HOME/Library/Application Support/ownCloud/owncloud.cfg``
|
||||
|
||||
|
||||
The configuration file contains settings using the Microsoft Windows .ini file
|
||||
@@ -27,8 +27,6 @@ Some interesting values that can be set on the configuration file are:
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
| ``forceSyncInterval`` | ``7200000`` | The duration of no activity after which a synchronization run shall be triggered automatically. |
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
| ``fullLocalDiscoveryInterval`` | ``3600000`` | The interval after which the next synchronization will perform a full local discovery. |
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
| ``notificationRefreshInterval`` | ``300000`` | Specifies the default interval of checking for new server notifications in milliseconds. |
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
|
||||
@@ -46,13 +44,6 @@ 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. |
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
|
||||
|
||||
+----------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
=========
|
||||
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``.
|
||||
Submodule doc/docs-themes deleted from 90bd26b118
19
doc/faq.rst
19
doc/faq.rst
@@ -21,25 +21,6 @@ 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
|
||||
-----------------------------------
|
||||
|
||||
|
||||
BIN
doc/images/client-4.png
Normal file
BIN
doc/images/client-4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 43 KiB |
BIN
doc/images/save_log_file.png
Normal file
BIN
doc/images/save_log_file.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
@@ -9,7 +9,6 @@ ownCloud Desktop Client Manual
|
||||
introduction
|
||||
installing
|
||||
navigating
|
||||
conflicts
|
||||
advancedusage
|
||||
autoupdate
|
||||
building
|
||||
@@ -17,4 +16,4 @@ ownCloud Desktop Client Manual
|
||||
troubleshooting
|
||||
faq
|
||||
glossary
|
||||
|
||||
|
||||
@@ -24,20 +24,6 @@ KWallet, so that the sync client can login automatically.
|
||||
You will also find links to source code archives and older versions on the
|
||||
download page.
|
||||
|
||||
System Requirements
|
||||
----------------------------------
|
||||
|
||||
- Windows 7+
|
||||
- Mac OS X 10.7+ (**64-bit only**)
|
||||
- CentOS 6 & 7 (64-bit only)
|
||||
- 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 Ubuntu `LTS`_.
|
||||
|
||||
Installation Wizard
|
||||
-------------------
|
||||
|
||||
@@ -67,7 +53,12 @@ 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
|
||||
@@ -23,3 +23,11 @@ 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
|
||||
|
||||
|
||||
@@ -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), menu bar (macOS), or notification area
|
||||
in the system tray (Windows, KDE), status bar (Mac OS X), or notification area
|
||||
(Linux).
|
||||
|
||||
.. figure:: images/icon.png
|
||||
|
||||
@@ -107,25 +107,14 @@ 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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
To obtain the client log file:
|
||||
|
||||
1. Open the ownCloud Desktop Client.
|
||||
|
||||
@@ -135,22 +124,37 @@ Logging to a Temporary Directory
|
||||
|
||||
.. image:: images/log_output_window.png
|
||||
|
||||
3. Enable the 'Permanently save logs' checkbox.
|
||||
3. Click the 'Save' button.
|
||||
|
||||
4. Look at its tooltip and take note of the directory the logs will be saved to.
|
||||
The Save Log File window opens.
|
||||
|
||||
5. Navigate to this directory.
|
||||
.. image:: images/save_log_file.png
|
||||
|
||||
6. Select the logs for the timeframe in which the issue occurred.
|
||||
4. Migrate to a location on your system where you want to save your log file.
|
||||
|
||||
Note that the choice to enable logging will be persist across client restarts.
|
||||
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``
|
||||
|
||||
Saving Files Directly
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
To save log files to a file or a directory:
|
||||
|
||||
@@ -166,8 +170,6 @@ 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:
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ if(SPHINX_FOUND)
|
||||
set(SPHINX_MAN_DIR "${CMAKE_CURRENT_BINARY_DIR}/man1")
|
||||
install(DIRECTORY ${SPHINX_MAN_DIR} DESTINATION ${CMAKE_INSTALL_MANDIR} OPTIONAL)
|
||||
add_custom_target( doc-man ${SPHINX_EXECUTABLE}
|
||||
-c ${CMAKE_BINARY_DIR}/doc -b man
|
||||
-c ${CMAKE_SOURCE_DIR}/doc -b man
|
||||
-d ${SPHINX_CACHE_DIR}/man
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${SPHINX_MAN_DIR} )
|
||||
|
||||
@@ -8,7 +8,359 @@ GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
MimeType=application/x-@APPLICATION_EXECUTABLE@;
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
Comment[oc]=@APPLICATION_NAME@ sincronizacion del client
|
||||
@@ -62,7 +414,7 @@ Icon[eu]=@APPLICATION_EXECUTABLE@
|
||||
GenericName[fa]=همسان سازی پوشهها
|
||||
Name[fa]=@APPLICATION_EXECUTABLE@ نسخهی همسان سازی مشتری
|
||||
Icon[fa]=@APPLICATION_EXECUTABLE@
|
||||
Comment[fr]=Client de synchronisation @APPLICATION_NAME@
|
||||
Comment[fr]=Synchronisez vos dossiers avec un serveur @APPLICATION_NAME@
|
||||
GenericName[fr]=Synchronisation de dossier
|
||||
Name[fr]=Client de synchronisation @APPLICATION_NAME@
|
||||
Icon[fr]=@APPLICATION_EXECUTABLE@
|
||||
@@ -98,13 +450,9 @@ Comment[lo]=@APPLICATION_NAME@ ການປະສານຂໍ້ມູນຄອ
|
||||
GenericName[lo]=ໂຟນເດີຊິງ
|
||||
Name[lo]=@APPLICATION_NAME@ ຊິງຄອມພິວເຕີລູກຂ່າຍ
|
||||
Icon[lo]=@APPLICATION_EXECUTABLE@
|
||||
Comment[mk]=@APPLICATION_NAME@ десктор клиент за синхронизација
|
||||
GenericName[mk]=Папка за синхронизација
|
||||
Name[mk]=@APPLICATION_NAME@ десктор клиент за синхронизација
|
||||
Icon[mk]=@APPLICATION_EXECUTABLE@
|
||||
Comment[hu_HU]=@APPLICATION_NAME@ asztali szinkronizációs kliens
|
||||
GenericName[hu_HU]=Mappaszinkronizálás
|
||||
Name[hu_HU]=@APPLICATION_NAME@ asztali szinkronizációs kliens
|
||||
GenericName[hu_HU]=Könyvtár szinkronizálás
|
||||
Name[hu_HU]=@APPLICATION_NAME@ asztali szinkr. kliens
|
||||
Icon[hu_HU]=@APPLICATION_EXECUTABLE@
|
||||
Comment[af_ZA]=@APPLICATION_NAME@ werkskermsinchroniseerkliënt
|
||||
GenericName[af_ZA]=Vouersinchronisering
|
||||
@@ -179,9 +527,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
|
||||
|
||||
BIN
resources/more.png
Normal file
BIN
resources/more.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 122 B |
@@ -1,5 +0,0 @@
|
||||
<?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>
|
||||
|
Before Width: | Height: | Size: 660 B |
@@ -21,7 +21,3 @@ if( UNIX AND NOT APPLE )
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_subdirectory(windows)
|
||||
endif()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
if(APPLE)
|
||||
set(OC_OEM_SHARE_ICNS "${CMAKE_BINARY_DIR}/src/gui/${APPLICATION_ICON_NAME}.icns")
|
||||
# Contrary to popular belief, this is called like this no matter what theme/OEM.
|
||||
set(OC_OEM_SHARE_ICNS "${CMAKE_BINARY_DIR}/src/gui/ownCloud.icns")
|
||||
|
||||
# The bundle identifier and application group need to have compatible values with the client
|
||||
# to be able to open a Mach port across the extension's sandbox boundary.
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
NSMutableSet *_registeredDirectories;
|
||||
NSString *_shareMenuTitle;
|
||||
NSMutableDictionary *_strings;
|
||||
NSMutableArray *_menuItems;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -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,27 +74,13 @@
|
||||
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];
|
||||
@@ -115,43 +101,54 @@
|
||||
}
|
||||
}];
|
||||
|
||||
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"];
|
||||
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:@""];
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
- (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];
|
||||
- (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"];
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - SyncClientProxyDelegate implementation
|
||||
@@ -184,14 +181,6 @@
|
||||
[_strings setObject:value forKey:key];
|
||||
}
|
||||
|
||||
- (void)resetMenuItems
|
||||
{
|
||||
_menuItems = [[NSMutableArray alloc] init];
|
||||
}
|
||||
- (void)addMenuItem:(NSDictionary *)item {
|
||||
[_menuItems addObject:item];
|
||||
}
|
||||
|
||||
- (void)connectionDidDie
|
||||
{
|
||||
[_strings removeAllObjects];
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
- (void)registerPath:(NSString*)path;
|
||||
- (void)unregisterPath:(NSString*)path;
|
||||
- (void)setString:(NSString*)key value:(NSString*)value;
|
||||
- (void)resetMenuItems;
|
||||
- (void)addMenuItem:(NSDictionary *)item;
|
||||
- (void)connectionDidDie;
|
||||
@end
|
||||
|
||||
|
||||
@@ -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. We always only receive one line from the client.
|
||||
|
||||
// Cut the trailing newline
|
||||
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,18 +123,6 @@
|
||||
// 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]);
|
||||
}
|
||||
@@ -143,7 +131,7 @@
|
||||
- (void)askOnSocket:(NSString*)path query:(NSString*)verb
|
||||
{
|
||||
NSString *query = [NSString stringWithFormat:@"%@:%@\n", verb,path];
|
||||
|
||||
|
||||
@try {
|
||||
[_remoteEnd sendMessage:[query dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
} @catch(NSException* e) {
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
|
||||
******************************************************************************/
|
||||
|
||||
#include <KCoreAddons/KPluginFactory>
|
||||
#include <KCoreAddons/KPluginLoader>
|
||||
#include <KPluginFactory>
|
||||
#include <KPluginLoader>
|
||||
#include <KIOWidgets/kabstractfileitemactionplugin.h>
|
||||
#include <QtNetwork/QLocalSocket>
|
||||
#include <KIOCore/kfileitem.h>
|
||||
@@ -27,12 +27,10 @@
|
||||
#include <QtWidgets/QMenu>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QEventLoop>
|
||||
#include "ownclouddolphinpluginhelper.h"
|
||||
|
||||
class OwncloudDolphinPluginAction : public KAbstractFileItemActionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit OwncloudDolphinPluginAction(QObject* parent, const QList<QVariant>&)
|
||||
: KAbstractFileItemActionPlugin(parent) { }
|
||||
@@ -40,72 +38,22 @@ public:
|
||||
QList<QAction*> actions(const KFileItemListProperties& fileItemInfos, QWidget* parentWidget) Q_DECL_OVERRIDE
|
||||
{
|
||||
auto helper = OwncloudDolphinPluginHelper::instance();
|
||||
if (!helper->isConnected() || !fileItemInfos.isLocal())
|
||||
return {};
|
||||
|
||||
// If any of the url is outside of a sync folder, return an empty menu.
|
||||
const QList<QUrl> urls = fileItemInfos.urlList();
|
||||
const auto paths = helper->paths();
|
||||
QByteArray files;
|
||||
for (const auto &url : urls) {
|
||||
QDir localPath(url.toLocalFile());
|
||||
auto localFile = localPath.canonicalPath();
|
||||
if (!std::any_of(paths.begin(), paths.end(), [&](const QString &s) {
|
||||
return localFile.startsWith(s);
|
||||
}))
|
||||
return {};
|
||||
|
||||
if (!files.isEmpty())
|
||||
files += '\x1e'; // Record separator
|
||||
files += localFile.toUtf8();
|
||||
}
|
||||
|
||||
if (helper->version() < "1.1") { // in this case, lexicographic order works
|
||||
return legacyActions(fileItemInfos, parentWidget);
|
||||
}
|
||||
|
||||
auto menu = new QMenu(parentWidget);
|
||||
QEventLoop loop;
|
||||
auto con = connect(helper, &OwncloudDolphinPluginHelper::commandRecieved, this, [&](const QByteArray &cmd) {
|
||||
if (cmd.startsWith("GET_MENU_ITEMS:END")) {
|
||||
loop.quit();
|
||||
} else if (cmd.startsWith("MENU_ITEM:")) {
|
||||
auto args = QString::fromUtf8(cmd).split(QLatin1Char(':'));
|
||||
if (args.size() < 4)
|
||||
return;
|
||||
auto action = menu->addAction(args.mid(3).join(QLatin1Char(':')));
|
||||
if (args.value(2).contains(QLatin1Char('d')))
|
||||
action->setDisabled(true);
|
||||
auto call = args.value(1).toLatin1();
|
||||
connect(action, &QAction::triggered, [helper, call, files] {
|
||||
helper->sendCommand(QByteArray(call + ":" + files + "\n"));
|
||||
});
|
||||
}
|
||||
});
|
||||
QTimer::singleShot(100, &loop, SLOT(quit())); // add a timeout to be sure we don't freeze dolphin
|
||||
helper->sendCommand(QByteArray("GET_MENU_ITEMS:" + files + "\n"));
|
||||
loop.exec(QEventLoop::ExcludeUserInputEvents);
|
||||
disconnect(con);
|
||||
if (menu->actions().isEmpty()) {
|
||||
delete menu;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto menuaction = new QAction(parentWidget);
|
||||
menuaction->setText(helper->contextMenuTitle());
|
||||
menuaction->setMenu(menu);
|
||||
return { menuaction };
|
||||
}
|
||||
|
||||
|
||||
QList<QAction *> legacyActions(const KFileItemListProperties &fileItemInfos, QWidget *parentWidget)
|
||||
{
|
||||
QList<QUrl> urls = fileItemInfos.urlList();
|
||||
if (urls.count() != 1)
|
||||
if (urls.count() != 1 || !helper->isConnected())
|
||||
return {};
|
||||
QDir localPath(urls.first().toLocalFile());
|
||||
|
||||
auto url = urls.first();
|
||||
if (!url.isLocalFile())
|
||||
return {};
|
||||
QDir localPath(url.toLocalFile());
|
||||
auto localFile = localPath.canonicalPath();
|
||||
auto helper = OwncloudDolphinPluginHelper::instance();
|
||||
|
||||
const auto paths = helper->paths();
|
||||
if (!std::any_of(paths.begin(), paths.end(), [&](const QString &s) {
|
||||
return localFile.startsWith(s);
|
||||
} ))
|
||||
return {};
|
||||
|
||||
auto menuaction = new QAction(parentWidget);
|
||||
menuaction->setText(helper->contextMenuTitle());
|
||||
auto menu = new QMenu(parentWidget);
|
||||
@@ -113,8 +61,8 @@ public:
|
||||
|
||||
auto shareAction = menu->addAction(helper->shareActionTitle());
|
||||
connect(shareAction, &QAction::triggered, this, [localFile, helper] {
|
||||
helper->sendCommand(QByteArray("SHARE:" + localFile.toUtf8() + "\n"));
|
||||
});
|
||||
helper->sendCommand(QByteArray("SHARE:"+localFile.toUtf8()+"\n"));
|
||||
} );
|
||||
|
||||
if (!helper->copyPrivateLinkTitle().isEmpty()) {
|
||||
auto copyPrivateLinkAction = menu->addAction(helper->copyPrivateLinkTitle());
|
||||
@@ -129,6 +77,7 @@ public:
|
||||
helper->sendCommand(QByteArray("EMAIL_PRIVATE_LINK:" + localFile.toUtf8() + "\n"));
|
||||
});
|
||||
}
|
||||
|
||||
return { menuaction };
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include <QtNetwork/QLocalSocket>
|
||||
#include <qcoreevent.h>
|
||||
#include <QStandardPaths>
|
||||
#include <QFile>
|
||||
#include "ownclouddolphinpluginhelper.h"
|
||||
#include "config.h"
|
||||
@@ -60,7 +59,6 @@ void OwncloudDolphinPluginHelper::sendCommand(const char* data)
|
||||
|
||||
void OwncloudDolphinPluginHelper::slotConnected()
|
||||
{
|
||||
sendCommand("VERSION:\n");
|
||||
sendCommand("GET_STRINGS:\n");
|
||||
}
|
||||
|
||||
@@ -69,14 +67,12 @@ void OwncloudDolphinPluginHelper::tryConnect()
|
||||
if (_socket.state() != QLocalSocket::UnconnectedState) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString socketPath = QStandardPaths::locate(QStandardPaths::RuntimeLocation,
|
||||
APPLICATION_SHORTNAME,
|
||||
QStandardPaths::LocateDirectory);
|
||||
if(socketPath.isEmpty())
|
||||
return;
|
||||
QString runtimeDir = QFile::decodeName(qgetenv("XDG_RUNTIME_DIR"));
|
||||
runtimeDir.append( QChar('/'));
|
||||
runtimeDir.append( QLatin1String(APPLICATION_SHORTNAME) );
|
||||
|
||||
_socket.connectToServer(socketPath + QLatin1String("/socket"));
|
||||
const QString socketPath = runtimeDir + QLatin1String("/socket");
|
||||
_socket.connectToServer(socketPath);
|
||||
}
|
||||
|
||||
void OwncloudDolphinPluginHelper::slotReadyRead()
|
||||
@@ -102,16 +98,6 @@ void OwncloudDolphinPluginHelper::slotReadyRead()
|
||||
_strings[args[1]] = args.mid(2).join(QLatin1Char(':'));
|
||||
}
|
||||
continue;
|
||||
} else if (line.startsWith("VERSION:")) {
|
||||
auto args = line.split(':');
|
||||
auto version = args.value(2);
|
||||
_version = version;
|
||||
if (!version.startsWith("1.")) {
|
||||
// Incompatible version, disconnect forever
|
||||
_connectTimer.stop();
|
||||
_socket.disconnectFromServer();
|
||||
return;
|
||||
}
|
||||
}
|
||||
emit commandRecieved(line);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <QObject>
|
||||
#include <QBasicTimer>
|
||||
#include <QLocalSocket>
|
||||
#include <QRegularExpression>
|
||||
#include "ownclouddolphinpluginhelper_export.h"
|
||||
|
||||
class OWNCLOUDDOLPHINPLUGINHELPER_EXPORT OwncloudDolphinPluginHelper : public QObject {
|
||||
@@ -45,8 +44,6 @@ public:
|
||||
QString copyPrivateLinkTitle() const { return _strings["COPY_PRIVATE_LINK_MENU_TITLE"]; }
|
||||
QString emailPrivateLinkTitle() const { return _strings["EMAIL_PRIVATE_LINK_MENU_TITLE"]; }
|
||||
|
||||
QByteArray version() { return _version; }
|
||||
|
||||
signals:
|
||||
void commandRecieved(const QByteArray &cmd);
|
||||
|
||||
@@ -64,5 +61,4 @@ private:
|
||||
QBasicTimer _connectTimer;
|
||||
|
||||
QMap<QString, QString> _strings;
|
||||
QByteArray _version;
|
||||
};
|
||||
|
||||
@@ -24,7 +24,6 @@ if python3:
|
||||
import urllib.parse
|
||||
import socket
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
from gi.repository import GObject, Nautilus
|
||||
|
||||
@@ -64,9 +63,8 @@ class SocketConnect(GObject.GObject):
|
||||
self.registered_paths = {}
|
||||
self._watch_id = 0
|
||||
self._sock = None
|
||||
self._listeners = [self._update_registered_paths, self._get_version]
|
||||
self._listeners = [self._update_registered_paths]
|
||||
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.
|
||||
|
||||
@@ -103,7 +101,6 @@ class SocketConnect(GObject.GObject):
|
||||
self.connected = True
|
||||
self._watch_id = GObject.io_add_watch(self._sock, GObject.IO_IN, self._handle_notify)
|
||||
|
||||
self.sendCommand('VERSION:\n')
|
||||
self.sendCommand('GET_STRINGS:\n')
|
||||
|
||||
return False # Don't run again
|
||||
@@ -115,43 +112,29 @@ class SocketConnect(GObject.GObject):
|
||||
|
||||
return True # Run again, if enabled via timeout_add()
|
||||
|
||||
# Reads data that becomes available.
|
||||
# New responses can be accessed with get_available_responses().
|
||||
# Returns false if no data was received within timeout
|
||||
def read_socket_data_with_timeout(self, timeout):
|
||||
self._sock.settimeout(timeout)
|
||||
try:
|
||||
self._remainder += self._sock.recv(1024)
|
||||
except socket.timeout:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
finally:
|
||||
self._sock.settimeout(None)
|
||||
|
||||
# Parses response lines out of collected data, returns list of strings
|
||||
def get_available_responses(self):
|
||||
end = self._remainder.rfind(b'\n')
|
||||
if end == -1:
|
||||
return []
|
||||
data = self._remainder[:end]
|
||||
self._remainder = self._remainder[end+1:]
|
||||
return data.decode('utf-8').split('\n')
|
||||
|
||||
# Notify is the raw answer from the socket
|
||||
def _handle_notify(self, source, condition):
|
||||
# Blocking is ok since we're notified of available data
|
||||
self._remainder += self._sock.recv(1024)
|
||||
data = source.recv(1024)
|
||||
# Prepend the remaining data from last call
|
||||
if len(self._remainder) > 0:
|
||||
data = self._remainder + data
|
||||
self._remainder = ''.encode('utf-8')
|
||||
|
||||
if len(self._remainder) == 0:
|
||||
if len(data) > 0:
|
||||
# Remember the remainder for next round
|
||||
lastNL = data.rfind('\n'.encode('utf-8'));
|
||||
if lastNL > -1 and lastNL < len(data):
|
||||
self._remainder = data[lastNL+1:]
|
||||
data = data[:lastNL]
|
||||
|
||||
for l in data.split('\n'.encode('utf-8')):
|
||||
self._handle_server_response(l.decode('utf-8'))
|
||||
else:
|
||||
return False
|
||||
|
||||
for line in self.get_available_responses():
|
||||
self.handle_server_response(line)
|
||||
|
||||
return True # Run again
|
||||
|
||||
def handle_server_response(self, line):
|
||||
def _handle_server_response(self, line):
|
||||
# print("Server response: " + line)
|
||||
parts = line.split(':')
|
||||
action = parts[0]
|
||||
@@ -171,10 +154,6 @@ class SocketConnect(GObject.GObject):
|
||||
if not self.registered_paths:
|
||||
self.reconnect()
|
||||
|
||||
def _get_version(self, action, args):
|
||||
if action == 'VERSION':
|
||||
self.protocolVersion = args[1]
|
||||
|
||||
socketConnect = SocketConnect()
|
||||
|
||||
|
||||
@@ -204,88 +183,28 @@ class MenuExtension(GObject.GObject, Nautilus.MenuProvider):
|
||||
|
||||
def get_file_items(self, window, files):
|
||||
# Show the menu extension to share a file or folder
|
||||
#
|
||||
# Show if file is OK.
|
||||
# Ignore top level folders.
|
||||
# Also show extension for folders
|
||||
# if there is a OK or SYNC underneath.
|
||||
# This is only
|
||||
|
||||
# Get usable file paths from the uris
|
||||
all_internal_files = True
|
||||
for i, file_uri in enumerate(files):
|
||||
filename = get_local_path(file_uri.get_uri())
|
||||
|
||||
# Check if its a folder (ends with an /), if yes add a "/"
|
||||
# otherwise it will not find the entry in the table
|
||||
isDir = os.path.isdir(filename + os.sep)
|
||||
if isDir:
|
||||
filename += os.sep
|
||||
|
||||
# Check if toplevel folder, we need to ignore those as they cannot be shared
|
||||
topLevelFolder, internalFile = self.check_registered_paths(filename)
|
||||
if not internalFile:
|
||||
all_internal_files = False
|
||||
|
||||
files[i] = filename
|
||||
|
||||
# Don't show a context menu if some selected files aren't in a sync folder
|
||||
if not all_internal_files:
|
||||
return []
|
||||
|
||||
if socketConnect.protocolVersion >= '1.1': # lexicographic!
|
||||
return self.ask_for_menu_items(files)
|
||||
else:
|
||||
return self.legacy_menu_items(files)
|
||||
|
||||
def ask_for_menu_items(self, files):
|
||||
record_separator = '\x1e'
|
||||
filesstring = record_separator.join(files)
|
||||
socketConnect.sendCommand('GET_MENU_ITEMS:{}\n'.format(filesstring))
|
||||
|
||||
done = False
|
||||
start = time.time()
|
||||
timeout = 0.1 # 100ms
|
||||
menu_items = []
|
||||
while not done:
|
||||
dt = time.time() - start
|
||||
if dt >= timeout:
|
||||
break
|
||||
if not socketConnect.read_socket_data_with_timeout(timeout - dt):
|
||||
break
|
||||
for line in socketConnect.get_available_responses():
|
||||
# Process lines we don't care about
|
||||
if done or not (line.startswith('GET_MENU_ITEMS:') or line.startswith('MENU_ITEM:')):
|
||||
socketConnect.handle_server_response(line)
|
||||
continue
|
||||
if line == 'GET_MENU_ITEMS:END':
|
||||
done = True
|
||||
# don't break - we'd discard other responses
|
||||
if line.startswith('MENU_ITEM:'):
|
||||
args = line.split(':')
|
||||
if len(args) < 4:
|
||||
continue
|
||||
menu_items.append([args[1], 'd' not in args[2], ':'.join(args[3:])])
|
||||
|
||||
if not done:
|
||||
return self.legacy_menu_items(files)
|
||||
|
||||
if len(menu_items) == 0:
|
||||
return []
|
||||
|
||||
# Set up the 'ownCloud...' submenu
|
||||
item_owncloud = Nautilus.MenuItem(
|
||||
name='IntegrationMenu', label=self.strings.get('CONTEXT_MENU_TITLE', appname))
|
||||
menu = Nautilus.Menu()
|
||||
item_owncloud.set_submenu(menu)
|
||||
|
||||
for action, enabled, label in menu_items:
|
||||
item = Nautilus.MenuItem(name=action, label=label, sensitive=enabled)
|
||||
item.connect("activate", self.context_menu_action, action, filesstring)
|
||||
menu.append_item(item)
|
||||
|
||||
return [item_owncloud]
|
||||
|
||||
|
||||
def legacy_menu_items(self, files):
|
||||
# No legacy menu for a selection of several files
|
||||
if len(files) != 1:
|
||||
return
|
||||
file = files[0]
|
||||
|
||||
filename = get_local_path(file.get_uri())
|
||||
# Check if its a folder (ends with an /), if yes add a "/"
|
||||
# otherwise it will not find the entry in the table
|
||||
isDir = os.path.isdir(filename + os.sep)
|
||||
if isDir:
|
||||
filename += os.sep
|
||||
|
||||
# Check if toplevel folder, we need to ignore those as they cannot be shared
|
||||
topLevelFolder, internalFile = self.check_registered_paths(filename)
|
||||
if topLevelFolder or not internalFile:
|
||||
return []
|
||||
filename = files[0]
|
||||
|
||||
entry = socketConnect.nautilusVFSFile_table.get(filename)
|
||||
if not entry:
|
||||
@@ -321,7 +240,7 @@ class MenuExtension(GObject.GObject, Nautilus.MenuProvider):
|
||||
item = Nautilus.MenuItem(
|
||||
name='NautilusPython::ShareItem',
|
||||
label=self.strings.get('SHARE_MENU_TITLE', 'Share...'))
|
||||
item.connect("activate", self.context_menu_action, 'SHARE', filename)
|
||||
item.connect("activate", self.context_menu_action, 'SHARE', file)
|
||||
menu.append_item(item)
|
||||
|
||||
# Add permalink menu options, but hide these options for older clients
|
||||
@@ -329,19 +248,20 @@ class MenuExtension(GObject.GObject, Nautilus.MenuProvider):
|
||||
if 'COPY_PRIVATE_LINK_MENU_TITLE' in self.strings:
|
||||
item_copyprivatelink = Nautilus.MenuItem(
|
||||
name='CopyPrivateLink', label=self.strings.get('COPY_PRIVATE_LINK_MENU_TITLE', 'Copy private link to clipboard'))
|
||||
item_copyprivatelink.connect("activate", self.context_menu_action, 'COPY_PRIVATE_LINK', filename)
|
||||
item_copyprivatelink.connect("activate", self.context_menu_action, 'COPY_PRIVATE_LINK', file)
|
||||
menu.append_item(item_copyprivatelink)
|
||||
|
||||
if 'EMAIL_PRIVATE_LINK_MENU_TITLE' in self.strings:
|
||||
item_emailprivatelink = Nautilus.MenuItem(
|
||||
name='EmailPrivateLink', label=self.strings.get('EMAIL_PRIVATE_LINK_MENU_TITLE', 'Send private link by email...'))
|
||||
item_emailprivatelink.connect("activate", self.context_menu_action, 'EMAIL_PRIVATE_LINK', filename)
|
||||
item_emailprivatelink.connect("activate", self.context_menu_action, 'EMAIL_PRIVATE_LINK', file)
|
||||
menu.append_item(item_emailprivatelink)
|
||||
|
||||
return [item_owncloud]
|
||||
|
||||
|
||||
def context_menu_action(self, menu, action, filename):
|
||||
def context_menu_action(self, menu, action, file):
|
||||
filename = get_local_path(file.get_uri())
|
||||
# print("Context menu: " + action + ' ' + filename)
|
||||
socketConnect.sendCommand(action + ":" + filename + "\n")
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
add_subdirectory(OCContextMenu)
|
||||
add_subdirectory(OCOverlays)
|
||||
add_subdirectory(OCUtil)
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
add_library(OCContextMenu MODULE
|
||||
dllmain.cpp
|
||||
OCClientInterface.cpp
|
||||
OCContextMenu.cpp
|
||||
OCContextMenuFactory.cpp
|
||||
OCContextMenuRegHandler.cpp
|
||||
stdafx.cpp
|
||||
OCContextMenu.rc
|
||||
OCContextMenu.def
|
||||
)
|
||||
|
||||
target_link_libraries(OCContextMenu
|
||||
OCUtil)
|
||||
|
||||
install(TARGETS OCContextMenu
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -34,7 +34,7 @@ using namespace std;
|
||||
#define PIPE_TIMEOUT 5*1000 //ms
|
||||
#define SOCK_BUFFER 4096
|
||||
|
||||
OCClientInterface::ContextMenuInfo OCClientInterface::FetchInfo(const std::wstring &files)
|
||||
OCClientInterface::ContextMenuInfo OCClientInterface::FetchInfo()
|
||||
{
|
||||
auto pipename = CommunicationSocket::DefaultPipePath();
|
||||
|
||||
@@ -45,8 +45,7 @@ OCClientInterface::ContextMenuInfo OCClientInterface::FetchInfo(const std::wstri
|
||||
if (!socket.Connect(pipename)) {
|
||||
return {};
|
||||
}
|
||||
socket.SendMsg(L"GET_STRINGS:CONTEXT_MENU_TITLE\n");
|
||||
socket.SendMsg((L"GET_MENU_ITEMS:" + files + L"\n").data());
|
||||
socket.SendMsg(L"GET_STRINGS\n");
|
||||
|
||||
ContextMenuInfo info;
|
||||
std::wstring response;
|
||||
@@ -61,14 +60,16 @@ OCClientInterface::ContextMenuInfo OCClientInterface::FetchInfo(const std::wstri
|
||||
wstring stringName, stringValue;
|
||||
if (!StringUtil::extractChunks(response, stringName, stringValue))
|
||||
continue;
|
||||
if (stringName == L"CONTEXT_MENU_TITLE")
|
||||
if (stringName == L"SHARE_MENU_TITLE")
|
||||
info.shareMenuTitle = move(stringValue);
|
||||
else if (stringName == L"CONTEXT_MENU_TITLE")
|
||||
info.contextMenuTitle = move(stringValue);
|
||||
} else if (StringUtil::begins_with(response, wstring(L"MENU_ITEM:"))) {
|
||||
wstring commandName, flags, title;
|
||||
if (!StringUtil::extractChunks(response, commandName, flags, title))
|
||||
continue;
|
||||
info.menuItems.push_back({ commandName, flags, title });
|
||||
} else if (StringUtil::begins_with(response, wstring(L"GET_MENU_ITEMS:END"))) {
|
||||
else if (stringName == L"COPY_PRIVATE_LINK_MENU_TITLE")
|
||||
info.copyLinkMenuTitle = move(stringValue);
|
||||
else if (stringName == L"EMAIL_PRIVATE_LINK_MENU_TITLE")
|
||||
info.emailLinkMenuTitle = move(stringValue);
|
||||
}
|
||||
else if (StringUtil::begins_with(response, wstring(L"GET_STRINGS:END"))) {
|
||||
break; // Stop once we completely received the last sent request
|
||||
}
|
||||
}
|
||||
@@ -80,7 +81,22 @@ OCClientInterface::ContextMenuInfo OCClientInterface::FetchInfo(const std::wstri
|
||||
return info;
|
||||
}
|
||||
|
||||
void OCClientInterface::SendRequest(const wchar_t *verb, const std::wstring &path)
|
||||
void OCClientInterface::RequestShare(const std::wstring &path)
|
||||
{
|
||||
SendRequest(L"SHARE", path);
|
||||
}
|
||||
|
||||
void OCClientInterface::RequestCopyLink(const std::wstring &path)
|
||||
{
|
||||
SendRequest(L"COPY_PRIVATE_LINK", path);
|
||||
}
|
||||
|
||||
void OCClientInterface::RequestEmailLink(const std::wstring &path)
|
||||
{
|
||||
SendRequest(L"EMAIL_PRIVATE_LINK", path);
|
||||
}
|
||||
|
||||
void OCClientInterface::SendRequest(wchar_t *verb, const std::wstring &path)
|
||||
{
|
||||
auto pipename = CommunicationSocket::DefaultPipePath();
|
||||
|
||||
|
||||
@@ -46,14 +46,18 @@ public:
|
||||
struct ContextMenuInfo {
|
||||
std::vector<std::wstring> watchedDirectories;
|
||||
std::wstring contextMenuTitle;
|
||||
struct MenuItem
|
||||
{
|
||||
std::wstring command, flags, title;
|
||||
};
|
||||
std::vector<MenuItem> menuItems;
|
||||
std::wstring shareMenuTitle;
|
||||
std::wstring copyLinkMenuTitle;
|
||||
std::wstring emailLinkMenuTitle;
|
||||
};
|
||||
static ContextMenuInfo FetchInfo(const std::wstring &files);
|
||||
static void SendRequest(const wchar_t *verb, const std::wstring &path);
|
||||
static ContextMenuInfo FetchInfo();
|
||||
|
||||
static void RequestShare(const std::wstring &path);
|
||||
static void RequestCopyLink(const std::wstring &path);
|
||||
static void RequestEmailLink(const std::wstring &path);
|
||||
|
||||
private:
|
||||
static void SendRequest(wchar_t *verb, const std::wstring &path);
|
||||
};
|
||||
|
||||
#endif //ABSTRACTSOCKETHANDLER_H
|
||||
|
||||
@@ -22,8 +22,13 @@
|
||||
#include <shellapi.h>
|
||||
#include <StringUtil.h>
|
||||
|
||||
extern HINSTANCE g_hInst;
|
||||
extern long g_cDllRef;
|
||||
|
||||
#define IDM_SHARE 0
|
||||
#define IDM_COPYLINK 1
|
||||
#define IDM_EMAILLINK 2
|
||||
|
||||
OCContextMenu::OCContextMenu(void)
|
||||
: m_cRef(1)
|
||||
{
|
||||
@@ -35,6 +40,23 @@ OCContextMenu::~OCContextMenu(void)
|
||||
InterlockedDecrement(&g_cDllRef);
|
||||
}
|
||||
|
||||
|
||||
void OCContextMenu::OnVerbShare(HWND hWnd)
|
||||
{
|
||||
OCClientInterface::RequestShare(std::wstring(m_szSelectedFile));
|
||||
}
|
||||
|
||||
void OCContextMenu::OnVerbCopyLink(HWND hWnd)
|
||||
{
|
||||
OCClientInterface::RequestCopyLink(std::wstring(m_szSelectedFile));
|
||||
}
|
||||
|
||||
void OCContextMenu::OnVerbEmailLink(HWND hWnd)
|
||||
{
|
||||
OCClientInterface::RequestEmailLink(std::wstring(m_szSelectedFile));
|
||||
}
|
||||
|
||||
|
||||
#pragma region IUnknown
|
||||
|
||||
// Query to the interface the component supported.
|
||||
@@ -75,12 +97,12 @@ IFACEMETHODIMP_(ULONG) OCContextMenu::Release()
|
||||
IFACEMETHODIMP OCContextMenu::Initialize(
|
||||
LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hKeyProgID)
|
||||
{
|
||||
m_selectedFiles.clear();
|
||||
|
||||
if (!pDataObj) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
STGMEDIUM stm;
|
||||
|
||||
@@ -88,19 +110,14 @@ IFACEMETHODIMP OCContextMenu::Initialize(
|
||||
// Get an HDROP handle.
|
||||
HDROP hDrop = static_cast<HDROP>(GlobalLock(stm.hGlobal));
|
||||
if (hDrop) {
|
||||
// Ignore multi-selections
|
||||
UINT nFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
|
||||
for (int i = 0; i < nFiles; ++i) {
|
||||
if (nFiles == 1) {
|
||||
// Get the path of the file.
|
||||
wchar_t buffer[MAX_PATH];
|
||||
|
||||
if (!DragQueryFile(hDrop, i, buffer, ARRAYSIZE(buffer))) {
|
||||
m_selectedFiles.clear();
|
||||
break;
|
||||
if (0 != DragQueryFile(hDrop, 0, m_szSelectedFile, ARRAYSIZE(m_szSelectedFile)))
|
||||
{
|
||||
hr = S_OK;
|
||||
}
|
||||
|
||||
if (i)
|
||||
m_selectedFiles += L'\x1e';
|
||||
m_selectedFiles += buffer;
|
||||
}
|
||||
|
||||
GlobalUnlock(stm.hGlobal);
|
||||
@@ -111,7 +128,7 @@ IFACEMETHODIMP OCContextMenu::Initialize(
|
||||
|
||||
// If any value other than S_OK is returned from the method, the context
|
||||
// menu item is not displayed.
|
||||
return m_selectedFiles.empty() ? E_FAIL : S_OK;
|
||||
return hr;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
@@ -136,8 +153,17 @@ IFACEMETHODIMP OCContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT
|
||||
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
|
||||
}
|
||||
|
||||
m_info = OCClientInterface::FetchInfo(m_selectedFiles);
|
||||
if (m_info.menuItems.empty()) {
|
||||
OCClientInterface::ContextMenuInfo info = OCClientInterface::FetchInfo();
|
||||
bool skip = true;
|
||||
size_t selectedFileLength = wcslen(m_szSelectedFile);
|
||||
for (const std::wstring path : info.watchedDirectories) {
|
||||
if (StringUtil::isDescendantOf(m_szSelectedFile, selectedFileLength, path)) {
|
||||
skip = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skip) {
|
||||
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
|
||||
}
|
||||
|
||||
@@ -149,7 +175,7 @@ IFACEMETHODIMP OCContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT
|
||||
mii.fMask = MIIM_SUBMENU | MIIM_FTYPE | MIIM_STRING;
|
||||
mii.hSubMenu = hSubmenu;
|
||||
mii.fType = MFT_STRING;
|
||||
mii.dwTypeData = &m_info.contextMenuTitle[0];
|
||||
mii.dwTypeData = &info.contextMenuTitle[0];
|
||||
|
||||
if (!InsertMenuItem(hMenu, indexMenu++, TRUE, &mii))
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
@@ -157,59 +183,133 @@ IFACEMETHODIMP OCContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT
|
||||
InsertSeperator(hMenu, indexMenu++);
|
||||
|
||||
UINT indexSubMenu = 0;
|
||||
for (auto &item : m_info.menuItems) {
|
||||
bool disabled = item.flags.find(L'd') != std::string::npos;
|
||||
|
||||
{
|
||||
assert(!info.shareMenuTitle.empty());
|
||||
MENUITEMINFO mii = { sizeof(mii) };
|
||||
mii.fMask = MIIM_ID | MIIM_FTYPE | MIIM_STRING | MIIM_STATE;
|
||||
mii.wID = idCmdFirst + indexSubMenu;
|
||||
mii.fMask = MIIM_ID | MIIM_FTYPE | MIIM_STRING;
|
||||
mii.wID = idCmdFirst + IDM_SHARE;
|
||||
mii.fType = MFT_STRING;
|
||||
mii.dwTypeData = &item.title[0];
|
||||
mii.fState = disabled ? MFS_DISABLED : MFS_ENABLED;
|
||||
mii.dwTypeData = &info.shareMenuTitle[0];
|
||||
|
||||
if (!InsertMenuItem(hSubmenu, indexSubMenu, true, &mii))
|
||||
if (!InsertMenuItem(hSubmenu, indexSubMenu++, TRUE, &mii))
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
indexSubMenu++;
|
||||
}
|
||||
{
|
||||
assert(!info.copyLinkMenuTitle.empty());
|
||||
MENUITEMINFO mii = { sizeof(mii) };
|
||||
mii.fMask = MIIM_ID | MIIM_FTYPE | MIIM_STRING;
|
||||
mii.wID = idCmdFirst + IDM_COPYLINK;
|
||||
mii.fType = MFT_STRING;
|
||||
mii.dwTypeData = &info.copyLinkMenuTitle[0];
|
||||
|
||||
if (!InsertMenuItem(hSubmenu, indexSubMenu++, TRUE, &mii))
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
{
|
||||
assert(!info.emailLinkMenuTitle.empty());
|
||||
MENUITEMINFO mii = { sizeof(mii) };
|
||||
mii.fMask = MIIM_ID | MIIM_FTYPE | MIIM_STRING;
|
||||
mii.wID = idCmdFirst + IDM_EMAILLINK;
|
||||
mii.fType = MFT_STRING;
|
||||
mii.dwTypeData = &info.emailLinkMenuTitle[0];
|
||||
|
||||
if (!InsertMenuItem(hSubmenu, indexSubMenu++, TRUE, &mii))
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
|
||||
// Return an HRESULT value with the severity set to SEVERITY_SUCCESS.
|
||||
// Set the code value to the offset of the largest command identifier
|
||||
// that was assigned, plus one (1).
|
||||
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(indexSubMenu));
|
||||
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(IDM_EMAILLINK + 1));
|
||||
}
|
||||
|
||||
IFACEMETHODIMP OCContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
|
||||
{
|
||||
std::wstring command;
|
||||
|
||||
// For the Unicode case, if the high-order word is not zero, the
|
||||
// command's verb string is in lpcmi->lpVerbW.
|
||||
if (HIWORD(((CMINVOKECOMMANDINFOEX*)pici)->lpVerbW))
|
||||
{
|
||||
command = ((CMINVOKECOMMANDINFOEX *)pici)->lpVerbW;
|
||||
} else {
|
||||
// If the command cannot be identified through the verb string, then
|
||||
// check the identifier offset.
|
||||
|
||||
auto offset = LOWORD(pici->lpVerb);
|
||||
if (offset >= m_info.menuItems.size())
|
||||
// Is the verb supported by this context menu extension?
|
||||
if (StrCmpIW(((CMINVOKECOMMANDINFOEX*)pici)->lpVerbW, L"ocshare") == 0) {
|
||||
OnVerbShare(pici->hwnd);
|
||||
}
|
||||
else if (StrCmpIW(((CMINVOKECOMMANDINFOEX*)pici)->lpVerbW, L"occopylink") == 0) {
|
||||
OnVerbCopyLink(pici->hwnd);
|
||||
}
|
||||
else if (StrCmpIW(((CMINVOKECOMMANDINFOEX*)pici)->lpVerbW, L"ocemaillink") == 0) {
|
||||
OnVerbEmailLink(pici->hwnd);
|
||||
}
|
||||
else {
|
||||
// If the verb is not recognized by the context menu handler, it
|
||||
// must return E_FAIL to allow it to be passed on to the other
|
||||
// context menu handlers that might implement that verb.
|
||||
return E_FAIL;
|
||||
|
||||
command = m_info.menuItems[offset].command;
|
||||
}
|
||||
}
|
||||
|
||||
// If the command cannot be identified through the verb string, then
|
||||
// check the identifier offset.
|
||||
else
|
||||
{
|
||||
// Is the command identifier offset supported by this context menu
|
||||
// extension?
|
||||
if (LOWORD(pici->lpVerb) == IDM_SHARE) {
|
||||
OnVerbShare(pici->hwnd);
|
||||
}
|
||||
else if (LOWORD(pici->lpVerb) == IDM_COPYLINK) {
|
||||
OnVerbCopyLink(pici->hwnd);
|
||||
}
|
||||
else if (LOWORD(pici->lpVerb) == IDM_EMAILLINK) {
|
||||
OnVerbEmailLink(pici->hwnd);
|
||||
}
|
||||
else {
|
||||
// If the verb is not recognized by the context menu handler, it
|
||||
// must return E_FAIL to allow it to be passed on to the other
|
||||
// context menu handlers that might implement that verb.
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
OCClientInterface::SendRequest(command.data(), m_selectedFiles);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP OCContextMenu::GetCommandString(UINT_PTR idCommand,
|
||||
UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax)
|
||||
{
|
||||
if (idCommand < m_info.menuItems.size() && uFlags == GCS_VERBW) {
|
||||
return StringCchCopyW(reinterpret_cast<PWSTR>(pszName), cchMax,
|
||||
m_info.menuItems[idCommand].command.data());
|
||||
HRESULT hr = E_INVALIDARG;
|
||||
|
||||
switch (idCommand) {
|
||||
case IDM_SHARE:
|
||||
if (uFlags == GCS_VERBW) {
|
||||
// GCS_VERBW is an optional feature that enables a caller to
|
||||
// discover the canonical name for the verb passed in through
|
||||
// idCommand.
|
||||
hr = StringCchCopy(reinterpret_cast<PWSTR>(pszName), cchMax,
|
||||
L"OCShareViaOC");
|
||||
}
|
||||
break;
|
||||
case IDM_COPYLINK:
|
||||
if (uFlags == GCS_VERBW) {
|
||||
hr = StringCchCopy(reinterpret_cast<PWSTR>(pszName), cchMax,
|
||||
L"OCCopyLink");
|
||||
}
|
||||
break;
|
||||
case IDM_EMAILLINK:
|
||||
if (uFlags == GCS_VERBW) {
|
||||
hr = StringCchCopy(reinterpret_cast<PWSTR>(pszName), cchMax,
|
||||
L"OCEmailLink");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return E_INVALIDARG;
|
||||
|
||||
// If the idCommand or uFlags is not supported by this context menu
|
||||
// extension handler, return E_INVALIDARG.
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
#pragma endregion
|
||||
@@ -17,8 +17,6 @@
|
||||
|
||||
#pragma once
|
||||
#include <shlobj.h> // For IShellExtInit and IContextMenu
|
||||
#include <string>
|
||||
#include "OCClientInterface.h"
|
||||
|
||||
class OCContextMenu : public IShellExtInit, public IContextMenu
|
||||
{
|
||||
@@ -45,9 +43,21 @@ private:
|
||||
// Reference count of component.
|
||||
long m_cRef;
|
||||
|
||||
// The name of the selected files (separated by '\x1e')
|
||||
std::wstring m_selectedFiles;
|
||||
OCClientInterface::ContextMenuInfo m_info;
|
||||
// The name of the selected file.
|
||||
wchar_t m_szSelectedFile[MAX_PATH];
|
||||
|
||||
// The method that handles the "ocshare" verb.
|
||||
void OnVerbShare(HWND hWnd);
|
||||
void OnVerbCopyLink(HWND hWnd);
|
||||
void OnVerbEmailLink(HWND hWnd);
|
||||
|
||||
PWSTR m_pszMenuText;
|
||||
PCSTR m_pszVerb;
|
||||
PCWSTR m_pwszVerb;
|
||||
PCSTR m_pszVerbCanonicalName;
|
||||
PCWSTR m_pwszVerbCanonicalName;
|
||||
PCSTR m_pszVerbHelpText;
|
||||
PCWSTR m_pwszVerbHelpText;
|
||||
};
|
||||
|
||||
#endif //OCCONTEXTMENU_H
|
||||
|
||||
Binary file not shown.
@@ -1,17 +0,0 @@
|
||||
add_library(OCOverlays MODULE
|
||||
DllMain.cpp
|
||||
OCOverlay.cpp
|
||||
OCOverlayFactory.cpp
|
||||
OCOverlayRegistrationHandler.cpp
|
||||
stdafx.cpp
|
||||
OCOverlay.rc
|
||||
OCOverlays.def
|
||||
)
|
||||
|
||||
target_link_libraries(OCOverlays
|
||||
OCUtil)
|
||||
|
||||
install(TARGETS OCOverlays
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
Binary file not shown.
@@ -22,7 +22,7 @@
|
||||
#define OVERLAY_GUID_WARNING L"{0960F096-F328-48A3-B746-276B1E3C3722}"
|
||||
#define OVERLAY_GUID_WARNING_SHARED L"{0960F097-F328-48A3-B746-276B1E3C3722}"
|
||||
|
||||
#define OVERLAY_GENERIC_NAME L"ownCloud overlay handler"
|
||||
#define OVERLAY_GENERIC_NAME L"OC Overlay Handler"
|
||||
|
||||
// two spaces to put us ahead of the competition :/
|
||||
#define OVERLAY_NAME_ERROR L" OCError"
|
||||
@@ -47,4 +47,4 @@
|
||||
|
||||
#define GET_FILE_OVERLAY_ID L"getFileIconId"
|
||||
|
||||
#define PORT 34001
|
||||
#define PORT 34001
|
||||
@@ -1,17 +0,0 @@
|
||||
add_library(OCUtil SHARED
|
||||
CommunicationSocket.cpp
|
||||
FileUtil.cpp
|
||||
RegistryUtil.cpp
|
||||
RemotePathChecker.cpp
|
||||
stdafx.cpp
|
||||
StringUtil.cpp
|
||||
)
|
||||
|
||||
target_include_directories(OCUtil
|
||||
PUBLIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
install(TARGETS OCUtil
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
74
shell_integration/windows/OCUtil/OCMessage.cpp
Normal file
74
shell_integration/windows/OCUtil/OCMessage.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
#include "OCMessage.h"
|
||||
#include "ParserUtil.h"
|
||||
#include "UtilConstants.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
OCMessage::OCMessage(void)
|
||||
{
|
||||
_command = new wstring();
|
||||
_value = new wstring();
|
||||
}
|
||||
|
||||
OCMessage::~OCMessage(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool OCMessage::InitFromMessage(const wstring* message)
|
||||
{
|
||||
if(message->length() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!ParserUtil::GetItem(COMMAND, message, _command))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!ParserUtil::GetItem(VALUE, message, _value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::wstring* OCMessage::GetCommand()
|
||||
{
|
||||
return _command;
|
||||
}
|
||||
|
||||
std::wstring* OCMessage::GetValue()
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
void OCMessage::SetCommand(std::wstring* command)
|
||||
{
|
||||
_command = command;
|
||||
}
|
||||
|
||||
void OCMessage::SetValue(std::wstring* value)
|
||||
{
|
||||
_value = value;
|
||||
}
|
||||
42
shell_integration/windows/OCUtil/OCMessage.h
Normal file
42
shell_integration/windows/OCUtil/OCMessage.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
#ifndef OCMESSAGE_H
|
||||
#define OCMESSAGE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#pragma once
|
||||
|
||||
class __declspec(dllexport) OCMessage
|
||||
{
|
||||
public:
|
||||
OCMessage(void);
|
||||
~OCMessage(void);
|
||||
|
||||
bool InitFromMessage(const std::wstring*);
|
||||
|
||||
std::wstring* GetCommand();
|
||||
std::wstring* GetValue();
|
||||
|
||||
void SetCommand(std::wstring*);
|
||||
void SetValue(std::wstring*);
|
||||
|
||||
private:
|
||||
|
||||
std::wstring* _command;
|
||||
std::wstring* _value;
|
||||
};
|
||||
|
||||
#endif
|
||||
389
shell_integration/windows/OCUtil/ParserUtil.cpp
Normal file
389
shell_integration/windows/OCUtil/ParserUtil.cpp
Normal file
@@ -0,0 +1,389 @@
|
||||
/**
|
||||
* Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
#include "ParserUtil.h"
|
||||
#include "UtilConstants.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool ParserUtil::GetItem(const wchar_t* item, const wstring* message, wstring* result)
|
||||
{
|
||||
size_t start = message->find(item, 0);
|
||||
|
||||
if(start == string::npos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t end = message->find(COLON, start);
|
||||
|
||||
if(end == string::npos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//Move to next character after :
|
||||
end += 1;
|
||||
|
||||
wchar_t c = message->at(end);
|
||||
|
||||
//Move to the next character, which is the start of the value
|
||||
end += 1;
|
||||
|
||||
if(c == '[')
|
||||
{
|
||||
return GetList(end - 1, message, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetValue(end, message, result);
|
||||
}
|
||||
}
|
||||
|
||||
bool ParserUtil::GetList(size_t start, const wstring* message, wstring* result)
|
||||
{
|
||||
size_t end = start + 1;
|
||||
|
||||
int openBraceCount = 1;
|
||||
|
||||
while(openBraceCount > 0)
|
||||
{
|
||||
size_t closeBraceLocation = message->find(CLOSE_BRACE, end);
|
||||
size_t openBraceLocation = message->find(OPEN_BRACE, end);
|
||||
|
||||
if(closeBraceLocation < openBraceLocation)
|
||||
{
|
||||
openBraceCount--;
|
||||
end = closeBraceLocation + 1;
|
||||
}
|
||||
else if(openBraceLocation < closeBraceLocation)
|
||||
{
|
||||
openBraceCount++;
|
||||
end = openBraceLocation + 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
size_t length = end - start;
|
||||
|
||||
return GetString(start, end, message, result);
|
||||
}
|
||||
|
||||
size_t ParserUtil::GetNextStringItemInList(const wstring* message, size_t start, wstring* result)
|
||||
{
|
||||
size_t end = string::npos;
|
||||
size_t commaLocation = message->find(COMMA, start);
|
||||
|
||||
if(commaLocation == string::npos)
|
||||
{
|
||||
end = message->find(CLOSE_BRACE, start);
|
||||
if(end == string::npos)
|
||||
{
|
||||
end = message->length();
|
||||
}
|
||||
else
|
||||
{
|
||||
end = end - 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
end = commaLocation - 1;
|
||||
}
|
||||
|
||||
if(!GetString(start + 2, end, message, result))
|
||||
{
|
||||
return string::npos;
|
||||
}
|
||||
|
||||
return end + 2;
|
||||
}
|
||||
|
||||
size_t ParserUtil::GetNextOCItemInList(const wstring* message, size_t start, wstring* result)
|
||||
{
|
||||
size_t end = message->find(OPEN_CURLY_BRACE, start) + 1;
|
||||
|
||||
int openBraceCount = 1;
|
||||
|
||||
while(openBraceCount > 0)
|
||||
{
|
||||
size_t closeBraceLocation = message->find(CLOSE_CURLY_BRACE, end);
|
||||
size_t openBraceLocation = message->find(OPEN_CURLY_BRACE, end);
|
||||
|
||||
if(closeBraceLocation < openBraceLocation)
|
||||
{
|
||||
openBraceCount--;
|
||||
end = closeBraceLocation + 1;
|
||||
}
|
||||
else if(openBraceLocation < closeBraceLocation)
|
||||
{
|
||||
openBraceCount++;
|
||||
end = openBraceLocation + 1;
|
||||
}
|
||||
}
|
||||
|
||||
size_t length = end - start;
|
||||
|
||||
if(!GetString(start, end, message, result))
|
||||
{
|
||||
return string::npos;
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
bool ParserUtil::GetValue(size_t start, const wstring* message, wstring* result)
|
||||
{
|
||||
if(message->at(start - 1) == '\"')
|
||||
{
|
||||
size_t end = message->find(QUOTE, start);
|
||||
return GetString(start, end, message, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
start = start - 1;
|
||||
|
||||
size_t end = message->find(COMMA, start);
|
||||
|
||||
result->append(message->substr(start, end-start));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParserUtil::GetString(size_t start, size_t end, const wstring* message, wstring* result)
|
||||
{
|
||||
if(end == string::npos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t length = end - start;
|
||||
|
||||
if(length > 0)
|
||||
{
|
||||
result->append(message->substr(start, length));
|
||||
}
|
||||
else
|
||||
{
|
||||
result->append(L"");
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParserUtil::IsList(wstring* message)
|
||||
{
|
||||
wchar_t c = message->at(0);
|
||||
|
||||
if(c == '[')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ParserUtil::ParseJsonList(wstring* message, vector<wstring*>* items)
|
||||
{
|
||||
|
||||
size_t currentLocation = message->find(OPEN_BRACE, 0);
|
||||
|
||||
while(currentLocation < message->size())
|
||||
{
|
||||
wstring* item = new wstring();
|
||||
|
||||
currentLocation = ParserUtil::GetNextStringItemInList(message, currentLocation, item);
|
||||
|
||||
if(currentLocation == string::npos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
items->push_back(item);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParserUtil::ParseOCList(wstring* message, vector<wstring*>* items)
|
||||
{
|
||||
|
||||
size_t currentLocation = message->find(OPEN_CURLY_BRACE, 0);
|
||||
|
||||
while(currentLocation < message->size())
|
||||
{
|
||||
wstring* item = new wstring();
|
||||
|
||||
currentLocation = ParserUtil::GetNextOCItemInList(message, currentLocation, item);
|
||||
|
||||
if(currentLocation == string::npos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
items->push_back(item);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParserUtil::ParseOCMessageList(wstring* message, vector<OCMessage*>* messages)
|
||||
{
|
||||
vector<wstring*>* items = new vector<wstring*>();
|
||||
|
||||
if(!ParseOCList(message, items))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for(vector<wstring*>::iterator it = items->begin(); it != items->end(); it++)
|
||||
{
|
||||
wstring* temp = *it;
|
||||
|
||||
OCMessage* message = new OCMessage();
|
||||
message->InitFromMessage(temp);
|
||||
|
||||
messages->push_back(message);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParserUtil::SerializeList(std::vector<std::wstring>* list, std::wstring* result, bool escapeQuotes)
|
||||
{
|
||||
if(result == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
result->append(OPEN_BRACE);
|
||||
|
||||
for(vector<wstring>::iterator it = list->begin(); it != list->end(); it++)
|
||||
{
|
||||
wstring value = *it;
|
||||
|
||||
if(escapeQuotes)
|
||||
{
|
||||
result->append(BACK_SLASH);
|
||||
}
|
||||
|
||||
result->append(QUOTE);
|
||||
result->append(value.c_str());
|
||||
|
||||
if(escapeQuotes)
|
||||
{
|
||||
result->append(BACK_SLASH);
|
||||
}
|
||||
|
||||
result->append(QUOTE);
|
||||
result->append(COMMA);
|
||||
}
|
||||
|
||||
//Erase last comma
|
||||
result->erase(result->size() - 1, 1);
|
||||
|
||||
result->append(CLOSE_BRACE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParserUtil::SerializeMessage(std::map<std::wstring*, std::wstring*>* arguments, std::wstring* result, bool escapeQuotes)
|
||||
{
|
||||
if(result == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
result->append(OPEN_CURLY_BRACE);
|
||||
|
||||
for(map<wstring*, wstring*>::iterator it = arguments->begin(); it != arguments->end(); it++)
|
||||
{
|
||||
wstring key = *it->first;
|
||||
wstring value = *it->second;
|
||||
|
||||
if(escapeQuotes)
|
||||
{
|
||||
result->append(BACK_SLASH);
|
||||
}
|
||||
|
||||
result->append(QUOTE);
|
||||
result->append(key.c_str());
|
||||
|
||||
if(escapeQuotes)
|
||||
{
|
||||
result->append(BACK_SLASH);
|
||||
}
|
||||
|
||||
result->append(QUOTE);
|
||||
result->append(COLON);
|
||||
result->append(value.c_str());
|
||||
result->append(COMMA);
|
||||
}
|
||||
|
||||
//Erase last comma
|
||||
result->erase(result->size() - 1, 1);
|
||||
|
||||
result->append(CLOSE_CURLY_BRACE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParserUtil::SerializeMessage(OCMessage* OCMessage, std::wstring* result)
|
||||
{
|
||||
if(result == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
result->append(OPEN_CURLY_BRACE);
|
||||
|
||||
result->append(QUOTE);
|
||||
result->append(COMMAND);
|
||||
result->append(QUOTE);
|
||||
|
||||
result->append(COLON);
|
||||
|
||||
result->append(QUOTE);
|
||||
result->append(OCMessage->GetCommand()->c_str());
|
||||
result->append(QUOTE);
|
||||
|
||||
result->append(COMMA);
|
||||
|
||||
result->append(QUOTE);
|
||||
result->append(VALUE);
|
||||
result->append(QUOTE);
|
||||
|
||||
result->append(COLON);
|
||||
|
||||
if(!IsList(OCMessage->GetValue()))
|
||||
{
|
||||
result->append(QUOTE);
|
||||
}
|
||||
|
||||
result->append(OCMessage->GetValue()->c_str());
|
||||
|
||||
if(!IsList(OCMessage->GetValue()))
|
||||
{
|
||||
result->append(QUOTE);
|
||||
}
|
||||
|
||||
result->append(CLOSE_CURLY_BRACE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -61,30 +61,6 @@ public:
|
||||
thirdChunk = source.substr(statusEnd + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool extractChunks(const std::wstring &source, std::wstring &secondChunk, std::wstring &thirdChunk, std::wstring &forthChunk)
|
||||
{
|
||||
auto statusBegin = source.find(L':', 0);
|
||||
assert(statusBegin != std::wstring::npos);
|
||||
|
||||
auto statusEnd = source.find(L':', statusBegin + 1);
|
||||
if (statusEnd == std::wstring::npos) {
|
||||
// the command do not contains two colon?
|
||||
return false;
|
||||
}
|
||||
|
||||
auto thirdColon = source.find(L':', statusEnd + 1);
|
||||
if (statusEnd == std::wstring::npos) {
|
||||
// the command do not contains three colon?
|
||||
return false;
|
||||
}
|
||||
|
||||
// Assume the caller extracted the chunk before the first colon.
|
||||
secondChunk = source.substr(statusBegin + 1, statusEnd - statusBegin - 1);
|
||||
thirdChunk = source.substr(statusEnd + 1, thirdColon - statusEnd - 1);
|
||||
forthChunk = source.substr(thirdColon + 1);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // STRINGUTIL_H
|
||||
|
||||
2
src/3rdparty/libcrashreporter-qt
vendored
2
src/3rdparty/libcrashreporter-qt
vendored
Submodule src/3rdparty/libcrashreporter-qt updated: 3f92d83acf...e8fffe61e7
12301
src/3rdparty/sqlite3/sqlite3.c
vendored
12301
src/3rdparty/sqlite3/sqlite3.c
vendored
File diff suppressed because it is too large
Load Diff
658
src/3rdparty/sqlite3/sqlite3.h
vendored
658
src/3rdparty/sqlite3/sqlite3.h
vendored
File diff suppressed because it is too large
Load Diff
@@ -4,16 +4,11 @@ endif()
|
||||
|
||||
set(synclib_NAME ${APPLICATION_EXECUTABLE}sync)
|
||||
|
||||
find_package(Qt5 5.6 COMPONENTS Core Network Xml Concurrent REQUIRED)
|
||||
if (Qt5Core_VERSION VERSION_LESS 5.9.0)
|
||||
message(STATUS "For HTTP/2 support, compile with Qt 5.9 or higher.")
|
||||
endif()
|
||||
|
||||
if(NOT TOKEN_AUTH_ONLY)
|
||||
find_package(Qt5Keychain REQUIRED)
|
||||
endif()
|
||||
|
||||
if(NOT MSVC)
|
||||
if(NOT WIN32)
|
||||
if(NOT (CMAKE_SYSTEM_PROCESSOR MATCHES "^(alpha|parisc|hppa)"))
|
||||
if((CMAKE_CXX_COMPILER_ID MATCHES "GNU") AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9))
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector --param=ssp-buffer-size=4")
|
||||
|
||||
@@ -7,7 +7,17 @@ set(cmd_SRC
|
||||
simplesslerrorhandler.cpp
|
||||
netrcparser.cpp
|
||||
)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src/libsync
|
||||
${CMAKE_BINARY_DIR}/src/libsync
|
||||
)
|
||||
|
||||
# csync is required.
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src/csync
|
||||
${CMAKE_BINARY_DIR}/src/csync
|
||||
)
|
||||
|
||||
# Need tokenizer for netrc parser
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src/3rdparty/qtokenizer)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE")
|
||||
@@ -17,15 +27,13 @@ endif()
|
||||
|
||||
if(NOT BUILD_LIBRARIES_ONLY)
|
||||
add_executable(${cmd_NAME} ${cmd_SRC})
|
||||
qt5_use_modules(${cmd_NAME} Network )
|
||||
set_target_properties(${cmd_NAME} PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY} )
|
||||
set_target_properties(${cmd_NAME} PROPERTIES
|
||||
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/${APPLICATION_EXECUTABLE};${CMAKE_INSTALL_RPATH}" )
|
||||
|
||||
target_link_libraries(${cmd_NAME} ocsync ${synclib_NAME} Qt5::Core Qt5::Network)
|
||||
|
||||
# Need tokenizer for netrc parser
|
||||
target_include_directories(${cmd_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/src/3rdparty/qtokenizer)
|
||||
target_link_libraries(${cmd_NAME} ${synclib_NAME})
|
||||
endif()
|
||||
|
||||
if(BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||
@@ -37,6 +45,7 @@ elseif(NOT BUILD_LIBRARIES_ONLY)
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
|
||||
|
||||
# FIXME: The following lines are dup in src/gui and src/cmd because it needs to be done after both are installed
|
||||
#FIXME: find a nice solution to make the second if(BUILD_OWNCLOUD_OSX_BUNDLE) unnecessary
|
||||
# currently it needs to be done because the code right above needs to be executed no matter
|
||||
|
||||
@@ -23,16 +23,17 @@
|
||||
#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"
|
||||
|
||||
@@ -52,7 +53,7 @@
|
||||
using namespace OCC;
|
||||
|
||||
|
||||
static void nullMessageHandler(QtMsgType, const QMessageLogContext &, const QString &)
|
||||
static void nullMessageHandler(QtMsgType, const char *)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -82,6 +83,8 @@ 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:
|
||||
@@ -324,11 +327,13 @@ int main(int argc, char **argv)
|
||||
options.restartTimes = 3;
|
||||
options.uplimit = 0;
|
||||
options.downlimit = 0;
|
||||
ClientProxy clientProxy;
|
||||
|
||||
parseOptions(app.arguments(), &options);
|
||||
|
||||
csync_set_log_level(options.silent ? 1 : 11);
|
||||
if (options.silent) {
|
||||
qInstallMessageHandler(nullMessageHandler);
|
||||
qInstallMsgHandler(nullMessageHandler);
|
||||
} else {
|
||||
qSetMessagePattern("%{time MM-dd hh:mm:ss:zzz} [ %{type} %{category} ]%{if-debug}\t[ %{function} ]%{endif}:\t%{message}");
|
||||
}
|
||||
@@ -435,6 +440,8 @@ 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;
|
||||
@@ -457,6 +464,7 @@ int main(int argc, char **argv)
|
||||
|
||||
QEventLoop loop;
|
||||
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;
|
||||
@@ -528,7 +536,7 @@ restart_sync:
|
||||
engine.excludedFiles().addExcludeFilePath(systemExcludeFile);
|
||||
}
|
||||
|
||||
if (!engine.excludedFiles().reloadExcludeFiles()) {
|
||||
if (!engine.excludedFiles().reloadExcludes()) {
|
||||
qFatal("Cannot load system exclude list or list supplied via --exclude");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
#include "configfile.h"
|
||||
#include "common/utility.h"
|
||||
#include "account.h"
|
||||
#include "simplesslerrorhandler.h"
|
||||
|
||||
@@ -207,7 +207,6 @@ static inline uint64_t c_jhash64(const uint8_t *k, uint64_t length, uint64_t int
|
||||
/* handle the last 23 bytes */
|
||||
c += length;
|
||||
switch(len) {
|
||||
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
||||
case 23: c+=((uint64_t)k[22]<<56);
|
||||
case 22: c+=((uint64_t)k[21]<<48);
|
||||
case 21: c+=((uint64_t)k[20]<<40);
|
||||
|
||||
@@ -19,11 +19,8 @@
|
||||
#include "filesystembase.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QUrl>
|
||||
#include <QFile>
|
||||
#include <QCryptographicHash>
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
@@ -406,6 +403,27 @@ QByteArray FileSystem::calcAdler32(const QString &filename)
|
||||
}
|
||||
#endif
|
||||
|
||||
QString FileSystem::makeConflictFileName(const QString &fn, const QDateTime &dt)
|
||||
{
|
||||
QString conflictFileName(fn);
|
||||
// Add _conflict-XXXX 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");
|
||||
|
||||
// Additional marker
|
||||
QByteArray conflictFileUserName = qgetenv("CSYNC_CONFLICT_FILE_USERNAME");
|
||||
if (conflictFileUserName.isEmpty())
|
||||
conflictFileName.insert(dotLocation, "_conflict-" + timeString);
|
||||
else
|
||||
conflictFileName.insert(dotLocation, "_conflict_" + QString::fromUtf8(conflictFileUserName) + "-" + timeString);
|
||||
|
||||
return conflictFileName;
|
||||
}
|
||||
|
||||
bool FileSystem::remove(const QString &fileName, QString *errorString)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
@@ -425,83 +443,6 @@ 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
|
||||
|
||||
@@ -109,11 +109,6 @@ 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,6 +131,11 @@ namespace FileSystem {
|
||||
QByteArray OCSYNC_EXPORT calcAdler32(const QString &fileName);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns a file name based on \a fn that's suitable for a conflict.
|
||||
*/
|
||||
QString OCSYNC_EXPORT makeConflictFileName(const QString &fn, const QDateTime &dt);
|
||||
|
||||
/**
|
||||
* Returns true when a file is locked. (Windows only)
|
||||
*/
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "ownsql.h"
|
||||
#include "common/utility.h"
|
||||
#include "common/asserts.h"
|
||||
#include <sqlite3.h>
|
||||
|
||||
#define SQLITE_SLEEP_TIME_USEC 100000
|
||||
#define SQLITE_REPEAT_COUNT 20
|
||||
@@ -49,12 +48,6 @@ SqlDatabase::SqlDatabase()
|
||||
{
|
||||
}
|
||||
|
||||
SqlDatabase::~SqlDatabase()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
bool SqlDatabase::isOpen()
|
||||
{
|
||||
return _db != 0;
|
||||
@@ -190,9 +183,6 @@ 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;
|
||||
@@ -226,8 +216,9 @@ sqlite3 *SqlDatabase::sqliteDb()
|
||||
/* =========================================================================================== */
|
||||
|
||||
SqlQuery::SqlQuery(SqlDatabase &db)
|
||||
: _sqldb(&db)
|
||||
, _db(db.sqliteDb())
|
||||
: _db(db.sqliteDb())
|
||||
, _stmt(0)
|
||||
, _errId(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -238,16 +229,18 @@ SqlQuery::~SqlQuery()
|
||||
}
|
||||
}
|
||||
|
||||
SqlQuery::SqlQuery(const QByteArray &sql, SqlDatabase &db)
|
||||
: _sqldb(&db)
|
||||
, _db(db.sqliteDb())
|
||||
SqlQuery::SqlQuery(const QString &sql, SqlDatabase &db)
|
||||
: _db(db.sqliteDb())
|
||||
, _stmt(0)
|
||||
, _errId(0)
|
||||
{
|
||||
prepare(sql);
|
||||
}
|
||||
|
||||
int SqlQuery::prepare(const QByteArray &sql, bool allow_failure)
|
||||
int SqlQuery::prepare(const QString &sql, bool allow_failure)
|
||||
{
|
||||
_sql = sql.trimmed();
|
||||
QString s(sql);
|
||||
_sql = s.trimmed();
|
||||
if (_stmt) {
|
||||
finish();
|
||||
}
|
||||
@@ -255,7 +248,7 @@ int SqlQuery::prepare(const QByteArray &sql, bool allow_failure)
|
||||
int n = 0;
|
||||
int rc;
|
||||
do {
|
||||
rc = sqlite3_prepare_v2(_db, _sql.constData(), -1, &_stmt, 0);
|
||||
rc = sqlite3_prepare_v2(_db, _sql.toUtf8().constData(), -1, &_stmt, 0);
|
||||
if ((rc == SQLITE_BUSY) || (rc == SQLITE_LOCKED)) {
|
||||
n++;
|
||||
OCC::Utility::usleep(SQLITE_SLEEP_TIME_USEC);
|
||||
@@ -267,32 +260,19 @@ int SqlQuery::prepare(const QByteArray &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 startsWithInsensitive(_sql, "SELECT");
|
||||
return (!_sql.isEmpty() && _sql.startsWith("SELECT", Qt::CaseInsensitive));
|
||||
}
|
||||
|
||||
bool SqlQuery::isPragma()
|
||||
{
|
||||
return startsWithInsensitive(_sql, "PRAGMA");
|
||||
return (!_sql.isEmpty() && _sql.startsWith("PRAGMA", Qt::CaseInsensitive));
|
||||
}
|
||||
|
||||
bool SqlQuery::exec()
|
||||
@@ -459,13 +439,8 @@ 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()
|
||||
@@ -476,18 +451,4 @@ 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
|
||||
|
||||
@@ -19,19 +19,15 @@
|
||||
#ifndef OWNSQL_H
|
||||
#define OWNSQL_H
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
#include <QSet>
|
||||
|
||||
#include "ocsynclib.h"
|
||||
|
||||
struct sqlite3;
|
||||
struct sqlite3_stmt;
|
||||
|
||||
namespace OCC {
|
||||
|
||||
class SqlQuery;
|
||||
|
||||
/**
|
||||
* @brief The SqlDatabase class
|
||||
* @ingroup libsync
|
||||
@@ -41,7 +37,6 @@ class OCSYNC_EXPORT SqlDatabase
|
||||
Q_DISABLE_COPY(SqlDatabase)
|
||||
public:
|
||||
explicit SqlDatabase();
|
||||
~SqlDatabase();
|
||||
|
||||
bool isOpen();
|
||||
bool openOrCreateReadWrite(const QString &filename);
|
||||
@@ -66,54 +61,18 @@ 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 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);
|
||||
explicit SqlQuery(const QString &sql, SqlDatabase &db);
|
||||
|
||||
~SqlQuery();
|
||||
QString error() const;
|
||||
@@ -122,13 +81,16 @@ 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;
|
||||
@@ -137,12 +99,11 @@ public:
|
||||
void finish();
|
||||
|
||||
private:
|
||||
SqlDatabase *_sqldb = nullptr;
|
||||
sqlite3 *_db = nullptr;
|
||||
sqlite3_stmt *_stmt = nullptr;
|
||||
sqlite3 *_db;
|
||||
sqlite3_stmt *_stmt;
|
||||
QString _error;
|
||||
int _errId;
|
||||
QByteArray _sql;
|
||||
QString _sql;
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -112,13 +112,6 @@ public:
|
||||
qint64 _modtime;
|
||||
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
|
||||
@@ -176,18 +169,10 @@ public:
|
||||
* Since folders in the selective sync list will not be rediscovered (csync_ftw,
|
||||
* _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.
|
||||
*
|
||||
@@ -222,22 +207,6 @@ public:
|
||||
void setDataFingerprint(const QByteArray &dataFingerprint);
|
||||
QByteArray dataFingerprint();
|
||||
|
||||
|
||||
// Conflict record functions
|
||||
|
||||
/// Store a new or updated record in the database
|
||||
void setConflictRecord(const ConflictRecord &record);
|
||||
|
||||
/// 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 file with the conflict tag
|
||||
void deleteConflictRecord(const QByteArray &path);
|
||||
|
||||
/// Return all paths of files with a conflict tag in the name and records in the db
|
||||
QByteArrayList conflictRecordPaths();
|
||||
|
||||
|
||||
/**
|
||||
* Delete any file entry. This will force the next sync to re-sync everything as if it was new,
|
||||
* restoring everyfile on every remote. If a file is there both on the client and server side,
|
||||
@@ -245,12 +214,6 @@ public:
|
||||
*/
|
||||
void clearFileTable();
|
||||
|
||||
/**
|
||||
* Set the 'ItemTypeVirtualFileDownload' to all the files that have the ItemTypeVirtualFile flag
|
||||
* within the directory specified path path
|
||||
*/
|
||||
void markVirtualFileForDownloadRecursively(const QByteArray &path);
|
||||
|
||||
private:
|
||||
int getFileRecordCount();
|
||||
bool updateDatabaseStructure();
|
||||
@@ -260,7 +223,7 @@ private:
|
||||
void commitInternal(const QString &context, bool startTrans = true);
|
||||
void startTransaction();
|
||||
void commitTransaction();
|
||||
QVector<QByteArray> tableColumns(const QByteArray &table);
|
||||
QStringList tableColumns(const QString &table);
|
||||
bool checkConnect();
|
||||
|
||||
// Same as forceRemoteDiscoveryNextSync but without acquiring the lock
|
||||
@@ -277,56 +240,46 @@ private:
|
||||
int _transaction;
|
||||
bool _metadataTableIsEmpty;
|
||||
|
||||
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;
|
||||
// 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> _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;
|
||||
|
||||
/* 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).
|
||||
/* 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
|
||||
*
|
||||
* The contained paths have a trailing /.
|
||||
*/
|
||||
QList<QByteArray> _etagStorageFilter;
|
||||
QList<QByteArray> _avoidReadFromDbOnNextSyncFilter;
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
QByteArray _journalMode;
|
||||
QString _journalMode;
|
||||
};
|
||||
|
||||
bool OCSYNC_EXPORT
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace OCC {
|
||||
|
||||
SyncJournalFileRecord::SyncJournalFileRecord()
|
||||
: _inode(0)
|
||||
, _type(ItemTypeSkip)
|
||||
, _type(0)
|
||||
, _fileSize(0)
|
||||
, _serverHasIgnoredFiles(false)
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user